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/02 07:58:27 UTC

svn commit: r1098489 [1/3] - in /tuscany/sca-cpp/trunk: ./ modules/edit/ modules/edit/htdocs/ modules/edit/htdocs/app/ modules/edit/htdocs/clone/ modules/edit/htdocs/create/ modules/edit/htdocs/dash/ modules/edit/htdocs/data/ modules/edit/htdocs/graph/...

Author: jsdelfino
Date: Mon May  2 05:58:26 2011
New Revision: 1098489

URL: http://svn.apache.org/viewvc?rev=1098489&view=rev
Log:
Simplify HTML and Javascript to improve UI and performance on iOS devices. Fix offline cache manifest. Add an app clone page.

Added:
    tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/
    tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/create/
    tuscany/sca-cpp/trunk/modules/edit/htdocs/create/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/menu.js
    tuscany/sca-cpp/trunk/modules/edit/htdocs/public/delete.png
    tuscany/sca-cpp/trunk/modules/edit/htdocs/public/delete.xcf
    tuscany/sca-cpp/trunk/modules/edit/htdocs/stats/
    tuscany/sca-cpp/trunk/modules/edit/htdocs/stats/index.html
    tuscany/sca-cpp/trunk/modules/js/htdocs/all-min.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/ui-min.css
Removed:
    tuscany/sca-cpp/trunk/modules/edit/htdocs/dash/
    tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/graph.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/main.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/menu.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/page/page.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/props/
    tuscany/sca-cpp/trunk/modules/edit/htdocs/store/store.html
Modified:
    tuscany/sca-cpp/trunk/.gitignore
    tuscany/sca-cpp/trunk/modules/edit/Makefile.am
    tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf
    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/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/public/iframe.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/public/notauth.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/public/notfound.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/public/notyet.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/public/oops.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/store/index.html
    tuscany/sca-cpp/trunk/modules/edit/mkapplinks
    tuscany/sca-cpp/trunk/modules/edit/ssl-start
    tuscany/sca-cpp/trunk/modules/edit/start
    tuscany/sca-cpp/trunk/modules/js/Makefile.am
    tuscany/sca-cpp/trunk/modules/js/htdocs/ui.css
    tuscany/sca-cpp/trunk/modules/js/htdocs/ui.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/uicyan.css
    tuscany/sca-cpp/trunk/modules/server/server-conf

Modified: tuscany/sca-cpp/trunk/.gitignore
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/.gitignore?rev=1098489&r1=1098488&r2=1098489&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/.gitignore (original)
+++ tuscany/sca-cpp/trunk/.gitignore Mon May  2 05:58:26 2011
@@ -56,6 +56,7 @@ config.guess
 config.sub
 config.status
 config.js
+all.js
 depcomp
 install-sh
 ltmain.sh
@@ -85,6 +86,8 @@ doxygen
 *.stamp
 *.jar
 *.prefix
+*.crt
+*.patch
 index.yaml
 core
 gen-cpp/
@@ -133,7 +136,6 @@ json-value
 value-json
 element-value
 value-element
-modules/edit/apps/*/htdocs
 modules/edit/apps/*/nuvem
 modules/edit/apps/*/lib
 chat-send

Modified: tuscany/sca-cpp/trunk/modules/edit/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/Makefile.am?rev=1098489&r1=1098488&r2=1098489&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/modules/edit/Makefile.am Mon May  2 05:58:26 2011
@@ -20,7 +20,7 @@ if WANT_PYTHON
 moddir = $(prefix)/modules/edit
 dist_mod_SCRIPTS = start stop ssl-start mkapplinks
 
-nobase_dist_mod_DATA = edit.composite *.py htdocs/*.html htdocs/dash/*.html htdocs/data/*.html htdocs/app/*.html htdocs/store/*.html htdocs/props/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html palettes/*/palette.composite apps/*/app.composite apps/*/app.html dashboards/* store/*
-EXTRA_DIST = edit.composite *.py htdocs/*.html htdocs/dash/*.html htdocs/data/*.html htdocs/app/*.html htdocs/store/*.html htdocs/props/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html palettes/*/palette.composite apps/*/app.composite apps/*/app.html dashboards/* store/*
+nobase_dist_mod_DATA = edit.composite *.py htdocs/*.html htdocs/*.js htdocs/create/*.html htdocs/data/*.html htdocs/app/*.html htdocs/store/*.html htdocs/stats/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html palettes/*/palette.composite apps/*/app.composite apps/*/htdocs/app.html dashboards/* store/*
+EXTRA_DIST = edit.composite *.py htdocs/*.html htdocs/*.js htdocs/create/*.html htdocs/data/*.html htdocs/app/*.html htdocs/store/*.html htdocs/stats/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html palettes/*/palette.composite apps/*/app.composite apps/*/htdocs/app.html dashboards/* store/*
 
 endif

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf?rev=1098489&r1=1098488&r2=1098489&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf Mon May  2 05:58:26 2011
@@ -1,26 +1,16 @@
-CACHE-MANIFEST
+CACHE MANIFEST
 
 # Common resources
-atomutil.js
-component.js
-elemutil.js
-jsconfig.js
-jsonutil.js
-scdl.js
-ui.css
-ui.js
-util.js
-xmlutil.js
+all-min.js
+config.js
+ui-min.css
 
 # App resources
 app.html
 data/index.html
-index.html
 favicon.ico
-login/index.html
-logout/index.html
+index.html
 public/app.png
-public/grid72.png
 public/iframe.html
 public/img.png
 public/notauth.html
@@ -30,3 +20,6 @@ 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=1098489&r1=1098488&r2=1098489&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  2 05:58:26 2011
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -16,7 +17,7 @@
  * specific language governing permissions and limitations
  * under the License.    
 -->
-<html manifest="cache-manifest.cmf">
+<html manifest="/cache-manifest.cmf">
 <head>
 <title>App</title>
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
@@ -26,20 +27,13 @@
 document.title = window.location.hostname.split('.')[0];
 </script>
 <link rel="apple-touch-icon" href="/public/touchicon.png"/>
-<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <script type="text/javascript" src="/config.js"></script>
-<script type="text/javascript" src="/util.js"></script>
-<script type="text/javascript" src="/elemutil.js"></script>
-<script type="text/javascript" src="/xmlutil.js"></script>
-<script type="text/javascript" src="/atomutil.js"></script>
-<script type="text/javascript" src="/jsonutil.js"></script>
-<script type="text/javascript" src="/scdl.js"></script>
-<script type="text/javascript" src="/ui.js"></script>
-<script type="text/javascript" src="/component.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 </head>
-<body class="delayed">
+<body class="delayed" onorientationchange="ui.reload();">
 
-<div id="bodydiv" style="position: absolute; top: 0px; left: 0px; right: 0px;">
+<div id="bodydiv" class="devicewidth">
 
 <div id="app"></div>
 
@@ -51,11 +45,11 @@ document.title = window.location.hostnam
 if (ui.isIE()) $('bodydiv').style.right = -20;
 
 /**
- * Page, every and location components.
+ * Start, stop, timer and geolocation components.
  */
-var appstartcomp = sca.httpclient('appstart', '/appstart');
-var appstopcomp = sca.httpclient('appstop', '/appstop');
-var everycomp = sca.httpclient('every', '/every');
+var startcomp = sca.httpclient('start', '/start');
+var stopcomp = sca.httpclient('stop', '/stop');
+var timercomp = sca.httpclient('timer', '/timer');
 var geolocationcomp = sca.httpclient('geolocation', '/geolocation');
 
 /**
@@ -255,11 +249,13 @@ function fixupwidget(e) {
     }
     if (e.className == 'list') {
         car(childElements(e)).innerHTML = '';
+        e.style.width = '100%';
         car(childElements(e)).style.width = '100%';
         return e;
     }
     if (e.className == 'table') {
         car(childElements(e)).innerHTML = '';
+        e.style.width = '100%';
         car(childElements(e)).style.width = '100%';
         return e;
     }
@@ -300,26 +296,24 @@ function getpagedata() {
         }
 
         // Get the component app data
-        var doc = appstartcomp.get(window.location.search, function(doc) {
-            try {
-                $('app').innerHTML = $('appFrame').contentDocument.body.innerHTML;
-
-                // Initial setup of the widgets
-                map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID($('app'), 'page').childNodes)));
-
-                // Display data on the page
-                displaypage(doc);
-
-                // Get and eval the optional timer and location watch setup scripts
-                everycomp.get('setup', evalcompinit);
-                geolocationcomp.get('setup', evalcompinit);
-                return true;
+        var doc = startcomp.get(window.location.search);
+        try {
+            $('app').innerHTML = $('appFrame').contentDocument.body.innerHTML;
+
+            // Initial setup of the widgets
+            map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID($('app'), 'page').childNodes)));
 
-            } catch(e) {
-                log('exception on appstartcomp.get()', e);
-            }
-        });
+            // 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'));
+            return true;
+
+        } catch(e) {
+            log('exception on startcomp.get()', e);
+        }
     } catch(e) {
         log('exception in getpagedata()', e);
     }
@@ -330,10 +324,7 @@ function getpagedata() {
  * Get app data from a component.
  */
 function getcompdata(comp, qs) {
-    var doc = comp.get(qs, function(doc) {
-        return displaydoc(doc);
-    });
-    return true;
+    return displaydoc(comp.get(qs));
 }
 
 /**
@@ -377,7 +368,7 @@ function buttonClickHandler(id) {
  */
 function intervalHandler() {
     try {
-        return getcompdata(everycomp, compquery());
+        return getcompdata(timercomp, compquery());
     } catch(e) {
         log('exception in intervalHandler()', e);
     }

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=1098489&r1=1098488&r2=1098489&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  2 05:58:26 2011
@@ -1,37 +1,24 @@
-CACHE-MANIFEST
+CACHE MANIFEST
 
 # Common resources
-atomutil.js
-component.js
-elemutil.js
-jsconfig.js
-jsonutil.js
-scdl.js
-ui.css
-ui.js
-util.js
-xmlutil.js
+all-min.js
+config.js
+ui-min.css
 
 # App resources
 app/index.html
-dash/dashboard.html
-dash/index.html
+clone/index.html
+data/index.html
+create/index.html
 data/index.html
 favicon.ico
-graph/graph.html
 graph/graph.js
 graph/index.html
 home.png
 index.html
-login/index.html
-logout/index.html
-main.html
-menu.html
+menu.js
 page/index.html
-page/page.html
 page/page.js
-props/index.html
-props/props.html
 public/app.png
 public/grid72.png
 public/iframe.html
@@ -42,6 +29,9 @@ public/notyet.html
 public/oops.html
 public/touchicon.png
 robots.txt
+stats/index.html
 store/index.html
-store/store.html
+
+NETWORK:
+*
 

Added: 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=1098489&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/index.html (added)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/index.html Mon May  2 05:58:26 2011
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+-->
+<html>
+<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="/config.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
+<script type="text/javascript" src="/menu.js"></script>
+</head>
+<body class="delayed" onorientationchange="ui.reload();">
+<div id="bodydiv" class="devicewidth">
+
+<div id="menu"></div>
+
+<table style="width: 100%;">
+<tr>
+<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
+</tr>
+</table>
+
+<table style="width: 100%;">
+<tr>
+<th id="th" class="thl thr" style="padding-top: 4px; padding-bottom:4px;">Clone this App</th>
+</tr>
+</table>
+
+<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><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>
+<tr><td><input type="checkbox" value="shared"/><span>Shared</span></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr>
+<tr><td><input type="text" id="appTitle" size="30" placeholder="Enter the title of your app" style="width: 300px;"/></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
+<tr><td><textarea id="appDescription" cols="40" rows="3" placeholder="Enter a short description of your app" style="width: 300px;"></textarea></td></tr>
+<tr><td>
+<input id="cloneAppOKButton" type="submit" class="greenbutton" style="font-weight: bold;" value="Clone" title="Clone the app"/>
+<input id="cloneAppCancelButton" type="button" class="redbutton" value="Cancel"/>
+</td></tr>
+</table>
+</form>
+
+</div>
+
+<script type="text/javascript">
+// Get the app name
+var appname = ui.queryParams()['app'];
+if (isNil(appname))
+    window.open('/', '_self');
+
+/**
+ * Return the link to an app.
+ */
+function applink(appname) {
+    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 + '/';
+    return link;
+}
+
+// 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>';
+$('th').innerHTML = tclone + ' this App';
+$('cloneAppOKButton').value = tclone;
+$('cloneAppOKButton').title = tclone + ' the app';
+
+// Load the menu bar
+displaymenu();
+
+// Init form
+$('appDomain').innerHTML = '.' + window.location.hostname;
+
+// Show the page
+ui.showbody();
+
+// Init service references
+var editWidget = sca.component("EditWidget");
+var dashboard = sca.reference(editWidget, "dashboard");
+var apps = sca.reference(editWidget, "apps");
+
+/**
+ * The current app entry and corresponding saved XML content.
+ */
+var appentry;
+var savedappentryxml = '';
+
+/**
+ * Get and display an app.
+ */
+function getapp(name) {
+    if (isNil(name))
+        return false;
+    return apps.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;
+        $('appDescription').innerHTML = '';
+        savedappentryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
+        return true;
+    });
+}
+
+/**
+ * Clone an app.
+ */
+$('cloneAppForm').onsubmit = function() {
+    var name = $('appName').value;
+    if (name == '')
+        return false;
+    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');
+    return false;
+};
+
+/**
+ * Cancel cloning an app.
+ */
+$('cloneAppCancelButton').onclick = function() {
+    return window.open('/store/', '_self');
+};
+
+// Get the current app
+getapp(appname);
+
+</script>
+
+</body>
+</html>
+

Added: 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=1098489&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/create/index.html (added)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/create/index.html Mon May  2 05:58:26 2011
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+-->
+<html>
+<head>
+<title>Create App</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="/config.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
+<script type="text/javascript" src="/menu.js"></script>
+</head>
+<body class="delayed" onorientationchange="ui.reload();">
+<div id="bodydiv" class="devicewidth">
+
+<div id="menu"></div>
+
+<table style="width: 100%;">
+<tr><td><h1><span id="h1"></span></h1></td></tr>
+</table>
+
+<table style="width: 100%;">
+<tr>
+<th class="thl thr" style="padding-top: 4px; padding-bottom:4px;">Create an App</th>
+</tr>
+</table>
+
+<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><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>
+<tr><td><input type="checkbox" value="shared"/><span>Shared</span></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr>
+<tr><td><input type="text" id="appTitle" size="30" placeholder="Enter the title of your app" style="width: 300px;"/></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
+<tr><td><textarea id="appDescription" cols="40" rows="3" placeholder="Enter a short description of your app" style="width: 300px;"></textarea></td></tr>
+<tr><td>
+<input id="createAppOKButton" type="submit" class="greenbutton" style="font-weight: bold;" value="Create" title="Create the app"/>
+<input id="createAppCancelButton" type="button" class="redbutton" value="Cancel"/>
+</td></tr>
+</table>
+</form>
+
+</div>
+
+<script type="text/javascript">
+// Set page titles
+document.title = windowtitle(window.location.hostname) + ' - Create App';
+$('h1').innerHTML = hometitle(window.location.hostname);
+
+// Load the menu bar
+displaymenu();
+
+// Init form
+$('appDomain').innerHTML = '.' + window.location.hostname;
+
+// Show the page
+ui.showbody();
+
+// Init service references
+var editWidget = sca.component("EditWidget");
+var dashboard = sca.reference(editWidget, "dashboard");
+
+/**
+ * Create an app.
+ */
+$('createAppForm').onsubmit = function() {
+    var name = $('appName').value;
+    if (name == '')
+        return false;
+    var title = $('appTitle').value;
+    var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", name)));
+    var entry = atom.writeATOMEntry(valuesToElements(app));
+    dashboard.put(name, car(entry));
+    window.open('/store/', '_self');
+    return false;
+};
+
+/**
+ * Cancel creating an app.
+ */
+$('createAppCancelButton').onclick = function() {
+    return window.open('/store/', '_self');
+};
+
+</script>
+
+</body>
+</html>
+

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=1098489&r1=1098488&r2=1098489&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  2 05:58:26 2011
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
 <!--
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -27,18 +28,11 @@ document.title = 'View - ' + window.loca
 <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.css">
+<link rel="stylesheet" type="text/css" href="/ui-min.css">
 <script type="text/javascript" src="/config.js"></script>
-<script type="text/javascript" src="/util.js"></script>
-<script type="text/javascript" src="/elemutil.js"></script>
-<script type="text/javascript" src="/xmlutil.js"></script>
-<script type="text/javascript" src="/atomutil.js"></script>
-<script type="text/javascript" src="/jsonutil.js"></script>
-<script type="text/javascript" src="/scdl.js"></script>
-<script type="text/javascript" src="/ui.js"></script>
-<script type="text/javascript" src="/component.js"></script>
+<script type="text/javascript" src="/all-min.js"></script>
 </head>  
-<body class="delayed">
+<body class="delayed" onorientationchange="ui.reload();">
 
 <div id="bodydiv" style="position: absolute; top: 0px; left: 0px; right: 0px;">
 
@@ -75,15 +69,14 @@ function datatable(e) {
  */
 function mkdoctable(doc) {
     var tr = '<tr><td class="datatdl">' + 'value' + '</td>' + '<td class="datatdr">' + doc + '</td></tr>';
-    return '<table class="datatable ' + (window.name == 'dataFrame'? ' databg' : '') + '" style="width: 100%;">' + tr + '</table>';
+    return '<table class="datatable ' + (window.name == 'previewFrame'? ' databg' : '') + '" style="width: 100%;">' + tr + '</table>';
 }
 
 /**
  * Get and display the contents of the current component.
  */
 function getdata() {
-    comp.get('', function(doc) {
-
+    return comp.get('', function(doc) {
         if (json.isJSON(mklist(doc)))
             return display(datatable(json.readJSON(mklist(doc))));
 

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=1098489&r1=1098488&r2=1098489&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  2 05:58:26 2011
@@ -53,15 +53,15 @@ graph.colors.lightgray1 = '#dcdcdc'
 /**
  * Default positions and sizes.
  */
-var palcx = 250;
-var trashcx = 230;
+var palcx = 2500;
+var trashcx = 2480;
 var proxcx = 20;
 var proxcy = 20;
 var buttoncx = 65;
 var buttoncy = 30;
 var curvsz = 6;
 var tabsz = 2;
-var fontsz = '';
+var fontsz = '11px';
 
 /**
  * Base path class.
@@ -103,986 +103,520 @@ graph.BasePath = function() {
 };
 
 /**
- * Rendering functions that work both with VML and SVG.
+ * SVG rendering functions.
  */
 
+graph.svgns='http://www.w3.org/2000/svg';
+
 /**
- * VML rendering.
+ * Make an SVG graph.
  */
-if (ui.isIE()) {
+graph.mkgraph = function(pos, cvalue, cadd, 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());
+    div.style.top = ui.pixpos(pos.ypos());
+    div.style.overflow = 'hidden';
+    document.body.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);
 
-    graph.vmlns='urn:schemas-microsoft-com:vml';
-    document.write('<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />');
+    // Track element dragging and selection
+    graph.dragging = null;
+    graph.selected = null;
+    cvalue.disabled = true;
+    cdelete.disabled = true;
 
     /**
-     * Make a VML graph.
+     * Find the first draggable element in a hierarchy of elements.
      */
-    graph.mkgraph = function(pos, cname, pvalue) {
+    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);
+    }
 
-        // Create div element to host the graph
-        var div = document.createElement('div');
-        div.id = 'vmldiv';
-        div.style.position = 'absolute';
-        div.style.left = pos.xpos();
-        div.style.top = pos.ypos();
-        document.body.appendChild(div);
-
-        // Create a VML group
-        var vmlg = document.createElement('v:group');
-        vmlg.style.width = 5000;
-        vmlg.style.height = 5000;
-        vmlg.coordsize = '5000,5000';
-        div.appendChild(vmlg);
+    /**
+     * Handle a mouse down event.
+     */
+    div.onmousedown = function(e) {
 
-        // Track element dragging and selection
-        graph.dragging = null;
-        graph.selected = null;
-        cname.disabled = true;
-        pvalue.disabled = true;
+        // Find draggable component
+        graph.dragging = draggable(e.target);
+        graph.selected = graph.dragging;
+        if (graph.dragging == null) {
+
+            // Reset current selection
+            cvalue.value = '';
+            cvalue.disabled = true;
+            cdelete.disabled = true;
 
-        /**
-         * Find the first draggable element in a hierarchy of elements.
-         */
-        function draggable(n) {
-            if (n == vmlg)
-                return null;
-            if (n.nodeName == 'group' && n.id != '')
-                return n;
-            return draggable(n.parentNode);
+            // Trigger component select event
+            svg.oncompselect('');
+            return true;
         }
 
-        /**
-         * Handle a mousedown event.
-         */
-        vmlg.onmousedown = function() {
-            window.event.returnValue = false;
-
-            // Find draggable element
-            graph.dragging = draggable(window.event.srcElement);
+        // 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;
-            if (graph.dragging == null) {
-
-                // Reset current selection
-                cname.value = '';
-                cname.disabled = true;
-                pvalue.value = '';
-                pvalue.disabled = true;
-
-                // Trigger component select event
-                vmlg.oncompselect('');
-                return false;
-            }
-
-            // Clone component from the palette
-            var compos = scdl.composite(vmlg.compos);
-            if (graph.dragging.id.substring(0, 8) == 'palette:') {
-                graph.dragging = graph.clonepalette(graph.dragging, compos);
-                graph.selected = graph.dragging;
-            }
-
-            // Cut wire to component
-            if (graph.dragging.parentNode != vmlg)
-                setElement(compos, graph.cutwire(graph.dragging, compos, vmlg));
-
-            // Bring component to the top
-            graph.bringtotop(graph.dragging, vmlg);
-
-            // Remember mouse position
-            graph.dragX = window.event.clientX;
-            graph.dragY = window.event.clientY;
-            vmlg.setCapture();
-
-            // Update the component name and property value fields
-            cname.value = graph.selected.id;
-            cname.disabled = false;
-            pvalue.value = graph.property(graph.selected.comp);
-            pvalue.disabled = !graph.hasproperty(graph.selected.comp);
-
-            // Trigger component select event
-            vmlg.oncompselect(vmlg.appname, graph.selected.id);
-            return false;
-        };
-
-        /**
-         * Handle a mouseup event.
-         */
-        vmlg.onmouseup = function() {
-            if (graph.dragging == null)
-                return false;
-
-            if (graph.dragging.parentNode == vmlg && 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(vmlg.compos);
-                        setElement(compos, graph.addcomp(graph.dragging.comp, compos));
-                        graph.dragging.compos = vmlg.compos;
-                    }
-
-                    // Update component position
-                    setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, vmlg)));
-
-                    // Wire component to neighboring reference
-                    if (!isNil(graph.dragging.svcpos)) {
-                        var compos = scdl.composite(vmlg.compos);
-                        setElement(compos, grah.clonerefs(graph.wire(graph.dragging, compos, vmlg)));
-                    }
-
-                } else {
-
-                    // Discard component dragged out of composite
-                    vmlg.removeChild(graph.dragging);
-                    if (!isNil(graph.dragging.compos)) {
-                        var compos = scdl.composite(vmlg.compos);
-                        setElement(compos, graph.clonerefs(graph.gcollect(graph.removecomp(graph.dragging.comp, compos))));
-                    }
-
-                    // Reset current selection
-                    graph.selected = null;
-                    cname.value = '';
-                    cname.disabled = true;
-                    pvalue.value = '';
-                    pvalue.disabled = true;
-
-                    // Trigger component select event
-                    vmlg.oncompselect('');
-                }
-
-                // Trigger composite change event
-                vmlg.oncomposchange(false);
-            }
-
-            // Forget current dragged component
-            graph.dragging = null;
-            vmlg.releaseCapture();
-
-            // Refresh the composite
-            graph.refresh(vmlg);
-            return false;
-        };
 
-        /**
-         * Handle a mousemove event.
-         */
-        vmlg.onmousemove = function() {
-            if (graph.dragging == null)
-                return false;
-
-            // Calculate new position of dragged element
+            // Move into the editing area and hide the palette
             var gpos = graph.relpos(graph.dragging);
-            var newX = gpos.xpos() + (window.event.clientX - graph.dragX);
-            var newY = gpos.ypos() + (window.event.clientY - graph.dragY);
-            if (newX >= 0)
-                graph.dragX = window.event.clientX;
-            else
-                newX = 0;
-            if (newY >= 0)
-                graph.dragY = window.event.clientY;
-            else
-                newY = 0;
+            graph.move(graph.dragging, graph.mkpath().move(gpos.xpos() + palcx, gpos.ypos()));
+            div.style.left = ui.pixpos(palcx * -1);
+        }
 
-            // Move the dragged element
-            graph.move(graph.dragging, graph.mkpath().move(newX, newY));
+        // 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);
+
+        // 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);
 
-            return false;
-        };
+        if (e.preventDefault)
+            e.preventDefault();
+        else
+            e.returnValue = false;
+        return true;
+    };
 
-        /**
-         * Handle field on change events.
-         */
-        cname.onchange = function() {
-            if (graph.selected == null)
-                return false;
-
-            // Change component name and refactor references to it
-            var compos = scdl.composite(vmlg.compos);
-            cname.value = graph.ucid(cname.value, compos);
-            cname.disabled = false;
-            graph.selected.id = cname.value;
-            setElement(compos, graph.renamecomp(graph.selected.comp, compos, cname.value));
+    // Support touch devices
+    div.ontouchstart = div.onmousedown;
 
-            // Trigger component select event
-            vmlg.oncompselect(vmlg.appname, graph.selected.id);
+    /**
+     * Handle a mouse up event.
+     */
+    div.onmouseup = function(e) {
+        if (graph.dragging == null)
+            return true;
 
-            // Refresh the composite
-            graph.refresh(vmlg);
+        if (graph.dragging.parentNode == svg && graph.dragging.id.substring(0, 8) != 'palette:') {
+            var gpos = graph.relpos(graph.dragging);
+            if (gpos.xpos() >= trashcx) {
 
-            // Trigger composite change event
-            vmlg.oncomposchange(true);
-            return false;
-        };
+                // 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;
+                }
 
-        pvalue.onchange = function() {
-            if (graph.selected == null)
-                return false;
-
-            // Change the component property value
-            graph.setproperty(graph.selected.comp, pvalue.value);
-            pvalue.value = graph.property(graph.selected.comp);
-            pvalue.disabled = !graph.hasproperty(graph.selected.comp);
+                // Update component position
+                setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, svg)));
 
-            // Refresh the composite
-            graph.refresh(vmlg);
+                // 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 composite change event
-            vmlg.oncomposchange(true);
-            return false;
-        };
+            } else {
 
-        // Create hidden spans to help compute the width of
-        // component, reference and property titles
-        graph.comptitlewidthdiv = document.createElement('span');
-        graph.comptitlewidthdiv.style.visibility = 'hidden'
-        if (fontsz != '')
-            graph.comptitlewidthdiv.style.fontSize = fontsz;
-        div.appendChild(graph.comptitlewidthdiv);
-
-        graph.reftitlewidthdiv = document.createElement('span');
-        graph.reftitlewidthdiv.style.visibility = 'hidden'
-        if (fontsz != '')
-            graph.comptitlewidthdiv.style.fontSize = fontsz;
-        div.appendChild(graph.reftitlewidthdiv);
-
-        graph.proptitlewidthdiv = document.createElement('span');
-        graph.proptitlewidthdiv.style.visibility = 'hidden'
-        if (fontsz != '')
-            graph.comptitlewidthdiv.style.fontSize = fontsz;
-        div.appendChild(graph.proptitlewidthdiv);
+                // 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)))));
+                }
 
-        return vmlg;
-    };
+                // Reset current selection
+                graph.selected = null;
+                cvalue.value = '';
+                cvalue.disabled = true;
+                cdelete.disabled = true;
 
-    /**
-     * Make a shape path.
-     */
-    graph.mkpath = function() {
-        function Path() {
-            this.BasePath = graph.BasePath;
-            this.BasePath();
-
-            this.clone = function() {
-                return graph.mkpath().pos(this.xpos(), this.ypos());
-            };
-
-            this.move = function(x, y) {
-                this.path += 'M ' + x + ',' + y + ' '; 
-                return this.pos(x, y);
-            };
-
-            this.line = function(x, y) {
-                this.path += 'L ' + x + ',' + y + ' ';
-                return this.pos(x, y);
-            };
-
-            this.curve = function(x1, y1, x, y) {
-                this.path += 'QB ' + x1 + ',' + y1 + ',' + x + ',' + y + ' ';
-                return this.pos(x, y);
-            };
-
-            this.end = function() {
-                this.path += 'X E';
-                return this;
-            };
+                // Trigger component select event
+                svg.oncompselect('');
+            }
         }
 
-        return new Path();
-    };
-
-    /**
-     * Return an element representing a title.
-     */
-    graph.mktitle = function(t, style, pos) {
-        var title = document.createElement('v:textbox');
-        title.style.position = 'absolute';
-        title.style.left = pos.xpos() + 2;
-        title.style.top = pos.ypos();
-        title.inset = '' + 6 + 'px ' + pos.ypos() + 'px 0px 0px';
-        if (style != '')
-            title.style.cssText = style;
-        if (fontsz != '')
-            title.style.fontSize = fontsz;
-        var tnode = document.createTextNode(t);
-        title.appendChild(tnode);
-        return title;
-    };
-
-    /**
-     * Return an element representing the title of a component.
-     */
-    graph.comptitle = function(comp) {
-        var tsvcs = graph.tsvcs(comp);
-        var lsvcs = graph.lsvcs(comp);
-        var pos = graph.mkpath().move(isNil(lsvcs)? tabsz : (tabsz * 5), isNil(tsvcs)? tabsz : (tabsz * 5));
-        return graph.mktitle(graph.title(comp), graph.compstyle(comp), pos);
-    };
-
-    /**
-     * Return the width of the title of a component.
-     */
-    graph.comptitlewidth = function(comp) {
-        var t = graph.title(comp);
-        graph.comptitlewidthdiv.innerHTML = t;
-        var twidth = graph.comptitlewidthdiv.offsetWidth + 2;
-        graph.comptitlewidthdiv.innerHTML = '';
-        return twidth;
-    };
-
-    /**
-     * Return an element representing the value of a property.
-     */
-    graph.proptitle = function(comp) {
-        var tsvcs = graph.tsvcs(comp);
-        var lsvcs = graph.lsvcs(comp);
-        var pos = graph.mkpath().move(graph.comptitlewidth(comp) + 7 + (isNil(lsvcs)? tabsz : (tabsz * 5)), isNil(tsvcs)? tabsz : (tabsz * 5));
-        return graph.mktitle(graph.propertytitle(comp), graph.propstyle(comp), pos);
-    };
-
-    /**
-     * Return the width of the value of a property.
-     */
-    graph.proptitlewidth = function(comp) {
-        var t = graph.proptitle(comp);
-        graph.proptitlewidthdiv.innerHTML = t;
-        var twidth = graph.proptitlewidthdiv.offsetWidth + 4;
-        graph.proptitlewidthdiv.innerHTML = '';
-        return twidth;
-    };
+        // Forget current dragged component
+        graph.dragging = null;
 
-    /**
-     * Return an element representing the title of a reference.
-     */
-    graph.reftitle = function(ref) {
-        return graph.mktitle(graph.title(ref), graph.refstyle(ref), graph.mkpath().move(25,25));
-    };
+        // Refresh the composite
+        graph.refresh(svg);
 
-    /**
-     * Return the width of the title of a reference.
-     */
-    graph.reftitlewidth = function(ref) {
-        var t = graph.title(ref);
-        graph.reftitlewidthdiv.innerHTML = t;
-        var twidth = graph.reftitlewidthdiv.offsetWidth;
-        graph.reftitlewidthdiv.innerHTML = '';
-        return twidth;
+        // Trigger composite change event
+        svg.oncomposchange(false);
+        return true;
     };
 
-    /**
-     * Return a node representing a component.
-     */
-    graph.compnode = function(comp, cassoc, pos) {
+    // Support touch devices
+    div.ontouchend = div.onmouseup;
 
-        // Make the component and property title elements
-        var title = graph.comptitle(comp);
-        var prop = graph.proptitle(comp);
-
-        // Compute the component shape path
-        var path = graph.comppath(comp, cassoc);
-        var d = path.str();
-
-        // Create the main component shape
-        var shape = document.createElement('v:shape');
-        shape.style.width = 5000;
-        shape.style.height = 5000;
-        shape.coordsize = '5000,5000';
-        shape.path = d;
-        shape.fillcolor = graph.color(comp);
-        shape.stroked = 'false';
-
-        // Create an overlay contour shape
-        var contour = document.createElement('v:shape');
-        contour.style.width = 5000;
-        contour.style.height = 5000;
-        contour.coordsize = '5000,5000';
-        contour.path = d;
-        contour.filled = 'false';
-        contour.strokecolor = graph.colors.gray;
-        contour.strokeweight = '1';
-        contour.style.left = 1;
-        contour.style.top = 1;
-        var stroke = document.createElement('v:stroke');
-        stroke.opacity = '20%';
-        contour.appendChild(stroke);
-
-        // Create a group and add the component and contour shapes to it
-        var g = document.createElement('v:group');
-        g.id = scdl.name(comp);
-        g.style.width = 5000;
-        g.style.height = 5000;
-        g.coordsize = '5000,5000';
-        g.style.left = pos.xpos();
-        g.style.top = pos.ypos();
-        g.appendChild(shape);
-        shape.appendChild(title);
-        shape.appendChild(prop);
-        g.appendChild(contour)
-
-        // Store the component and the positions of its services
-        // and references in the component shape
-        g.comp = comp;
-        g.refpos = reverse(path.refpos);
-        g.svcpos = reverse(path.svcpos);
+    // Handle a mouse click event.
+    div.onclick = function(e) {
+        if (graph.dragging == null && (e.target == div || e.target == svg)) {
 
-        return g;
-    };
-
-    /**
-     * Return a graphical group.
-     */
-    graph.mkgroup = function(pos) {
-        var g = document.createElement('v:group');
-        g.style.left = pos.xpos();
-        g.style.top = pos.ypos();
-        return g;
-    };
+            // Dismiss the palette
+            if (ui.numpos(div.style.left) != (palcx * -1))
+            	div.style.left = ui.pixpos(palcx * -1);
+        }
+        return true;
+    }
 
     /**
-     * Return a node representing a button.
+     * Handle a mouse move event.
      */
-    graph.mkbutton = function(t, pos) {
-
-        // Make the title element
-        var title = graph.mktitle(t, '', graph.mkpath().move(4,4));
-
-        // Compute the path of the button shape
-        var path = graph.buttonpath().str();
+    window.onmousemove = function(e) {
+        if (graph.dragging == null)
+            return true;
 
-        // Create the main button shape
-        var shape = document.createElement('v:shape');
-        shape.style.width = 5000;
-        shape.style.height = 5000;
-        shape.coordsize = '5000,5000';
-        shape.path = path;
-        shape.fillcolor = graph.colors.lightgray;
-        shape.stroked = 'false';
-
-        // Create an overlay contour shape
-        var contour = document.createElement('v:shape');
-        contour.style.width = 5000;
-        contour.style.height = 5000;
-        contour.coordsize = '5000,5000';
-        contour.path = path;
-        contour.filled = 'false';
-        contour.strokecolor = graph.colors.gray;
-        contour.strokeweight = '1';
-        contour.style.left = 1;
-        contour.style.top = 1;
-        var stroke = document.createElement('v:stroke');
-        stroke.opacity = '20%';
-        contour.appendChild(stroke);
-
-        // Create a group and add the button and contour shapes to it
-        var g = document.createElement('v:group');
-        g.style.width = 5000;
-        g.style.height = 5000;
-        g.coordsize = '5000,5000';
-        g.style.left = pos.xpos();
-        g.style.top = pos.ypos();
-        g.appendChild(shape);
-        shape.appendChild(title);
-        g.appendChild(contour)
-        return g;
-    };
+        // 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)
+            graph.dragX = pos.screenX;
+        else
+            newX = 0;
+        if (newY >= 0)
+            graph.dragY = pos.screenY;
+        else
+            newY = 0;
 
-    /**
-     * Return the relative position of a node.
-     */
-    graph.relpos = function(e) {
-        var curX = ui.csspos(e.style.left);
-        var curY = ui.csspos(e.style.top);
-        return graph.mkpath().move(curX, curY);
-    };
+        // Move the dragged element
+        graph.move(graph.dragging, graph.mkpath().move(newX, newY));
 
-    /**
-     * Move a node.
-     */
-    graph.move = function(e, pos) {
-        e.style.left = pos.xpos();
-        e.style.top = pos.ypos();
+        return true;
     };
 
-} else {
+    // Support touch devices
+    div.ontouchmove = window.onmousemove;
 
     /**
-     * SVG rendering.
+     * Handle field on change events.
      */
-    graph.svgns='http://www.w3.org/2000/svg';
+    cvalue.onchange = function() {
+        if (graph.selected == null)
+            return false;
 
-    /**
-     * Make an SVG graph.
-     */
-    graph.mkgraph = function(pos, cname, pvalue) {
+        // Change component name and refactor references to it
+        function changename() {
+            var compos = scdl.composite(svg.compos);
+            cvalue.value = graph.ucid(cvalue.value, compos);
+            graph.selected.id = cvalue.value;
+            setElement(compos, graph.sortcompos(graph.renamecomp(graph.selected.comp, compos, cvalue.value)));
 
-        // Create a div element to host the graph
-        var div = document.createElement('div');
-        div.id = 'svgdiv';
-        div.style.position = 'absolute';
-        div.style.left = pos.xpos();
-        div.style.top = pos.ypos();
-        // -webkit-user-select: none;
-        document.body.appendChild(div);
-
-        // Create SVG element
-        var svg = document.createElementNS(graph.svgns, 'svg');
-        svg.style.height = 5000;
-        svg.style.width = 5000;
-        div.appendChild(svg);
+            // Trigger component select event
+            svg.oncompselect(graph.selected.id);
 
-        // Track element dragging and selection
-        graph.dragging = null;
-        graph.selected = null;
-        cname.disabled = true;
-        pvalue.disabled = true;
+            // Refresh the composite
+            graph.refresh(svg);
 
-        /**
-         * Find the first draggable element in a hierarchy of elements.
-         */
-        function draggable(n) {
-            if (n == svg)
-                return null;
-            if (n.nodeName == 'g' && n.id != '')
-                return n;
-            return draggable(n.parentNode);
+            // Trigger composite change event
+            svg.oncomposchange(true);
+            return false;
         }
 
-        /**
-         * Handle a mouse down event.
-         */
-        svg.onmousedown = function(e) {
-            if (e.preventDefault)
-                e.preventDefault();
-            else
-                e.returnValue = false;
-
-            // Find draggable component
-            graph.dragging = draggable(e.target);
-            graph.selected = graph.dragging;
-            if (graph.dragging == null) {
-
-                // Reset current selection
-                cname.value = '';
-                cname.disabled = true;
-                pvalue.value = '';
-                pvalue.disabled = true;
+        // Change the component property value
+        function changeprop() {
+            graph.setproperty(graph.selected.comp, cvalue.value);
+            cvalue.value = graph.property(graph.selected.comp);
+            cvalue.disabled = !graph.hasproperty(graph.selected.comp);
 
-                // Trigger component select event
-                svg.oncompselect('');
-                return false;
-            }
-
-            // 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;
-            }
-
-            // Cut wire to component
-            if (graph.dragging.parentNode != svg)
-                setElement(compos, graph.cutwire(graph.dragging, compos, svg));
-
-            // Bring component to the top
-            graph.bringtotop(graph.dragging, svg);
-
-            // Remember current mouse position
-            var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
-            graph.dragX = pos.screenX;
-            graph.dragY = pos.screenY;
+            // Refresh the composite
+            graph.refresh(svg);
 
-            // Update the component name and property value fields
-            cname.value = graph.selected.id;
-            cname.disabled = false;
-            pvalue.value = graph.property(graph.selected.comp);
-            pvalue.disabled = !graph.hasproperty(graph.selected.comp);
-            
-            // Trigger component select event
-            svg.oncompselect(svg.appname, graph.selected.id);
+            // Trigger composite change event
+            svg.oncomposchange(true);
             return false;
-        };
-
-        // Support touch devices
-        svg.ontouchstart = svg.onmousedown;
+        }
 
-        /**
-         * Handle a mouse up event.
-         */
-        window.onmouseup = function(e) {
-            if (graph.dragging == null)
-                return false;
-
-            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.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)));
-
-                    // Wire component to neighboring reference
-                    if (!isNil(graph.dragging.svcpos)) {
-                        var compos = scdl.composite(svg.compos);
-                        setElement(compos, 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.clonerefs(graph.gcollect(graph.removecomp(graph.dragging.comp, compos))));
-                    }
-
-                    // Reset current selection
-                    graph.selected = null;
-                    cname.value = '';
-                    cname.disabled = true;
-                    pvalue.value = '';
-                    pvalue.disabled = true;
+        return graph.hasproperty(graph.selected.comp)? changeprop() : changename();
+    };
+    
+    // Handle delete event
+    cdelete.onclick = function() {
+        if (graph.selected == null)
+            return false;
+        if (graph.selected.id.substring(0, 8) != 'palette:' && !isNil(graph.selected.compos)) {
 
-                    // Trigger component select event
-                    svg.oncompselect('');
-                }
-            }
+            // Remove selected component
+            var compos = scdl.composite(svg.compos);
+            setElement(compos, graph.sortcompos(graph.clonerefs(graph.gcollect(graph.removecomp(graph.selected.comp, compos)))));
 
-            // Forget current dragged component
-            graph.dragging = null;
+            // Reset current selection
+            graph.selected = null;
+            cvalue.value = '';
+            cvalue.disabled = true;
+            cdelete.disabled = true;
 
             // Refresh the composite
             graph.refresh(svg);
 
-            // Trigger composite change event
-            svg.oncomposchange(false);
-            return false;
-        };
-
-        // Support touch devices
-        window.top.onmouseup = window.onmouseup;
-        window.ontouchend = window.onmouseup;
-        window.gestureend = window.onmouseup;
-        window.top.gestureend = window.onmouseup;
-        window.top.ontouchend = window.onmouseup;
-        window.ontouchcancel = window.onmouseup;
-        window.top.ontouchcancel = window.onmouseup;
-
-        /**
-         * Handle a mouse move event.
-         */
-        window.onmousemove = function(e) {
-            if (graph.dragging == null)
-                return false;
-            if (e.preventDefault)
-                e.preventDefault();
-            else
-                e.returnValue = false;
+            // Trigger component select event
+            svg.oncompselect('');
 
-            // 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)
-                graph.dragX = pos.screenX;
-            else
-                newX = 0;
-            if (newY >= 0)
-                graph.dragY = pos.screenY;
-            else
-                newY = 0;
+            // Trigger composite change event
+            svg.oncomposchange(true);
+        }
+        return false;
+    };
 
-            // Move the dragged element
-            graph.move(graph.dragging, graph.mkpath().move(newX, newY));
+    // Handle add event
+    cadd.onclick = function() {
 
-            return false;
-        };
+        // Show the palette
+        div.style.left = ui.pixpos(0);
+        return false;
+    };
 
-        // Support touch devices
-        window.top.onmousemove = window.onmousemove;
-        window.ontouchmove = window.onmousemove;
-        window.top.ontouchmove = window.onmousemove;
+    // Create a hidden SVG element to help compute the width
+    // of component and reference titles
+    graph.titlewidthsvg = document.createElementNS(graph.svgns, 'svg');
+    graph.titlewidthsvg.style.visibility = 'hidden';
+    graph.titlewidthsvg.style.height = ui.pixpos(0);
+    graph.titlewidthsvg.style.width = ui.pixpos(0);
+    div.appendChild(graph.titlewidthsvg);
 
-        /**
-         * Handle field on change events.
-         */
-        cname.onchange = function() {
-            if (graph.selected == null)
-                return false;
+    return svg;
+};
 
-            // Change component name and refactor references to it
-            var compos = scdl.composite(svg.compos);
-            cname.value = graph.ucid(cname.value, compos);
-            graph.selected.id = cname.value;
-            setElement(compos, graph.renamecomp(graph.selected.comp, compos, cname.value));
+/**
+ * Make a path.
+ */
+graph.mkpath = function() {
+    function Path() {
+        this.BasePath = graph.BasePath;
+        this.BasePath();
 
-            // Trigger component select event
-            svg.oncompselect(svg.appname, graph.selected.id);
+        this.clone = function() {
+            return graph.mkpath().pos(this.xpos(), this.ypos());
+        };
 
-            // Refresh the composite
-            graph.refresh(svg);
+        this.move = function(x, y) {
+            this.path += 'M' + x + ',' + y + ' '; 
+            return this.pos(x, y);
+        };
 
-            // Trigger composite change event
-            svg.oncomposchange(true);
-            return false;
+        this.line = function(x, y) {
+            this.path += 'L' + x + ',' + y + ' ';
+            return this.pos(x, y);
         };
-        
-        pvalue.onchange = function() {
-            if (graph.selected == null)
-                return false;
-
-            // Change the component property value
-            graph.setproperty(graph.selected.comp, pvalue.value);
-            pvalue.value = graph.property(graph.selected.comp);
-            pvalue.disabled = !graph.hasproperty(graph.selected.comp);
 
-            // Refresh the composite
-            graph.refresh(svg);
+        this.curve = function(x1, y1, x, y) {
+            this.path += 'Q' + x1 + ',' + y1 + ' ' + x + ',' + y + ' ';
+            return this.pos(x, y);
+        };
 
-            // Trigger composite change event
-            svg.oncomposchange(true);
-            return false;
+        this.end = function() {
+            this.path += 'Z';
+            return this;
         };
+    }
 
-        // Create a hidden SVG element to help compute the width
-        // of component and reference titles
-        graph.titlewidthsvg = document.createElementNS(graph.svgns, 'svg');
-        graph.titlewidthsvg.style.visibility = 'hidden';
-        graph.titlewidthsvg.style.height = 0;
-        graph.titlewidthsvg.style.width = 0;
-        div.appendChild(graph.titlewidthsvg);
+    return new Path();
+};
 
-        return svg;
-    };
+/**
+ * Return an element representing a title.
+ */
+graph.mktitle = function(t, style) {
+    var title = document.createElementNS(graph.svgns, 'text');
+    title.setAttribute('x', 5);
+    title.setAttribute('y', 15);
+    title.setAttribute('text-anchor', 'start');
+    if (style != '')
+        title.style.cssText = style;
+    if (fontsz != '')
+        title.style.fontSize = fontsz;
+    title.style.cursor = 'default';
+    title.appendChild(document.createTextNode(t));
+    return title;
+};
 
-    /**
-     * Make a path.
-     */
-    graph.mkpath = function() {
-        function Path() {
-            this.BasePath = graph.BasePath;
-            this.BasePath();
-
-            this.clone = function() {
-                return graph.mkpath().pos(this.xpos(), this.ypos());
-            };
-
-            this.move = function(x, y) {
-                this.path += 'M' + x + ',' + y + ' '; 
-                return this.pos(x, y);
-            };
-
-            this.line = function(x, y) {
-                this.path += 'L' + x + ',' + y + ' ';
-                return this.pos(x, y);
-            };
-
-            this.curve = function(x1, y1, x, y) {
-                this.path += 'Q' + x1 + ',' + y1 + ' ' + x + ',' + y + ' ';
-                return this.pos(x, y);
-            };
-
-            this.end = function() {
-                this.path += 'Z';
-                return this;
-            };
-        }
+/**
+ * Return an element representing the title of a component.
+ */
+graph.comptitle = function(comp) {
+    return graph.mktitle(graph.title(comp), graph.compstyle(comp));
+};
 
-        return new Path();
-    };
+/**
+ * Return the width of the title of a component.
+ */
+graph.comptitlewidth = function(comp) {
+    var title = graph.comptitle(comp);
+    graph.titlewidthsvg.appendChild(title);
+    var width = title.getBBox().width + 2;
+    graph.titlewidthsvg.removeChild(title);
+    return width;
+};
 
-    /**
-     * Return an element representing a title.
-     */
-    graph.mktitle = function(t, style) {
-        var title = document.createElementNS(graph.svgns, 'text');
-        title.setAttribute('x', 5);
-        title.setAttribute('y', 15);
-        title.setAttribute('text-anchor', 'start');
-        if (style != '')
-            title.style.cssText = style;
-        if (fontsz != '')
-            title.style.fontSize = fontsz;
-        title.appendChild(document.createTextNode(t));
-        return title;
-    };
+/**
+ * Return an element representing the title of a reference.
+ */
+graph.reftitle = function(ref) {
+    return graph.mktitle(graph.title(ref), graph.refstyle(ref));
+};
 
-    /**
-     * Return an element representing the title of a component.
-     */
-    graph.comptitle = function(comp) {
-        return graph.mktitle(graph.title(comp), graph.compstyle(comp));
-    };
+/**
+ * Return the width of the title of a reference.
+ */
+graph.reftitlewidth = function(ref) {
+    var title = graph.reftitle(ref);
+    graph.titlewidthsvg.appendChild(title);
+    var width = title.getBBox().width;
+    graph.titlewidthsvg.removeChild(title);
+    return width;
+};
 
-    /**
-     * Return the width of the title of a component.
-     */
-    graph.comptitlewidth = function(comp) {
-        var title = graph.comptitle(comp);
-        graph.titlewidthsvg.appendChild(title);
-        var width = title.getBBox().width + 2;
-        graph.titlewidthsvg.removeChild(title);
-        return width;
-    };
+/**
+ * Return an element representing the value of a property.
+ */
+graph.proptitle = function(comp) {
+    var title = graph.mktitle(graph.propertytitle(comp), graph.propstyle(comp));
+    title.setAttribute('x', graph.comptitlewidth(comp) + 7);
+    return title;
+};
 
-    /**
-     * Return an element representing the title of a reference.
-     */
-    graph.reftitle = function(ref) {
-        return graph.mktitle(graph.title(ref), graph.refstyle(ref));
-    };
+/**
+ * Return the width of the title of a property.
+ */
+graph.proptitlewidth = function(comp) {
+    var title = graph.proptitle(comp);
+    graph.titlewidthsvg.appendChild(title);
+    var width = title.getBBox().width + 4;
+    graph.titlewidthsvg.removeChild(title);
+    return width;
+};
 
-    /**
-     * Return the width of the title of a reference.
-     */
-    graph.reftitlewidth = function(ref) {
-        var title = graph.reftitle(ref);
-        graph.titlewidthsvg.appendChild(title);
-        var width = title.getBBox().width;
-        graph.titlewidthsvg.removeChild(title);
-        return width;
-    };
+/**
+ * Return a node representing a component.
+ */
+graph.compnode = function(comp, cassoc, pos) {
 
-    /**
-     * Return an element representing the value of a property.
-     */
-    graph.proptitle = function(comp) {
-        var title = graph.mktitle(graph.propertytitle(comp), graph.propstyle(comp));
-        title.setAttribute('x', graph.comptitlewidth(comp) + 7);
-        return title;
-    };
+    // Make the component and property title elements
+    var title = graph.comptitle(comp);
+    var prop = graph.proptitle(comp);
 
-    /**
-     * Return the width of the title of a property.
-     */
-    graph.proptitlewidth = function(comp) {
-        var title = graph.proptitle(comp);
-        graph.titlewidthsvg.appendChild(title);
-        var width = title.getBBox().width + 4;
-        graph.titlewidthsvg.removeChild(title);
-        return width;
-    };
+    // Compute the path of the component shape
+    var path = graph.comppath(comp, cassoc);
+    var d = path.str();
 
-    /**
-     * Return a node representing a component.
-     */
-    graph.compnode = function(comp, cassoc, pos) {
+    // Create the main component shape
+    var shape = document.createElementNS(graph.svgns, 'path');
+    shape.setAttribute('d', d);
+    shape.setAttribute('fill', graph.color(comp));
+    shape.setAttribute('fill-opacity', '0.60');
 
-        // Make the component and property title elements
-        var title = graph.comptitle(comp);
-        var prop = graph.proptitle(comp);
-
-        // Compute the path of the component shape
-        var path = graph.comppath(comp, cassoc);
-        var d = path.str();
-
-        // Create the main component shape
-        var shape = document.createElementNS(graph.svgns, 'path');
-        shape.setAttribute('d', d);
-        shape.setAttribute('fill', graph.color(comp));
-        shape.setAttribute('fill-opacity', '0.60');
-
-        // Create an overlay contour shape
-        var contour = document.createElementNS(graph.svgns, 'path');
-        contour.setAttribute('d', d);
-        contour.setAttribute('fill', 'none');
-        contour.setAttribute('stroke', graph.colors.gray);
-        contour.setAttribute('stroke-width', '3');
-        contour.setAttribute('stroke-opacity', '0.20');
-        contour.setAttribute('transform', 'translate(1,1)');
-
-        // Create a group and add the component and contour shapes to it.
-        var g = document.createElementNS(graph.svgns, 'g');
-        g.id = scdl.name(comp);
-        g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
-        g.appendChild(shape);
-        g.appendChild(contour);
-        g.appendChild(title);
-        g.appendChild(prop);
-
-        // Store the component and the positions of its services
-        // and references in the component shape
-        g.comp = comp;
-        g.refpos = reverse(path.refpos);
-        g.svcpos = reverse(path.svcpos);
+    // Create an overlay contour shape
+    var contour = document.createElementNS(graph.svgns, 'path');
+    contour.setAttribute('d', d);
+    contour.setAttribute('fill', 'none');
+    contour.setAttribute('stroke', graph.colors.gray);
+    contour.setAttribute('stroke-width', '3');
+    contour.setAttribute('stroke-opacity', '0.20');
+    contour.setAttribute('transform', 'translate(1,1)');
 
-        return g;
-    };
+    // Create a group and add the component and contour shapes to it.
+    var g = document.createElementNS(graph.svgns, 'g');
+    g.id = scdl.name(comp);
+    g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
+    g.appendChild(shape);
+    g.appendChild(contour);
+    g.appendChild(title);
+    g.appendChild(prop);
 
-    /**
-     * Return a graphical group.
-     */
-    graph.mkgroup = function(pos) {
-        var g = document.createElementNS(graph.svgns, 'g');
-        g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
-        return g;
-    };
+    // Store the component and the positions of its services
+    // and references in the component shape
+    g.comp = comp;
+    g.refpos = reverse(path.refpos);
+    g.svcpos = reverse(path.svcpos);
 
-    /**
-     * Return a node representing a button.
-     */
-    graph.mkbutton = function(t, pos) {
+    return g;
+};
 
-        // Make the button title
-        var title = graph.mktitle(t, '');
+/**
+ * Return a graphical group.
+ */
+graph.mkgroup = function(pos) {
+    var g = document.createElementNS(graph.svgns, 'g');
+    g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
+    return g;
+};
 
-        // Compute the path of the button shape
-        var path = graph.buttonpath().str();
+/**
+ * Return a node representing a button.
+ */
+graph.mkbutton = function(t, pos) {
 
-        // Create the main button shape
-        var shape = document.createElementNS(graph.svgns, 'path');
-        shape.setAttribute('d', path);
-        shape.setAttribute('fill', graph.colors.lightgray);
-        shape.setAttribute('fill-opacity', '0.60');
-
-        // Create an overlay contour shape
-        var contour = document.createElementNS(graph.svgns, 'path');
-        contour.setAttribute('d', path);
-        contour.setAttribute('fill', 'none');
-        contour.setAttribute('stroke', graph.colors.gray);
-        contour.setAttribute('stroke-width', '3');
-        contour.setAttribute('stroke-opacity', '0.20');
-        contour.setAttribute('transform', 'translate(1,1)');
-
-        // Create a group and add the button and contour shapes to it
-        var g = document.createElementNS(graph.svgns, 'g');
-        g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
-        g.appendChild(shape);
-        g.appendChild(contour);
-        g.appendChild(title);
-        return g;
-    };
+    // Make the button title
+    var title = graph.mktitle(t, '');
 
-    /**
-     * Return the relative position of a node.
-     */
-    graph.relpos = function(e) {
-        var pmatrix = e.parentNode.getCTM();
-        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().move(curX, curY);
-    };
+    // 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.lightgray);
+    shape.setAttribute('fill-opacity', '0.60');
+
+    // Create an overlay contour shape
+    var contour = document.createElementNS(graph.svgns, 'path');
+    contour.setAttribute('d', path);
+    contour.setAttribute('fill', 'none');
+    contour.setAttribute('stroke', graph.colors.gray);
+    contour.setAttribute('stroke-width', '3');
+    contour.setAttribute('stroke-opacity', '0.20');
+    contour.setAttribute('transform', 'translate(1,1)');
+
+    // Create a group and add the button and contour shapes to it
+    var g = document.createElementNS(graph.svgns, 'g');
+    g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
+    g.appendChild(shape);
+    g.appendChild(contour);
+    g.appendChild(title);
+    return g;
+};
 
-    /**
-     * Move a node.
-     */
-    graph.move = function(e, pos) {
-        e.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
-    };
+/**
+ * Return the relative position of a node.
+ */
+graph.relpos = function(e) {
+    var pmatrix = e.parentNode.getCTM();
+    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().move(curX, curY);
+};
+
+/**
+ * Move a node.
+ */
+graph.move = function(e, pos) {
+    e.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
 };
 
 /**
@@ -1725,11 +1259,46 @@ graph.clonepalette = function(e, compos)
  * 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) == "'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)));
 };
 
 /**
+ * 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 component to a SCDL composite.
  */
 graph.addcomp = function(comp, compos) {
@@ -1865,7 +1434,7 @@ graph.cutwire = function(node, compos, g
     var name = scdl.name(comp);
     var prom = mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name));
     return append(mklist(element, "'composite"),
-            append(filter(function(c) { return !(isElement(c) && scdl.name(c) == name); }, elementChildren(compos)), mklist(prom, comp)));
+            append(mklist(prom), filter(function(c) { return !(isElement(c) && elementName(c) == "'service" && scdl.name(c) == name); }, elementChildren(compos))));
 }
 
 /**
@@ -1933,6 +1502,7 @@ graph.wire = function(n, compos, g) {
 
     // 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);
@@ -1981,6 +1551,10 @@ graph.edit = function(appname, compos, n
     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;