summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sca-cpp/trunk/modules/edit/Makefile.am4
-rw-r--r--sca-cpp/trunk/modules/edit/apps/relay/app.composite10
-rw-r--r--sca-cpp/trunk/modules/edit/apps/store/app.composite10
-rw-r--r--sca-cpp/trunk/modules/edit/apps/store2/app.composite10
-rw-r--r--sca-cpp/trunk/modules/edit/apps/store3/app.composite10
-rw-r--r--sca-cpp/trunk/modules/edit/apps/travel/app.composite20
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/app/app.html85
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/app/index.html66
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html3
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/dash/index.html3
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/graph/graph.html39
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/graph/graph.js400
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/graph/index.html12
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/index.html7
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/menu.html2
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/page/index.html10
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/page/page.html22
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/page/page.js165
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/control/palette.composite10
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/operators/palette.composite24
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite2
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/social/palette.composite10
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/variables/palette.composite12
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/atomutil.js2
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/component.js4
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/elemutil.js54
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/scdl.js2
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/ui.css8
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/ui.js4
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/util.js118
30 files changed, 906 insertions, 222 deletions
diff --git a/sca-cpp/trunk/modules/edit/Makefile.am b/sca-cpp/trunk/modules/edit/Makefile.am
index 5b456ea4ca..2007507817 100644
--- a/sca-cpp/trunk/modules/edit/Makefile.am
+++ b/sca-cpp/trunk/modules/edit/Makefile.am
@@ -17,6 +17,6 @@
moddir = $(prefix)/modules/edit
-nobase_dist_mod_DATA = htdocs/*.html htdocs/dash/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html
-EXTRA_DIST = htdocs/*.html htdocs/dash/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html
+nobase_dist_mod_DATA = htdocs/*.html htdocs/dash/*.html htdocs/app/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html
+EXTRA_DIST = htdocs/*.html htdocs/dash/*.html htdocs/app/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html
diff --git a/sca-cpp/trunk/modules/edit/apps/relay/app.composite b/sca-cpp/trunk/modules/edit/apps/relay/app.composite
index 1e5015315c..2f630872de 100644
--- a/sca-cpp/trunk/modules/edit/apps/relay/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/relay/app.composite
@@ -28,7 +28,7 @@
<service name="HTML" promote="HTML"/>
<service name="JSONFB" promote="JSONFB"/>
- <component name="JSONTwit" t:color="red">
+ <component name="JSONTwit" t:color="blue1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="jsontwit"/>
@@ -38,7 +38,7 @@
</reference>
</component>
- <component name="XMLTwit" t:color="green">
+ <component name="XMLTwit" t:color="green1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="xmltwit"/>
@@ -48,7 +48,7 @@
</reference>
</component>
- <component name="RSSTwit" t:color="blue">
+ <component name="RSSTwit" t:color="blue1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="rsstwit"/>
@@ -58,7 +58,7 @@
</reference>
</component>
- <component name="HTML" t:color="yellow">
+ <component name="HTML" t:color="yellow1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="html"/>
@@ -68,7 +68,7 @@
</reference>
</component>
- <component name="JSONFB" t:color="orange">
+ <component name="JSONFB" t:color="orange1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="jsonfb"/>
diff --git a/sca-cpp/trunk/modules/edit/apps/store/app.composite b/sca-cpp/trunk/modules/edit/apps/store/app.composite
index ec3fa32fa4..6f4bb9f43c 100644
--- a/sca-cpp/trunk/modules/edit/apps/store/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/store/app.composite
@@ -25,7 +25,7 @@
<service name="Store" promote="Store"/>
<service name="ShoppingCart" promote="ShoppingCart"/>
- <component name="Store" t:color="green">
+ <component name="Store" t:color="green1">
<t:implementation.python script="store.py"/>
<service name="Widget">
<t:binding.http uri="store"/>
@@ -35,7 +35,7 @@
<reference name="shoppingTotal" target="ShoppingCart"/>
</component>
- <component name="Catalog" t:color="yellow">
+ <component name="Catalog" t:color="yellow1">
<t:implementation.python script="fruits-catalog.py"/>
<property name="currencyCode">USD</property>
<service name="Catalog">
@@ -44,7 +44,7 @@
<reference name="currencyConverter" target="CurrencyConverter"/>
</component>
- <component name="ShoppingCart" t:color="magenta">
+ <component name="ShoppingCart" t:color="magenta1">
<t:implementation.python script="shopping-cart.py"/>
<service name="ShoppingCart">
<t:binding.http uri="shoppingCart"/>
@@ -52,14 +52,14 @@
<reference name="cache" target="Cache"/>
</component>
- <component name="CurrencyConverter" t:color="blue">
+ <component name="CurrencyConverter" t:color="blue1">
<t:implementation.python script="currency-converter.py"/>
<service name="CurrencyConverter">
<t:binding.jsonrpc uri="currencyConverter"/>
</service>
</component>
- <component name="Cache" t:color="orange">
+ <component name="Cache" t:color="orange1">
<implementation.cpp path="../../components/cache" library="libmemcache"/>
<service name="Cache">
<t:binding.atom uri="cache"/>
diff --git a/sca-cpp/trunk/modules/edit/apps/store2/app.composite b/sca-cpp/trunk/modules/edit/apps/store2/app.composite
index afec3cb1d3..4a549b37c1 100644
--- a/sca-cpp/trunk/modules/edit/apps/store2/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/store2/app.composite
@@ -25,7 +25,7 @@
<service name="Store" promote="Store"/>
<service name="ShoppingCart" promote="ShoppingCart"/>
- <component name="Store" t:color="green">
+ <component name="Store" t:color="green1">
<t:implementation.python script="store.py"/>
<service name="Widget">
<t:binding.http uri="store"/>
@@ -35,7 +35,7 @@
<reference name="shoppingTotal" target="ShoppingCart"/>
</component>
- <component name="Catalog" t:color="yellow">
+ <component name="Catalog" t:color="yellow1">
<t:implementation.python script="fruits-catalog.py"/>
<property name="currencyCode">USD</property>
<service name="Catalog" t:align="top">
@@ -44,7 +44,7 @@
<reference name="currencyConverter" t:align="bottom" target="CurrencyConverter"/>
</component>
- <component name="ShoppingCart" t:color="magenta">
+ <component name="ShoppingCart" t:color="magenta1">
<t:implementation.python script="shopping-cart.py"/>
<service name="ShoppingCart">
<t:binding.http uri="shoppingCart"/>
@@ -52,14 +52,14 @@
<reference name="cache" target="Cache"/>
</component>
- <component name="CurrencyConverter" t:color="blue">
+ <component name="CurrencyConverter" t:color="blue1">
<t:implementation.python script="currency-converter.py"/>
<service name="CurrencyConverter" t:align="top">
<t:binding.jsonrpc uri="currencyConverter"/>
</service>
</component>
- <component name="Cache" t:color="orange">
+ <component name="Cache" t:color="orange1">
<implementation.cpp path="../../components/cache" library="libmemcache"/>
<service name="Cache">
<t:binding.atom uri="cache"/>
diff --git a/sca-cpp/trunk/modules/edit/apps/store3/app.composite b/sca-cpp/trunk/modules/edit/apps/store3/app.composite
index 7cba2c19e1..9ec440435e 100644
--- a/sca-cpp/trunk/modules/edit/apps/store3/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/store3/app.composite
@@ -25,7 +25,7 @@
<service name="Store" promote="Store"/>
<service name="ShoppingCart" promote="ShoppingCart"/>
- <component name="Store" t:color="green">
+ <component name="Store" t:color="green1">
<t:implementation.python script="store.py"/>
<service name="Widget">
<t:binding.http uri="store"/>
@@ -35,7 +35,7 @@
<reference name="shoppingTotal" target="ShoppingCart"/>
</component>
- <component name="Catalog" t:color="yellow">
+ <component name="Catalog" t:color="yellow1">
<t:implementation.python script="fruits-catalog.py"/>
<property name="currencyCode">USD</property>
<service name="Catalog">
@@ -44,7 +44,7 @@
<reference name="currencyConverter" t:align="bottom" target="CurrencyConverter"/>
</component>
- <component name="ShoppingCart" t:color="magenta">
+ <component name="ShoppingCart" t:color="magenta1">
<t:implementation.python script="shopping-cart.py"/>
<service name="ShoppingCart">
<t:binding.http uri="shoppingCart"/>
@@ -52,14 +52,14 @@
<reference name="cache" target="Cache"/>
</component>
- <component name="CurrencyConverter" t:color="blue">
+ <component name="CurrencyConverter" t:color="blue1">
<t:implementation.python script="currency-converter.py"/>
<service name="CurrencyConverter" t:align="top">
<t:binding.jsonrpc uri="currencyConverter"/>
</service>
</component>
- <component name="Cache" t:color="orange">
+ <component name="Cache" t:color="orange1">
<implementation.cpp path="../../components/cache" library="libmemcache"/>
<service name="Cache">
<t:binding.atom uri="cache"/>
diff --git a/sca-cpp/trunk/modules/edit/apps/travel/app.composite b/sca-cpp/trunk/modules/edit/apps/travel/app.composite
index 833944a855..b4cef31135 100644
--- a/sca-cpp/trunk/modules/edit/apps/travel/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/travel/app.composite
@@ -24,7 +24,7 @@
<service name="SCAToursUserInterface" promote="SCAToursUserInterface"/>
- <component name="SCAToursUserInterface" t:color="green">
+ <component name="SCAToursUserInterface" t:color="green1">
<t:implementation.widget location="scatours.html"/>
<service name="Widget">
<t:binding.http uri="/scatours"/>
@@ -80,7 +80,7 @@
<service name="CurrencyConverter"/>
</component>
- <component name="HotelPartner" t:color="orange">
+ <component name="HotelPartner" t:color="orange1">
<implementation.java class="com.tuscanyscatours.hotel.impl.HotelImpl"/>
<service name="Search">
<binding.ws name="searchws" uri="http://localhost:8086/Hotel/Search"/>
@@ -92,7 +92,7 @@
<service name="Book"/>
</component>
- <component name="FlightPartner" t:color="orange">
+ <component name="FlightPartner" t:color="orange1">
<implementation.java class="com.tuscanyscatours.flight.impl.FlightImpl"/>
<service name="Search">
<interface.java interface="com.tuscanyscatours.common.Search"
@@ -106,7 +106,7 @@
<service name="Book"/>
</component>
- <component name="CarPartner" t:color="orange">
+ <component name="CarPartner" t:color="orange1">
<implementation.java class="com.tuscanyscatours.car.impl.CarImpl"/>
<service name="Search">
<binding.ws name="searchws" uri="http://localhost:8086/Car/Search"/>
@@ -170,7 +170,7 @@
<reference name="cartUpdates" target="ShoppingCart/CartUpdates"/>
</component>
- <component name="TripPartner" t:color="orange">
+ <component name="TripPartner" t:color="orange1">
<implementation.java class="com.tuscanyscatours.trip.impl.TripImpl"/>
<service name="Search">
<binding.ws name="searchws" uri="http://localhost:8085/Trip/Search"/>
@@ -191,7 +191,7 @@
</reference>
</component>
- <component name="CartStore" t:color="yellow">
+ <component name="CartStore" t:color="yellow1">
<!-- Add service element to specify alignment -->
<service name="CartStore" t:align="top"/>
<implementation.java class="com.tuscanyscatours.shoppingcart.impl.CartStoreImpl"/>
@@ -220,19 +220,19 @@
</component>
<!-- Add placeholder components representing external endpoints -->
- <component name="HotelSearch" t:color="red">
+ <component name="HotelSearch" t:color="red1">
<service name="HotelSearch"/>
<implementation.java class="com.tuscanyscatours.PlaceHolderImpl" />
</component>
- <component name="FlightSearch" t:color="red">
+ <component name="FlightSearch" t:color="red1">
<service name="FlightSearch"/>
<implementation.java class="com.tuscanyscatours.PlaceHolderImpl" />
</component>
- <component name="CarSearch" t:color="red">
+ <component name="CarSearch" t:color="red1">
<service name="CarSearch"/>
<implementation.java class="com.tuscanyscatours.PlaceHolderImpl" />
</component>
- <component name="TripSearch" t:color="red">
+ <component name="TripSearch" t:color="red1">
<service name="TripSearch"/>
<implementation.java class="com.tuscanyscatours.PlaceHolderImpl" />
</component>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/app/app.html b/sca-cpp/trunk/modules/edit/htdocs/app/app.html
new file mode 100644
index 0000000000..a2cf0e1f60
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/htdocs/app/app.html
@@ -0,0 +1,85 @@
+<!--
+ * 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>
+<link rel="stylesheet" type="text/css" href="/ui.css">
+<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="/scdl.js"></script>
+<script type="text/javascript" src="/ui.js"></script>
+<script type="text/javascript" src="/component.js"></script>
+</head>
+<body>
+
+<table style="position: absolute; top: 0px; left: 0px;" width="100%">
+<tr><th><span>App Listing Information</span><span style="padding-top: 0px; padding-bottom:0px; position: absolute; top: 2px; right: 8px;"><input type="button" id="saveButton" style="font-weight: bold;" Value="Save"/></span></th></tr>
+</table>
+<br>
+<br>
+
+<div>
+<form id="appForm">
+<table width="100%">
+<tr><tr><td><b>App Title:</b></td></tr>
+<tr><td><input type="text" id="appTitle" size="20"/></td></tr>
+</table>
+</form>
+</div>
+
+<script type="text/javascript">
+
+// Init service references
+var editWidget = sca.component("EditWidget");
+var dashboard = sca.reference(editWidget, "dashboard");
+
+/**
+ * The current app name.
+ */
+var appname = ui.queryParams()['app'];
+
+/**
+ * Get and display an app.
+ */
+function getapp(name) {
+ dashboard.get(name, function(doc) {
+ var entry = atom.readATOMEntryDocument(doc);
+ $('appTitle').value = car(entry);
+ });
+}
+
+/**
+ * Save an app.
+ */
+$('saveButton').onclick = function() {
+ var title = $('appTitle').value;
+ var app = mklist(title, appname, mklist());
+ var entry = atom.writeATOMEntry(app);
+
+ dashboard.put(appname, car(entry));
+ return false;
+};
+
+// Get the current app
+getapp(appname);
+
+</script>
+</body>
+</html>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/app/index.html b/sca-cpp/trunk/modules/edit/htdocs/app/index.html
new file mode 100644
index 0000000000..ee07b5d4b7
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/htdocs/app/index.html
@@ -0,0 +1,66 @@
+<!--
+ * 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>App Editor</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-translucent"/>
+<link rel="stylesheet" type="text/css" href="/ui.css"/>
+<script type="text/javascript" src="/util.js"></script>
+<script type="text/javascript" src="/ui.js"></script>
+</head>
+<body>
+<div id="menu"></div>
+
+<br/>
+<h1><span id="title"></span></h1>
+</br>
+
+<div id="app"></div>
+
+<script type="text/javascript">
+/**
+ * The current app name.
+ */
+var appname = ui.queryParams()['app'];
+
+// Load the menu bar
+ui.loadwidget('menu', '/menu.html?app=' + appname);
+
+/**
+ * Display the page editor for an app.
+ */
+function editapp(name) {
+ if (isNil(name))
+ return;
+ $('title').innerHTML = 'Editing: ' + name;
+ $('app').innerHTML =
+ '<iframe id="appFrame" style="height: 100%; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="app.html?' +
+ 'app=' + name +
+ '"></iframe>';
+}
+
+// Display the editor for the current app
+editapp(appname);
+
+</script>
+</body>
+</html>
+
diff --git a/sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html b/sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html
index 71f9c61c41..29de0e396a 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html
@@ -85,7 +85,8 @@ function getapps(sync) {
title = car(entry);
apps += '<tr>';
- apps += '<td><input name="apps" type="checkbox" value="' + name + '">' + '<a href=\"' + '/graph/?app=' + name + '\">' + name + '</a></td>';
+ //apps += '<td><input name="apps" type="checkbox" value="' + name + '">' + '<a href=\"' + '/app/?app=' + name + '\">' + name + '</a></td>';
+ apps += '<td><a href=\"' + '/app/?app=' + name + '\">' + name + '</a></td>';
apps += '<td class="tdw">' + title + '</td>';
apps += '</tr>';
}
diff --git a/sca-cpp/trunk/modules/edit/htdocs/dash/index.html b/sca-cpp/trunk/modules/edit/htdocs/dash/index.html
index 3b3dcc0cd5..60aafcd12e 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/dash/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/dash/index.html
@@ -34,9 +34,10 @@
<div id="dashboard"></div>
<script type="text/javascript">
+// Load the menu bar
ui.loadwidget('menu', '/menu.html');
-// Display the dashboard widget
+// Load the dashboard
ui.loadwidget('dashboard', 'dashboard.html');
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.html b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.html
index 5eb8c6cc1e..b078901a29 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.html
@@ -31,7 +31,7 @@
<body>
<table style="position: absolute; top: 0px; left: 0px;" width="100%">
-<tr><th style="width: 338px;">Palette</th><th style="padding-top: 0px; padding-bottom: 0px;"><span>App</span><span style="position: absolute; top: 2px; right: 8px;"><input type="button" id="saveButton" style="font-weight: bold;" Value="Save"/></span></th></tr>
+<tr><th style="width: 338px;">Palette</th><th style="padding-top: 0px; padding-bottom: 0px;"><span>Composition</span><span style="position: absolute; top: 2px; right: 8px;"><input type="button" id="saveButton" style="font-weight: bold;" Value="Save"/></span></th></tr>
</table>
<script type="text/javascript">
@@ -43,11 +43,14 @@ var apps = sca.reference(editWidget, "apps");
//rconsole = sca.defun(sca.reference(editWidget, "log"), "log");
/**
- * Return the current app name.
+ * The current app name.
*/
-function appname() {
- return ui.queryParams()['app'];
-}
+var appname = ui.queryParams()['app'];
+
+/**
+ * The current app composite.
+ */
+var composite;
/**
* Return the composite in an ATOM entry.
@@ -65,7 +68,8 @@ function getapp(name, g) {
if (isNil(name))
return;
apps.get(name, function(doc) {
- appendNodes(graph.composite(atomcomposite(doc), graph.mkpath().move(350,0)), g);
+ composite = atomcomposite(doc);
+ graph.edit(composite, graph.composite(composite, graph.mkpath().move(350,0)), g);
});
}
@@ -77,7 +81,7 @@ function getpalette(name, g, bg, palette, gpalettes) {
return;
palettes.get(name, function(doc) {
gpalettes[name] = graph.composite(atomcomposite(doc), graph.mkpath().move(150,0));
- appendNodes(gpalettes[name], name == spalette? g : bg);
+ graph.display(gpalettes[name], name == spalette? g : bg);
});
}
@@ -87,16 +91,31 @@ function getpalette(name, g, bg, palette, gpalettes) {
*/
function installpalette(name, pos, g, bg, palette, gpalettes) {
var b = graph.mkbutton(name, pos);
- appendNodes(mklist(b), g);
+ graph.display(mklist(b), g);
b.onclick = function() {
+
// Display the selected palette
spalette = name;
for (var pn in gpalettes)
- appendNodes(gpalettes[pn], pn == spalette? g : bg);
+ graph.display(gpalettes[pn], pn == spalette? g : bg);
}
getpalette(name, g, bg, palette, gpalettes);
}
+/**
+ * Save the current edited page.
+ */
+$('saveButton').onclick = function(e) {
+
+ // Update the page ATOM entry
+ var compxml = writeXML(composite, false);
+ var entry = '<entry xmlns="http://www.w3.org/2005/Atom">' +
+ '<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml"><item>' +
+ compxml + '</item></content></entry>';
+ apps.put(appname, entry, function() {
+ });
+};
+
// Create editor graph area
var g = graph.mkgraph(graph.mkpath().move(0,50));
var bg = graph.mkgroup(graph.mkpath());
@@ -111,7 +130,7 @@ installpalette('social', graph.mkpath().move(0,220), g, bg, spalette, gpalettes)
installpalette('sensors', graph.mkpath().move(0,290), g, bg, spalette, gpalettes);
// Get and display the current app
-getapp(appname(), g);
+getapp(appname, g);
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
index c391afaf23..dc5b48e76a 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
+++ b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
@@ -21,12 +21,12 @@
* SVG and VML composite rendering functions.
*/
-var graph = new Object();
+var graph = {};
/**
* Basic colors
*/
-graph.colors = new Object();
+graph.colors = {};
graph.colors.black = '#000000';
graph.colors.blue = '#0000ff';
graph.colors.cyan = '#00ffff';
@@ -40,6 +40,13 @@ graph.colors.red = '#ff0000';
graph.colors.white = '#ffffff';
graph.colors.yellow = '#ffff00';
+graph.colors.orange1 = '#ffbb00';
+graph.colors.green1 = '#96d333';
+graph.colors.blue1 = '#00c3c9';
+graph.colors.red1 = '#d03f41';
+graph.colors.yellow1 = '#fcee21';
+graph.colors.magenta1 = '#c0688a';
+
/**
* Base path class.
*/
@@ -92,21 +99,31 @@ if (ui.isIE()) {
document.write('<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />');
/**
- * Make a graph.
+ * Make a VML graph.
*/
- graph.mkgraph = function() {
+ graph.mkgraph = function(pos) {
+
+ // 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);
+ // Keep track of the current dragged element
graph.dragging = null;
+ /**
+ * Find the first draggable element in a hierarchy of elements.
+ */
function draggable(n) {
if (n == vmlg)
return null;
@@ -115,53 +132,99 @@ if (ui.isIE()) {
return draggable(n.parentNode);
}
- function bringtotop(n) {
- if (n == vmlg)
- return null;
- n.parentNode.appendChild(n);
- return bringtotop(n.parentNode);
- }
-
+ /**
+ * Handle a mousedown event.
+ */
vmlg.onmousedown = function() {
window.event.returnValue = false;
+
+ // Find draggable element
graph.dragging = draggable(window.event.srcElement);
if (graph.dragging == null)
return false;
- bringtotop(graph.dragging);
+
+ // Bring it to the top
+ graph.bringtotop(graph.dragging, vmlg);
+
+ // Remember mouse position
graph.dragX = window.event.clientX;
graph.dragY = window.event.clientY;
vmlg.setCapture();
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:') {
+ if (ui.csspos(graph.dragging.style.left) >= 350) {
+
+ // Add dragged component to the edited composite
+ if (!isNil(graph.dragging.comp) && isNil(graph.dragging.compos)) {
+ var compos = scdl.composite(vmlg.compos);
+ setlist(compos, graph.addcomp(graph.dragging.comp, compos));
+ graph.dragging.compos = vmlg.compos;
+ }
+ } else {
+
+ // Discard top level element dragged out of composite area
+ vmlg.removeChild(graph.dragging);
+ if (!isNil(graph.dragging.comp) && !isNil(graph.dragging.compos)) {
+ var compos = scdl.composite(vmlg.compos);
+ setlist(compos, graph.removecomp(graph.dragging.comp, compos));
+ graph.dragging.compos = vmlg.compos;
+ }
+ }
+ }
+
+ // Forget current dragged element
graph.dragging = null;
vmlg.releaseCapture();
return false;
};
+ /**
+ * Handle a mousemove event.
+ */
vmlg.onmousemove = function() {
if (graph.dragging == null)
return false;
- var origX = graph.dragging.coordorigin.X;
- var origY = graph.dragging.coordorigin.Y;
- var newX = origX - (window.event.clientX - graph.dragX);
- var newY = origY - (window.event.clientY - graph.dragY);
- graph.dragX = window.event.clientX;
- graph.dragY = window.event.clientY;
- if (graph.dragging.id.substring(0, 8) == 'palette:') {
- // Clone an element dragged from the palette
- var clone = graph.compshape(graph.dragging.comp, mklist(), graph.mkpath().move(ui.posn(graph.dragging.style.left), ui.posn(graph.dragging.style.top)));
- graph.dragging.parentNode.appendChild(clone);
- graph.dragging = clone;
- }
- graph.dragging.setAttribute('coordorigin', newX + ' ' + newY);
+ // Calculate new position of dragged element
+ var origX = ui.csspos(graph.dragging.style.left);
+ var origY = ui.csspos(graph.dragging.style.top);
+ var newX = origX + (window.event.clientX - graph.dragX);
+ var newY = origY + (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;
+
+ // Clone an element dragged from the palette
+ if (graph.dragging.id.substring(0, 8) == 'palette:')
+ graph.dragging = graph.clonepalette(graph.dragging);
+
+ // Move the dragged element
+ graph.dragging.style.left = newX;
+ graph.dragging.style.top = newY;
+
+ // Update dragged component position
+ if (!isNil(graph.dragging.comp))
+ setlist(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.mkpath().move(newX, newY)));
+
return false;
};
+ // Create hidden spans to help compute the width of
+ // component and reference titles
graph.comptitlewidthdiv = document.createElement('span');
graph.comptitlewidthdiv.style.visibility = 'hidden'
graph.comptitlewidthdiv.style.fontWeight = 'bold'
@@ -268,10 +331,14 @@ if (ui.isIE()) {
* Return a shape representing a component.
*/
graph.compshape = function(comp, cassoc, pos) {
+
+ // Make the component title element
var title = graph.comptitle(comp);
+ // Compute the component shape path
var d = graph.comppath(comp, cassoc).str();
+ // Create the main component shape
var shape = document.createElement('v:shape');
shape.style.width = 5000;
shape.style.height = 5000;
@@ -280,6 +347,7 @@ if (ui.isIE()) {
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;
@@ -294,6 +362,7 @@ if (ui.isIE()) {
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;
@@ -325,17 +394,23 @@ if (ui.isIE()) {
* Return a shape representing a button.
*/
graph.mkbutton = function(t, pos) {
+
+ // Make the title element
var title = graph.mktitle(t, true, pos);
+
+ // Compute the path of the button shape
var d = graph.buttonpath().str();
+ // 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 = d;
- shape.fillcolor = graph.colors.blue;
+ shape.fillcolor = graph.colors.blue1;
shape.stroked = 'false';
+ // Create an overlay contour shape
var contour = document.createElement('v:shape');
contour.style.width = 5000;
contour.style.height = 5000;
@@ -350,6 +425,7 @@ if (ui.isIE()) {
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;
@@ -370,9 +446,11 @@ if (ui.isIE()) {
graph.svgns='http://www.w3.org/2000/svg';
/**
- * Make a graph.
+ * Make an SVG graph.
*/
graph.mkgraph = function(pos) {
+
+ // Create a div element to host the graph
var div = document.createElement('div');
div.id = 'svgdiv';
div.style.position = 'absolute';
@@ -381,13 +459,18 @@ if (ui.isIE()) {
// -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);
+ // Keep track of current dragged element
graph.dragging = null;
+ /**
+ * Find the first draggable element in a hierarchy of elements.
+ */
function draggable(n) {
if (n == svg)
return null;
@@ -396,37 +479,70 @@ if (ui.isIE()) {
return draggable(n.parentNode);
}
- function bringtotop(n) {
- if (n == svg)
- return null;
- n.parentNode.appendChild(n);
- return bringtotop(n.parentNode);
- }
-
+ /**
+ * Handle a mouse down event.
+ */
svg.onmousedown = function(e) {
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
+
+ // Find draggable element
graph.dragging = draggable(e.target);
if (graph.dragging == null)
return false;
- bringtotop(graph.dragging);
+
+ // Bring it to the top
+ graph.bringtotop(graph.dragging, svg);
+
+ // Remember the mouse position
var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
graph.dragX = pos.screenX;
graph.dragY = pos.screenY;
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 pmatrix = graph.dragging.parentNode.getCTM();
+ var matrix = graph.dragging.getCTM();
+ var curX = pmatrix != null? (Number(matrix.e) - Number(pmatrix.e)): Number(matrix.e);
+ if (curX >= 350) {
+
+ // Add dragged component to the edited composite
+ if (!isNil(graph.dragging.comp) && isNil(graph.dragging.compos)) {
+ var compos = scdl.composite(svg.compos);
+ setlist(compos, graph.addcomp(graph.dragging.comp, compos));
+ graph.dragging.compos = svg.compos;
+ }
+ } else {
+
+ // Discard top level element dragged out of composite area
+ svg.removeChild(graph.dragging);
+ if (!isNil(graph.dragging.comp) && !isNil(graph.dragging.compos)) {
+ var compos = scdl.composite(svg.compos);
+ setlist(compos, graph.removecomp(graph.dragging.comp, compos));
+ graph.dragging.compos = svg.compos;
+ }
+ }
+ }
+
+ // Forget current dragged element
graph.dragging = null;
return false;
};
+ // Support touch devices
window.top.onmouseup = window.onmouseup;
window.ontouchend = window.onmouseup;
window.gestureend = window.onmouseup;
@@ -435,6 +551,9 @@ if (ui.isIE()) {
window.ontouchcancel = window.onmouseup;
window.top.ontouchcancel = window.onmouseup;
+ /**
+ * Handle a mouse move event.
+ */
window.onmousemove = function(e) {
if (graph.dragging == null)
return false;
@@ -442,6 +561,8 @@ if (ui.isIE()) {
e.preventDefault();
else
e.returnValue = false;
+
+ // Calculate new position of dragged element
var pmatrix = graph.dragging.parentNode.getCTM();
var matrix = graph.dragging.getCTM();
var curX = pmatrix != null? (Number(matrix.e) - Number(pmatrix.e)): Number(matrix.e);
@@ -458,20 +579,27 @@ if (ui.isIE()) {
else
newY = 0;
- if (graph.dragging.id.substring(0, 8) == 'palette:') {
- // Clone an element dragged from the palette
- var clone = graph.compshape(graph.dragging.comp, mklist(), graph.mkpath());
- graph.dragging.parentNode.appendChild(clone);
- graph.dragging = clone;
- }
+ // Clone an element dragged from the palette
+ if (graph.dragging.id.substring(0, 8) == 'palette:')
+ graph.dragging = graph.clonepalette(graph.dragging);
+
+ // Move the dragged element
graph.dragging.setAttribute('transform', 'translate(' + newX + ',' + newY + ')');
+
+ // Update dragged component position
+ if (!isNil(graph.dragging.comp))
+ setlist(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.mkpath().move(newX, newY)));
+
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 = 0;
@@ -571,14 +699,19 @@ if (ui.isIE()) {
* Return a shape representing a component.
*/
graph.compshape = function(comp, cassoc, pos) {
+
+ // Make the component title
var title = graph.comptitle(comp);
+ // Compute the path of the component shape
var d = graph.comppath(comp, cassoc).str();
+ // Create the main component shape
var shape = document.createElementNS(graph.svgns, 'path');
shape.setAttribute('d', d);
shape.setAttribute('fill', graph.color(comp));
+ // Create an overlay contour shape
var contour = document.createElementNS(graph.svgns, 'path');
contour.setAttribute('d', d);
contour.setAttribute('fill', 'none');
@@ -587,6 +720,7 @@ if (ui.isIE()) {
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() + ')');
@@ -613,13 +747,19 @@ if (ui.isIE()) {
* Return a shape representing a button.
*/
graph.mkbutton = function(t, pos) {
+
+ // Make the button title
var title = graph.mktitle(t, true);
+
+ // Compute the path of the button shape
var d = graph.buttonpath().str();
+ // Create the main button shape
var shape = document.createElementNS(graph.svgns, 'path');
shape.setAttribute('d', d);
- shape.setAttribute('fill', graph.colors.blue);
+ shape.setAttribute('fill', graph.colors.blue1);
+ // Create an overlay contour shape
var contour = document.createElementNS(graph.svgns, 'path');
contour.setAttribute('d', d);
contour.setAttribute('fill', 'none');
@@ -628,6 +768,7 @@ if (ui.isIE()) {
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);
@@ -638,6 +779,16 @@ if (ui.isIE()) {
}
/**
+ * Bring an element and its parents to the top.
+ */
+graph.bringtotop = function(n, g) {
+ if (n == g)
+ return null;
+ n.parentNode.appendChild(n);
+ return graph.bringtotop(n.parentNode, g);
+}
+
+/**
* Return the title of a SCDL element.
*/
graph.title = function(e) {
@@ -646,7 +797,17 @@ graph.title = function(e) {
};
/**
- * Return the services and references of a component.
+ * Return the color of a component.
+ */
+graph.color = function(comp) {
+ return memo(comp, 'color', function() {
+ var c = scdl.color(comp);
+ return c == null? graph.colors.blue1 : graph.colors[c];
+ });
+};
+
+/**
+ * Return the services on the top side of a component.
*/
graph.tsvcs = function(comp) {
return memo(comp, 'tsvcs', function() {
@@ -658,6 +819,9 @@ graph.tsvcs = function(comp) {
});
};
+/**
+ * Return the services on the left side of a component.
+ */
graph.lsvcs = function(comp) {
return memo(comp, 'lsvcs', function() {
var svcs = scdl.services(comp);
@@ -676,12 +840,18 @@ graph.lsvcs = function(comp) {
});
};
+/**
+ * Return the references on the bottom side of a component.
+ */
graph.brefs = function(comp) {
return memo(comp, 'brefs', function() {
return filter(function(r) { return scdl.align(r) == 'bottom'; }, scdl.references(comp));
});
};
+/**
+ * Return the references on the right side of a component.
+ */
graph.rrefs = function(comp) {
return memo(comp, 'rrefs', function() {
return filter(function(r) { var a = scdl.align(r); return a == null || a == 'right'; }, scdl.references(comp));
@@ -689,16 +859,6 @@ graph.rrefs = function(comp) {
};
/**
- * Return the color of a component.
- */
-graph.color = function(comp) {
- return memo(comp, 'color', function() {
- var c = scdl.color(comp);
- return c == null? graph.colors.blue : graph.colors[c];
- });
-};
-
-/**
* Return the height of a reference on the right side of a component.
*/
graph.rrefheight = function(ref, cassoc) {
@@ -861,33 +1021,43 @@ graph.tsvcpath = function(svc, cassoc, path) {
* Return a path representing a component.
*/
graph.comppath = function(comp, cassoc) {
- var height = graph.compheight(comp, cassoc);
+
+ // Calculate the width and height of the component shape
var width = graph.compwidth(comp, cassoc);
+ var height = graph.compheight(comp, cassoc);
+ /**
+ * Apply a path rendering function to a list of services or references.
+ */
function renderpath(x, f, cassoc, path) {
if (isNil(x))
return path;
return renderpath(cdr(x), f, cassoc, f(car(x), cassoc, path));
}
+ // Render the services on the top side of the component
var tsvcs = graph.tsvcs(comp);
var path = graph.mkpath().move(10,0);
path = renderpath(tsvcs, graph.tsvcpath, cassoc, path);
+ // Render the references on the right side of the component
var rrefs = graph.rrefs(comp);
path = path.line(width - 10,path.ypos()).rcurve(10,0,0,10);
path = renderpath(rrefs, graph.rrefpath, cassoc, path);
+ // Render the references on the bottom side of the component
var brefs = reverse(graph.brefs(comp));
var boffset = 10 + graph.brefswidth(brefs, cassoc);
path = path.line(path.xpos(),height - 10).rcurve(0,10,-10,0).line(boffset, path.ypos());
path = renderpath(brefs, graph.brefpath, cassoc, path);
+ // Render the services on the top side of the component
var lsvcs = graph.lsvcs(comp);
var loffset = 10 + (length(lsvcs) * 60);
path = path.line(10,path.ypos()).rcurve(-10,0,0,-10).line(path.xpos(), loffset);
path = renderpath(lsvcs, graph.lsvcpath, cassoc, path);
+ // Close the component shape path
path = path.line(0,10).rcurve(0,-10,10,0);
return path.end();
};
@@ -915,15 +1085,31 @@ graph.composite = function(compos, pos) {
var cassoc = scdl.nameToElementAssoc(comps);
var proms = scdl.promotions(compos);
+ /**
+ * Render a component.
+ */
function rendercomp(comp, cassoc, pos) {
+
+ /**
+ * Render the references on the right side of a component.
+ */
function renderrrefs(refs, cassoc, pos) {
+
+ /**
+ * Render a reference on the right side of a component.
+ */
function renderrref(ref, cassoc, pos) {
var target = assoc(scdl.target(ref), cassoc);
if (isNil(target))
return mklist();
+
+ // Render the component target of the reference
return rendercomp(cadr(target), cassoc, pos);
}
+ /**
+ * Move the rendering cursor down below a reference.
+ */
function rendermove(ref, cassoc, pos) {
return pos.clone().rmove(0, graph.rrefheight(ref, cassoc));
}
@@ -933,14 +1119,26 @@ graph.composite = function(compos, pos) {
return append(renderrref(car(refs), cassoc, pos), renderrrefs(cdr(refs), cassoc, rendermove(car(refs), cassoc, pos)));
}
+ /**
+ * Render the references on the bottom side of a component.
+ */
function renderbrefs(refs, cassoc, pos) {
+
+ /**
+ * Render a reference on the bottom side of a component.
+ */
function renderbref(ref, cassoc, pos) {
var target = assoc(scdl.target(ref), cassoc);
if (isNil(target))
return mklist();
+
+ // Render the component target of the reference
return rendercomp(cadr(target), cassoc, pos);
}
+ /**
+ * Move the rendering cursor to the right of a reference.
+ */
function rendermove(ref, cassoc, pos) {
return pos.clone().rmove(graph.brefwidth(ref, cassoc), 0);
}
@@ -950,8 +1148,11 @@ graph.composite = function(compos, pos) {
return append(renderbref(car(refs), cassoc, pos), renderbrefs(cdr(refs), cassoc, rendermove(car(refs), cassoc, pos)));
}
+ // Compute the component shape
var gcomp = graph.compshape(comp, cassoc, pos);
+ // Add the shapes of the components wired to its references
+ // as children elements
var rrefs = graph.rrefs(comp);
var rpos = graph.mkpath().rmove(graph.compwidth(comp, cassoc), 0);
appendNodes(renderrrefs(rrefs, cassoc, rpos), gcomp);
@@ -963,7 +1164,14 @@ graph.composite = function(compos, pos) {
return mklist(gcomp);
}
+ /**
+ * Render a list of promoted service components.
+ */
function renderproms(svcs, cassoc, pos) {
+
+ /**
+ * Return the component promoted by a service.
+ */
function promcomp(svc, cassoc) {
var c = assoc(scdl.promote(svc), cassoc);
if (isNil(c))
@@ -971,12 +1179,18 @@ graph.composite = function(compos, pos) {
return cadr(c);
}
+ /**
+ * Return the position of a component.
+ */
function comppos(comp, pos) {
var x = scdl.x(comp);
var y = scdl.y(comp);
- return graph.mkpath().move(x != null? x : pos.xpos(), y != null? y : pos.ypos());
+ return graph.mkpath().move(x != null? Number(x) + 350 : pos.xpos(), y != null? Number(y) : pos.ypos());
}
+ /**
+ * Move the rendering cursor down below a component.
+ */
function rendermove(comp, cassoc, pos) {
return pos.clone().rmove(0, graph.compclosureheight(comp, cassoc) + 40);
}
@@ -984,6 +1198,8 @@ graph.composite = function(compos, pos) {
if (isNil(svcs))
return mklist();
+ // Render the first promoted component in the list
+ // then recurse to render the rest of the list
var comp = promcomp(car(svcs), cassoc);
if (isNil(comp))
return renderproms(cdr(svcs), cassoc, rendermove(car(svcs), cassoc, pos));
@@ -992,13 +1208,85 @@ graph.composite = function(compos, pos) {
return append(rendercomp(comp, cassoc, cpos), renderproms(cdr(svcs), cassoc, rendermove(comp, cassoc, cpos)));
}
+ // Render the promoted service components
var rproms = renderproms(proms, cassoc, pos.clone().rmove(20,20));
- if (name == 'palette')
+ if (name == 'palette') {
+
+ // 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
+ return map(function(r) {
+ r.compos = compos;
+ return r;
+ }, rproms);
+ }
return rproms;
};
+/**
+ * Clone a palette element and the component associated with it.
+ */
+graph.clones = 0;
+graph.clonepalette = function(e) {
+
+ // Clone the component and give it a unique name
+ var comp = append(mklist(element, "'component", mklist(attribute, "'name", scdl.name(e.comp) + (++graph.clones))),
+ filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e.comp)));
+
+ // Make the component shape element
+ var clone = graph.compshape(comp, mklist(), graph.mkpath());
+ e.parentNode.appendChild(clone);
+ return clone;
+};
+
+/**
+ * Move a component to the given position.
+ */
+graph.movecomp = function(comp, pos) {
+
+ // Add or set the x and y attributes of the component
+ return append(mklist(element, "'component", mklist(attribute, "'t:x", '' + (pos.xpos() - 350)), mklist(attribute, "'t:y", '' + pos.ypos())),
+ filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'t:x" || attributeName(e) == "'t:y")); }, elementChildren(comp)));
+};
+
+/**
+ * Add a component to a composite.
+ */
+graph.addcomp = function(comp, compos) {
+ var name = scdl.name(comp);
+ var prom = mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name));
+ return append(mklist(element, "'composite"), append(elementChildren(compos), mklist(prom, graph.dragging.comp)));
+}
+
+/**
+ * Remove a component from a composite.
+ */
+graph.removecomp = function(comp, compos) {
+ var name = scdl.name(comp);
+ return append(mklist(element, "'composite"),
+ filter(function(c) { return !(isElement(c) && scdl.name(c) == name); }, elementChildren(compos)));
+}
+
+/**
+ * Display a list of graphical nodes.
+ */
+graph.display = function(nodes, g) {
+ appendNodes(nodes, g);
+ return nodes;
+};
+
+/**
+ * Display and enable editing of a composite and the graphical
+ * nodes that represent it.
+ */
+graph.edit = function(compos, nodes, g) {
+ g.compos = compos;
+ return graph.display(nodes, g);
+};
+
diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/index.html b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
index aebc0ece68..e1f0bacdeb 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
@@ -18,7 +18,7 @@
-->
<html>
<head>
-<title>App Editor</title>
+<title>App Composition Editor</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-translucent"/>
@@ -37,14 +37,12 @@
<script type="text/javascript">
/**
- * Return the current app name.
+ * The current app name.
*/
-function appname() {
- return ui.queryParams()['app'];
-}
+var appname = ui.queryParams()['app'];
// Load the menu bar
-ui.loadwidget('menu', '/menu.html?app=' + appname());
+ui.loadwidget('menu', '/menu.html?app=' + appname);
/**
* Display the editor for an app.
@@ -60,7 +58,7 @@ function editapp(name) {
}
// Display the editor for the current app
-editapp(appname());
+editapp(appname);
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/index.html b/sca-cpp/trunk/modules/edit/htdocs/index.html
index 4dde5b543d..d0736ba295 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/index.html
@@ -37,10 +37,13 @@
<p>Try the <a href="dash">App Dashboard</a> to manage your collection of apps.</p>
<h2>App Editor</h2>
-<p>Try the <a href="graph/?app=store">App Editor</a> to edit an app.</p>
+<p>Try the <a href="app/?app=store">App Editor</a> to edit an app.</p>
+
+<h2>Composition Editor</h2>
+<p>Try the <a href="graph/?app=store">Composition Editor</a> to compose an app.</p>
<h2>Page Editor</h2>
-<p>Try the <a href="page/?app=store">Page Editor</a> to edit an app page.</p>
+<p>Try the <a href="page/?app=store">Page Editor</a> to draw an app page.</p>
<script type="text/javascript">
ui.loadwidget('menu', '/menu.html');
diff --git a/sca-cpp/trunk/modules/edit/htdocs/menu.html b/sca-cpp/trunk/modules/edit/htdocs/menu.html
index 7155e2fc55..21677c5602 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/menu.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/menu.html
@@ -40,7 +40,7 @@ var mdiv = $('menu');
var name = appname();
mdiv.innerHTML = ui.menubar(
append(mklist(ui.menu('Home', '/'), ui.menu('Dashboard', '/dash')),
- (isNil(name) || name == 'undefined')? mklist() : mklist(ui.menu('App', '/graph/?app=' + name), ui.menu('Page', '/page/?app=' + name))),
+ (isNil(name) || name == 'undefined')? mklist() : mklist(ui.menu('App', '/app/?app=' + name), ui.menu('Composition', '/graph/?app=' + name), ui.menu('Page', '/page/?app=' + name))),
mklist(ui.menu('Sign out', '/logout')));
</script>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/index.html b/sca-cpp/trunk/modules/edit/htdocs/page/index.html
index 92f286fdc6..5f9d93efed 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/page/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/page/index.html
@@ -37,14 +37,12 @@
<script type="text/javascript">
/**
- * Return the current app name.
+ * The current app name.
*/
-function appname() {
- return ui.queryParams()['app'];
-}
+var appname = ui.queryParams()['app'];
// Load the menu bar
-ui.loadwidget('menu', '/menu.html?app=' + appname());
+ui.loadwidget('menu', '/menu.html?app=' + appname);
/**
* Display the page editor for an app.
@@ -60,7 +58,7 @@ function editapp(name) {
}
// Display the editor for the current app
-editapp(appname());
+editapp(appname);
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/page.html b/sca-cpp/trunk/modules/edit/htdocs/page/page.html
index e2cd50088e..202fb7aacc 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/page/page.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/page/page.html
@@ -57,11 +57,9 @@ var editWidget = sca.component("EditWidget");
var pages = sca.reference(editWidget, "pages");
/**
- * Return the current app name.
+ * The current app name.
*/
-function appname() {
- return ui.queryParams()['app'];
-}
+var appname = ui.queryParams()['app'];
/**
* Return the page in an ATOM entry.
@@ -79,6 +77,7 @@ function getpage(name, edit) {
if (isNil(name))
return;
pages.get(name, function(doc) {
+
// Convert the page to XHTML
var xhtml = writeStrings(writeXML(atompage(doc), false));
@@ -88,7 +87,7 @@ function getpage(name, edit) {
// Append page nodes to editor
map(function(e) {
- e.style.left = ui.posn(e.style.left) + 350;
+ e.style.left = ui.csspos(e.style.left) + 350;
edit.appendChild(e);
return page.cover(e);
}, nodeList(buffer.childNodes[0].childNodes));
@@ -99,6 +98,7 @@ function getpage(name, edit) {
* Save the current edited page.
*/
$('saveButton').onclick = function(e) {
+
// Copy page DOM to hidden buffer
var edit = $('page');
var buffer = $('buffer');
@@ -114,8 +114,8 @@ $('saveButton').onclick = function(e) {
div.removeChild(e);
return e;
}
- var x = ui.posn(e.style.left) - 350;
- if (x < 0 || ui.posn(e.style.top) < 0) {
+ var x = ui.csspos(e.style.left) - 350;
+ if (x < 0 || ui.csspos(e.style.top) < 0) {
div.removeChild(e);
return e;
}
@@ -128,11 +128,11 @@ $('saveButton').onclick = function(e) {
var xhtml = writeStrings(writeXML(lxhtml, false));
// Update the page ATOM entry
- var name = appname();
- var entry = '<entry xmlns="http://www.w3.org/2005/Atom"><title type="text">' + name + '</title><id>' + name + '</id><content type="application/xml"><item>' +
+ var entry = '<entry xmlns="http://www.w3.org/2005/Atom">' +
+ '<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml"><item>' +
xhtml + '</item></content></entry>';
- pages.put(name, entry, function(e) {});
+ pages.put(appname, entry, function(e) {});
};
// Initialize the page editor
@@ -140,7 +140,7 @@ var edit = $('page');
page.initpage(edit);
// Get and display the current app page
-getpage(appname(), edit);
+getpage(appname, edit);
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/page.js b/sca-cpp/trunk/modules/edit/htdocs/page/page.js
index 25f6399075..4628ec1235 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/page/page.js
+++ b/sca-cpp/trunk/modules/edit/htdocs/page/page.js
@@ -20,56 +20,66 @@
/**
* Page editing functions.
*/
-var page = new Object();
+var page = {};
if (ui.isIE()) {
/**
- * Init a page editor.
+ * Init a page editor. IE-specific implementation.
*/
page.initpage = function(elem) {
- page.dragging = null;
- function draggable(n) {
- if (n == elem)
- return null;
- if (n.id != '')
- return n;
- if (n.covered)
- return n.covered;
- return draggable(n.parentNode);
- }
-
- function bringtotop(n) {
- n.parentNode.appendChild(n);
- n.cover.parentNode.appendChild(n.cover);
- }
+ // Keep track of the current dragged element
+ page.dragging = null;
+ /**
+ * Handle a mouse down event.
+ */
elem.onmousedown = function() {
window.event.returnValue = false;
- page.dragging = draggable(window.event.srcElement);
+
+ // Find a draggable element
+ page.dragging = page.draggable(window.event.srcElement, elem);
if (page.dragging == null)
return false;
- bringtotop(page.dragging);
+
+ // Bring it to the top
+ page.bringtotop(page.dragging);
+
+ // Save the mouse position
page.dragX = window.event.clientX;
page.dragY = window.event.clientY;
elem.setCapture();
return false;
};
+ /**
+ * Handle a mouse up event.
+ */
elem.onmouseup = function() {
if (page.dragging == null)
return false;
+
+ // Discard element dragged out of page area
+ if (ui.csspos(page.dragging.style.left) < 350 && page.dragging.id.substring(0, 8) != 'palette:')
+ page.dragging.parentNode.removeChild(page.dragging);
+
+ // Forget current dragged element
page.dragging = null;
elem.releaseCapture();
return false;
};
+ /**
+ * Handle a mouse move event.
+ */
elem.onmousemove = function() {
if (page.dragging == null)
return false;
- var curX = ui.posn(page.dragging.style.left);
- var curY = ui.posn(page.dragging.style.top);
+
+ // Compute dragged element position
+ var curX = ui.csspos(page.dragging.style.left);
+ var curY = ui.csspos(page.dragging.style.top);
var newX = curX + (window.event.clientX - page.dragX);
var newY = curY + (window.event.clientY - page.dragY);
if (newX >= 0)
@@ -81,10 +91,11 @@ if (ui.isIE()) {
else
newY = 0;
- if (page.dragging.id.substring(0, 8) == 'palette:') {
- // Clone the dragged element
+ // Clone element dragged from palette
+ if (page.dragging.id.substring(0, 8) == 'palette:')
page.dragging = page.clone(page.dragging);
- }
+
+ // Move dragged element
page.dragging.style.left = newX;
page.dragging.style.top = newY;
page.dragging.cover.style.left = newX;
@@ -92,7 +103,8 @@ if (ui.isIE()) {
};
- // Cover child elements with span elements
+ // Cover child elements with span elements to prevent
+ // any input events to reach them
map(page.cover, nodeList(elem.childNodes));
return elem;
@@ -101,59 +113,69 @@ if (ui.isIE()) {
} else {
/**
- * Init a page editor.
+ * Init a page editor. Generic implementation for all other browsers.
*/
page.initpage = function(elem) {
page.dragging = null;
- function draggable(n) {
- if (n == elem)
- return null;
- if (n.id != '')
- return n;
- if (n.covered)
- return n.covered;
- return draggable(n.parentNode);
- }
-
- function bringtotop(n) {
- n.parentNode.appendChild(n);
- n.cover.parentNode.appendChild(n.cover);
- }
-
+ /**
+ * Handle a mouse down event.
+ */
elem.onmousedown = function(e) {
if (e.preventDefault)
e.preventDefault();
else
e.returnValue = false;
- page.dragging = draggable(e.target);
+
+ // Find a draggable element
+ page.dragging = page.draggable(e.target, elem);
if (page.dragging == null)
return false;
- bringtotop(page.dragging);
+
+ // Bring it to the top
+ page.bringtotop(page.dragging);
+
+ // Remember mouse position
var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
page.dragX = pos.screenX;
page.dragY = pos.screenY;
return false;
};
+ // Support touch devices
elem.ontouchstart = elem.onmousedown;
+ /**
+ * Handle a mouse up event.
+ */
window.onmouseup = function(e) {
if (page.dragging == null)
return false;
+
+ // Discard element if dragged out of page area
+ if (ui.csspos(page.dragging.style.left) < 350 && page.dragging.id.substring(0, 8) != 'palette:')
+ page.dragging.parentNode.removeChild(page.dragging);
+
+ // Forget dragged element
page.dragging = null;
return false;
};
+ // Support touch devices
window.top.onmouseup = window.onmouseup;
window.ontouchend = window.onmouseup;
window.top.ontouchend = window.onmouseup;
+ /**
+ * Handle a mouse move event.
+ */
window.onmousemove = function(e) {
if (page.dragging == null)
return false;
- var curX = ui.posn(page.dragging.style.left);
- var curY = ui.posn(page.dragging.style.top);
+
+ // Compute position of dragged element
+ var curX = ui.csspos(page.dragging.style.left);
+ var curY = ui.csspos(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);
@@ -166,10 +188,12 @@ if (ui.isIE()) {
else
newY = 0;
+ // Clone element dragged from palette
if (page.dragging.id.substring(0, 8) == 'palette:') {
- // Clone the dragged element
page.dragging = page.clone(page.dragging);
}
+
+ // Move the dragged element
page.dragging.style.left = newX;
page.dragging.style.top = newY;
page.dragging.cover.style.left = newX;
@@ -177,11 +201,13 @@ if (ui.isIE()) {
return false;
};
+ // Support touch devices
window.top.onmousemove = window.onmousemove;
window.ontouchmove = window.onmousemove;
window.top.ontouchmove = window.onmousemove;
- // Cover child elements with span elements
+ // Cover child elements with span elements to prevent
+ // any input events to reach them
map(page.cover, nodeList(elem.childNodes));
return elem;
@@ -189,15 +215,37 @@ if (ui.isIE()) {
}
/**
- * Cover a page element with a <span> element to prevent mouse events to reach it.
+ * Find a draggable element in a hierarchy of elements.
+ */
+page.draggable = function(n, e) {
+ if (n == e)
+ return null;
+ if (n.id != '')
+ return n;
+ if (n.covered)
+ return n.covered;
+ return page.draggable(n.parentNode, e);
+}
+
+/**
+ * Bring an element and its parent to the top.
+ */
+page.bringtotop = function(n) {
+ n.parentNode.appendChild(n);
+ n.cover.parentNode.appendChild(n.cover);
+}
+
+/**
+ * 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');
cover.style.position = 'absolute';
- cover.style.left = ui.posn(e.style.left) - 5;
- cover.style.top = ui.posn(e.style.top) - 5;
+ cover.style.left = ui.csspos(e.style.left) - 5;
+ cover.style.top = ui.csspos(e.style.top) - 5;
cover.style.width = e.clientWidth + 10;
cover.style.height = e.clientHeight + 10;
cover.style.visibility = 'visible';
@@ -208,20 +256,31 @@ page.cover = function(e) {
}
/**
- * Clone a page element.
+ * Clone a palette element.
*/
page.clone = function(e) {
+
+ /**
+ * Clone an element's HTML.
+ */
function mkclone(e) {
var ne = document.createElement('span');
+
+ // Skip the palette: prefix
ne.id = e.id.substr(8);
+
+ // Copy the HTML content
ne.innerHTML = e.innerHTML;
return ne;
}
+ /**
+ * Clone an element's position.
+ */
function posclone(ne, e) {
ne.style.position = 'absolute';
- ne.style.left = ui.posn(e.style.left);
- ne.style.top = ui.posn(e.style.top);
+ ne.style.left = ui.csspos(e.style.left);
+ ne.style.top = ui.csspos(e.style.top);
e.parentNode.appendChild(ne);
page.cover(ne);
return ne;
diff --git a/sca-cpp/trunk/modules/edit/palettes/control/palette.composite b/sca-cpp/trunk/modules/edit/palettes/control/palette.composite
index 56c50a4e48..acb1c15755 100644
--- a/sca-cpp/trunk/modules/edit/palettes/control/palette.composite
+++ b/sca-cpp/trunk/modules/edit/palettes/control/palette.composite
@@ -28,7 +28,7 @@
<service name="ifelse" promote="ifelse"/>
<service name="foreach" promote="foreach"/>
- <component name="page" t:color="yellow">
+ <component name="page" t:color="yellow1">
<documentation>when page requested</documentation>
<t:implementation.python script="page.py"/>
<service name="page" t:visible="false"/>
@@ -36,7 +36,7 @@
<reference name="do" t:align="bottom"/>
</component>
- <component name="every" t:color="yellow">
+ <component name="every" t:color="yellow1">
<documentation>every n seconds</documentation>
<t:implementation.python script="every.py"/>
<service name="every" t:visible="false"/>
@@ -44,14 +44,14 @@
<reference name="do" t:align="bottom"/>
</component>
- <component name="if" t:color="yellow">
+ <component name="if" t:color="yellow1">
<t:implementation.python script="if_.py"/>
<service name="if" t:align="top"/>
<reference name="condition"/>
<reference name="do" t:align="bottom"/>
</component>
- <component name="ifelse" t:color="yellow">
+ <component name="ifelse" t:color="yellow1">
<documentation>if else</documentation>
<t:implementation.python script="ifelse.py"/>
<service name="ifelse" t:align="top"/>
@@ -60,7 +60,7 @@
<reference name="else" t:align="bottom"/>
</component>
- <component name="foreach" t:color="yellow">
+ <component name="foreach" t:color="yellow1">
<documentation>for each</documentation>
<t:implementation.python script="ifelse.py"/>
<service name="foreach" t:align="top"/>
diff --git a/sca-cpp/trunk/modules/edit/palettes/operators/palette.composite b/sca-cpp/trunk/modules/edit/palettes/operators/palette.composite
index 35f8dfdf9c..54fd47768a 100644
--- a/sca-cpp/trunk/modules/edit/palettes/operators/palette.composite
+++ b/sca-cpp/trunk/modules/edit/palettes/operators/palette.composite
@@ -35,37 +35,37 @@
<service name="add" promote="add"/>
<service name="subtract" promote="subtract"/>
- <component name="true" t:color="green">
+ <component name="true" t:color="green1">
<t:implementation.python script="true_.py"/>
<service name="true"/>
</component>
- <component name="false" t:color="green">
+ <component name="false" t:color="green1">
<t:implementation.python script="false_.py"/>
<service name="false"/>
</component>
- <component name="and" t:color="green">
+ <component name="and" t:color="green1">
<t:implementation.python script="and_.py"/>
<service name="and"/>
<reference name="value1"/>
<reference name="value2"/>
</component>
- <component name="or" t:color="green">
+ <component name="or" t:color="green1">
<t:implementation.python script="or_.py"/>
<service name="or"/>
<reference name="value1"/>
<reference name="value2"/>
</component>
- <component name="not" t:color="green">
+ <component name="not" t:color="green1">
<t:implementation.python script="not_.py"/>
<service name="not"/>
<reference name="value"/>
</component>
- <component name="equals" t:color="green">
+ <component name="equals" t:color="green1">
<documentation>=</documentation>
<t:implementation.python script="equals.py"/>
<service name="equals">
@@ -75,7 +75,7 @@
<reference name="value2"/>
</component>
- <component name="greater" t:color="green">
+ <component name="greater" t:color="green1">
<documentation>gt</documentation>
<t:implementation.python script="greater.py"/>
<service name="greater">
@@ -85,7 +85,7 @@
<reference name="value2"/>
</component>
- <component name="lesser" t:color="green">
+ <component name="lesser" t:color="green1">
<documentation>lt</documentation>
<t:implementation.python script="lesser.py"/>
<service name="lesser">
@@ -95,7 +95,7 @@
<reference name="value2"/>
</component>
- <component name="multiply" t:color="green">
+ <component name="multiply" t:color="green1">
<documentation>*</documentation>
<t:implementation.python script="multiply.py"/>
<service name="multiply">
@@ -105,7 +105,7 @@
<reference name="value2"/>
</component>
- <component name="divide" t:color="green">
+ <component name="divide" t:color="green1">
<documentation>/</documentation>
<t:implementation.python script="divide.py"/>
<service name="divide">
@@ -115,7 +115,7 @@
<reference name="value2"/>
</component>
- <component name="add" t:color="green">
+ <component name="add" t:color="green1">
<documentation>+</documentation>
<t:implementation.python script="add.py"/>
<service name="add">
@@ -125,7 +125,7 @@
<reference name="value2"/>
</component>
- <component name="subtract" t:color="green">
+ <component name="subtract" t:color="green1">
<documentation>-</documentation>
<t:implementation.python script="subtract.py"/>
<service name="subtract">
diff --git a/sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite b/sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite
index 20ef8225ce..87381f24f4 100644
--- a/sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite
+++ b/sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite
@@ -24,7 +24,7 @@
<service name="location" promote="location"/>
- <component name="location" t:color="magenta">
+ <component name="location" t:color="magenta1">
<t:implementation.python script="location.py"/>
<service name="location"/>
</component>
diff --git a/sca-cpp/trunk/modules/edit/palettes/social/palette.composite b/sca-cpp/trunk/modules/edit/palettes/social/palette.composite
index 264e2ed137..739b878025 100644
--- a/sca-cpp/trunk/modules/edit/palettes/social/palette.composite
+++ b/sca-cpp/trunk/modules/edit/palettes/social/palette.composite
@@ -28,7 +28,7 @@
<service name="HTML" promote="HTML"/>
<service name="JSONFB" promote="JSONFB"/>
- <component name="JSONTwit" t:color="red">
+ <component name="JSONTwit" t:color="blue1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="jsontwit"/>
@@ -38,7 +38,7 @@
</reference>
</component>
- <component name="XMLTwit" t:color="green">
+ <component name="XMLTwit" t:color="blue1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="xmltwit"/>
@@ -48,7 +48,7 @@
</reference>
</component>
- <component name="RSSTwit" t:color="blue">
+ <component name="RSSTwit" t:color="blue1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="rsstwit"/>
@@ -58,7 +58,7 @@
</reference>
</component>
- <component name="HTML" t:color="yellow">
+ <component name="HTML" t:color="blue1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="html"/>
@@ -68,7 +68,7 @@
</reference>
</component>
- <component name="JSONFB" t:color="orange">
+ <component name="JSONFB" t:color="blue1">
<t:implementation.python script="relay.py"/>
<service name="Relay">
<t:binding.http uri="jsonfb"/>
diff --git a/sca-cpp/trunk/modules/edit/palettes/variables/palette.composite b/sca-cpp/trunk/modules/edit/palettes/variables/palette.composite
index 42fc43525b..1d10027f95 100644
--- a/sca-cpp/trunk/modules/edit/palettes/variables/palette.composite
+++ b/sca-cpp/trunk/modules/edit/palettes/variables/palette.composite
@@ -29,17 +29,17 @@
<service name="first" promote="first"/>
<service name="rest" promote="rest"/>
- <component name="number" t:color="orange">
+ <component name="number" t:color="orange1">
<t:implementation.python script="number.py"/>
<service name="number"/>
</component>
- <component name="text" t:color="orange">
+ <component name="text" t:color="orange1">
<t:implementation.python script="text.py"/>
<service name="text"/>
</component>
- <component name="set" t:color="orange">
+ <component name="set" t:color="orange1">
<documentation>set variable</documentation>
<t:implementation.python script="set.py"/>
<service name="set"/>
@@ -47,7 +47,7 @@
<reference name="variable"/>
</component>
- <component name="list" t:color="orange">
+ <component name="list" t:color="orange1">
<documentation>make a list</documentation>
<t:implementation.python script="list_.py"/>
<service name="list"/>
@@ -55,14 +55,14 @@
<reference name="rest"/>
</component>
- <component name="first" t:color="orange">
+ <component name="first" t:color="orange1">
<documentation>first of a list</documentation>
<t:implementation.python script="first.py"/>
<service name="first"/>
<reference name="value"/>
</component>
- <component name="rest" t:color="orange">
+ <component name="rest" t:color="orange1">
<documentation>rest of a list</documentation>
<t:implementation.python script="rest.py"/>
<service name="rest"/>
diff --git a/sca-cpp/trunk/modules/js/htdocs/atomutil.js b/sca-cpp/trunk/modules/js/htdocs/atomutil.js
index 24a47980f7..21aa16e0fc 100644
--- a/sca-cpp/trunk/modules/js/htdocs/atomutil.js
+++ b/sca-cpp/trunk/modules/js/htdocs/atomutil.js
@@ -20,7 +20,7 @@
/**
* ATOM data conversion functions.
*/
-var atom = new Object();
+var atom = {};
/**
* Convert a list of elements to a list of values representing an ATOM entry.
diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js
index 9907e955c9..835cc148c2 100644
--- a/sca-cpp/trunk/modules/js/htdocs/component.js
+++ b/sca-cpp/trunk/modules/js/htdocs/component.js
@@ -34,7 +34,7 @@
/**
* Escape a character.
*/
-var JSONClient = new Object();
+var JSONClient = {};
JSONClient.escapeJSONChar = function(c) {
if(c == "\"" || c == "\\") return "\\" + c;
@@ -450,7 +450,7 @@ if (typeof DOMParser == "undefined") {
* Public API.
*/
-var sca = new Object();
+var sca = {};
/**
* Return a component.
diff --git a/sca-cpp/trunk/modules/js/htdocs/elemutil.js b/sca-cpp/trunk/modules/js/htdocs/elemutil.js
index be976c3982..f6f8dcd186 100644
--- a/sca-cpp/trunk/modules/js/htdocs/elemutil.js
+++ b/sca-cpp/trunk/modules/js/htdocs/elemutil.js
@@ -203,18 +203,28 @@ function selector(s) {
}
/**
- * Return the value of the attribute with the given name.
+ * Return the attribute with the given name.
*/
-function namedAttributeValue(name, l) {
+function namedAttribute(name, l) {
return memo(l, name, function() {
var f = filter(function(v) { return isAttribute(v) && attributeName(v) == name; }, l);
if (isNil(f))
return null;
- return caddr(car(f));
+ return car(f);
});
}
/**
+ * Return the value of the attribute with the given name.
+ */
+function namedAttributeValue(name, l) {
+ var a = namedAttribute(name, l);
+ if (a == null)
+ return null
+ return attributeValue(a);
+}
+
+/**
* Return child elements with the given name.
*/
function namedElementChildren(name, l) {
@@ -233,3 +243,41 @@ function namedElementChild(name, l) {
return car(f);
}
+/**
+ * Side effect functions. Use with moderation.
+ */
+
+/**
+ * Set the value of the attribute with the given name.
+ */
+function setNamedAttributeValue(name, v, l) {
+ var f = filter(function(v) { return isAttribute(v) && attributeName(v) == name; }, l);
+ if (!isNil(f)) {
+
+ // Un-memoize attribute and change its value
+ unmemo(l, name);
+ car(f)[2] = '' + v;
+ return v;
+ }
+
+ // Insert new attribute
+ insertn$(mklist(attribute, name, '' + v), l, 2);
+ return v;
+}
+
+/**
+ * Set the value of an element.
+ */
+function setElementValue(v, l) {
+ if (elementHasValue(l)) {
+
+ // Change existing element value
+ l[length(l) - 1] = v;
+ return v;
+ }
+
+ // Append element value
+ $append(l, mklist(v));
+ return v;
+}
+
diff --git a/sca-cpp/trunk/modules/js/htdocs/scdl.js b/sca-cpp/trunk/modules/js/htdocs/scdl.js
index df661a29ba..73d07b4a1c 100644
--- a/sca-cpp/trunk/modules/js/htdocs/scdl.js
+++ b/sca-cpp/trunk/modules/js/htdocs/scdl.js
@@ -20,7 +20,7 @@
/**
* SCDL parsing functions.
*/
-var scdl = new Object();
+var scdl = {};
/**
* Returns a composite element.
diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.css b/sca-cpp/trunk/modules/js/htdocs/ui.css
index f3f4507e27..5b441b735d 100644
--- a/sca-cpp/trunk/modules/js/htdocs/ui.css
+++ b/sca-cpp/trunk/modules/js/htdocs/ui.css
@@ -28,10 +28,10 @@ font-family: arial,sans-serif; font-style: normal; font-variant: normal; font-si
}
th {
-font-weight: bold; background-color: #e5ecf9; color: #598edd;
+font-weight: bold; background-color: #96d333; color: #000000;
text-align: left; padding-left: 2px; padding-right: 8px; padding-top: 2px; padding-bottom: 4px; vertical-align: text-top;
border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px;
-border-style: solid; border-top-color: #a2bae7; border-bottom-color: #d1d3d4;
+border-style: solid; border-top-color: #96d333; border-bottom-color: #96d333;
}
td {
@@ -52,11 +52,11 @@ vertical-align: middle;
}
a:link {
-color: blue;
+color: #96d333;
}
a:visited {
-color: blue;
+color: #96d333;
}
h1 {
diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.js b/sca-cpp/trunk/modules/js/htdocs/ui.js
index 483aef6f9f..31cdaed7c6 100644
--- a/sca-cpp/trunk/modules/js/htdocs/ui.js
+++ b/sca-cpp/trunk/modules/js/htdocs/ui.js
@@ -21,7 +21,7 @@
* UI utility functions.
*/
-var ui = new Object();
+var ui = {};
/**
* Return true if the current browser is Internet Explorer.
@@ -266,7 +266,7 @@ ui.installwidget = function() {
/**
* Convert a CSS position to a numeric position.
*/
-ui.posn = function(p) {
+ui.csspos = function(p) {
if (p == '')
return 0;
return Number(p.substr(0, p.length - 2));
diff --git a/sca-cpp/trunk/modules/js/htdocs/util.js b/sca-cpp/trunk/modules/js/htdocs/util.js
index 155836b4e9..873874c7be 100644
--- a/sca-cpp/trunk/modules/js/htdocs/util.js
+++ b/sca-cpp/trunk/modules/js/htdocs/util.js
@@ -218,3 +218,121 @@ function memo(obj, key, f) {
return obj[key] = f();
}
+/**
+ * Un-memoize a value.
+ */
+function unmemo(obj, key) {
+ obj[key] = null;
+ return true;
+}
+
+/**
+ * Functions with side effects. Use with moderation.
+ */
+
+/**
+ * Set the car of a list.
+ */
+function setcar(l, v) {
+ l[0] = v;
+ return l;
+}
+
+/**
+ * Set the cadr of a list.
+ */
+function setcadr(l, v) {
+ l[1] = v;
+ return l;
+}
+
+/**
+ * Set the caddr of a list.
+ */
+function setcaddr(l, v) {
+ l[2] = v;
+ return l;
+}
+
+/**
+ * Append the elements of a list to a list.
+ */
+function setappend(a, b) {
+ if (isNil(b))
+ return a;
+ a.push(car(b));
+ return setappend(a, cdr(b));
+}
+
+/**
+ * Set the cdr of a list.
+ */
+function setcdr(a, b) {
+ a.length = 1;
+ return setappend(a, b);
+}
+
+/**
+ * Set the contents of a list.
+ */
+function setlist(a, b) {
+ a.length = 0;
+ return setappend(a, b);
+}
+
+/**
+ * Insert a value at a given position in a list.
+ */
+function insertn$(v, n, l) {
+ function upshift(i) {
+ if (i == n)
+ return true;
+ l[i] = l[i - 1];
+ return upshift(i - 1);
+ }
+
+ upshift(length(l));
+ l[n] = v;
+ return l;
+}
+
+/**
+ * Insert a value at the beginning of a list.
+ */
+function insert$(v, l) {
+ return insertn$(v, 0, l);
+}
+
+/**
+ * Append a list at the end of a list.
+ */
+function append$(a, b) {
+ if (isNil(b))
+ return a;
+ a.push(car(b));
+ return append$(a, cdr(b));
+}
+
+/**
+ * Delete a value from a list.
+ */
+function delete$(v, l) {
+ function dnshift(i, max) {
+ if (i >= max)
+ return true;
+ l[i] = l[i + 1];
+ return dnshift(i + 1, max);
+ }
+
+ dnshift(n, length(l) - 1);
+ l.pop();
+ return l;
+}
+
+/**
+ * Delete a value at the beginning of a list.
+ */
+function delete$(l) {
+ return deleten$(l, 0);
+}
+