summaryrefslogtreecommitdiffstats
path: root/sca-cpp
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2011-01-13 10:27:39 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2011-01-13 10:27:39 +0000
commit2dffb211b9e30269a0db1c7741a4f07ff5260952 (patch)
treeee3feadb43e35ac6cfaee9c24673e8662e3c3299 /sca-cpp
parent79886cb0923d20021e09a231d3952c319402e2d4 (diff)
Refactor and minor improvements of the edit module. Add a palette of sample components.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1058487 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--sca-cpp/trunk/modules/edit/apps.py10
-rw-r--r--sca-cpp/trunk/modules/edit/apps/relay/app.composite (renamed from sca-cpp/trunk/modules/edit/domains/relay/app.composite)0
-rw-r--r--sca-cpp/trunk/modules/edit/apps/store/app.composite (renamed from sca-cpp/trunk/modules/edit/domains/store/app.composite)0
-rw-r--r--sca-cpp/trunk/modules/edit/apps/store2/app.composite (renamed from sca-cpp/trunk/modules/edit/domains/store2/app.composite)0
-rw-r--r--sca-cpp/trunk/modules/edit/apps/store3/app.composite (renamed from sca-cpp/trunk/modules/edit/domains/store3/app.composite)0
-rw-r--r--sca-cpp/trunk/modules/edit/apps/travel/app.composite (renamed from sca-cpp/trunk/modules/edit/domains/travel/app.composite)0
-rw-r--r--sca-cpp/trunk/modules/edit/dashboard.py72
-rw-r--r--sca-cpp/trunk/modules/edit/dashboards/joe@localhost (renamed from sca-cpp/trunk/modules/edit/workspaces/joe@localhost)0
-rw-r--r--sca-cpp/trunk/modules/edit/edit.composite69
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html2
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/dash/index.html7
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/graph/graph.html112
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/graph/graph.js (renamed from sca-cpp/trunk/modules/edit/htdocs/edit/graph.js)350
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/graph/index.html (renamed from sca-cpp/trunk/modules/edit/htdocs/edit/index.html)13
-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.html41
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/page/page.html (renamed from sca-cpp/trunk/modules/edit/htdocs/edit/edit.html)41
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/page/page.js204
-rw-r--r--sca-cpp/trunk/modules/edit/palettes.py32
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/control/palette.composite53
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/operators/palette.composite138
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite32
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/social/palette.composite81
-rw-r--r--sca-cpp/trunk/modules/edit/palettes/variables/palette.composite72
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/scdl.js27
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/ui.css12
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/ui.js26
28 files changed, 1186 insertions, 217 deletions
diff --git a/sca-cpp/trunk/modules/edit/apps.py b/sca-cpp/trunk/modules/edit/apps.py
index 920bb635e6..61cdfe07ef 100644
--- a/sca-cpp/trunk/modules/edit/apps.py
+++ b/sca-cpp/trunk/modules/edit/apps.py
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-# Workspace collection implementation
+# Apps collection implementation
import uuid
import sys
from util import *
@@ -24,24 +24,24 @@ from util import *
def appid(id):
return ("'" + car(id), "'app.composite")
-# Post a new app to the domains db
+# Post a new app to the apps db
def post(collection, app, cache):
id = appid((str(uuid.uuid1()),))
cache.put((id,), app)
return id
-# Put an app into the domains db
+# Put an app into the apps db
def put(id, app, cache):
cache.put(appid(id), app)
return True
-# Get an app from the domains db
+# Get an app from the apps db
def get(id, cache):
if isNil(id):
return ("Apps", "apps")
return (car(id), car(id), cache.get(appid(id)))
-# Delete an app from the domains db
+# Delete an app from the apps db
def delete(id, cache):
cache.delete(appid(id))
return True
diff --git a/sca-cpp/trunk/modules/edit/domains/relay/app.composite b/sca-cpp/trunk/modules/edit/apps/relay/app.composite
index 1e5015315c..1e5015315c 100644
--- a/sca-cpp/trunk/modules/edit/domains/relay/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/relay/app.composite
diff --git a/sca-cpp/trunk/modules/edit/domains/store/app.composite b/sca-cpp/trunk/modules/edit/apps/store/app.composite
index ec3fa32fa4..ec3fa32fa4 100644
--- a/sca-cpp/trunk/modules/edit/domains/store/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/store/app.composite
diff --git a/sca-cpp/trunk/modules/edit/domains/store2/app.composite b/sca-cpp/trunk/modules/edit/apps/store2/app.composite
index afec3cb1d3..afec3cb1d3 100644
--- a/sca-cpp/trunk/modules/edit/domains/store2/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/store2/app.composite
diff --git a/sca-cpp/trunk/modules/edit/domains/store3/app.composite b/sca-cpp/trunk/modules/edit/apps/store3/app.composite
index 7cba2c19e1..7cba2c19e1 100644
--- a/sca-cpp/trunk/modules/edit/domains/store3/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/store3/app.composite
diff --git a/sca-cpp/trunk/modules/edit/domains/travel/app.composite b/sca-cpp/trunk/modules/edit/apps/travel/app.composite
index 833944a855..833944a855 100644
--- a/sca-cpp/trunk/modules/edit/domains/travel/app.composite
+++ b/sca-cpp/trunk/modules/edit/apps/travel/app.composite
diff --git a/sca-cpp/trunk/modules/edit/dashboard.py b/sca-cpp/trunk/modules/edit/dashboard.py
index 990476a84e..825bf8b405 100644
--- a/sca-cpp/trunk/modules/edit/dashboard.py
+++ b/sca-cpp/trunk/modules/edit/dashboard.py
@@ -15,68 +15,68 @@
# specific language governing permissions and limitations
# under the License.
-# Workspace collection implementation
+# Dashboards collection implementation
import uuid
import sys
from util import *
-# Convert a particular user email to a workspace id
-def workspaceid(user):
+# Convert a particular user email to a dashboard id
+def dashboardid(user):
return ("'" + user.id(),)
-# Get a workspace from the cache
-def getworkspace(id, cache):
- workspace = cache.get(id)
- if isNil(workspace):
+# Get a dashboard from the cache
+def getdashboard(id, cache):
+ dashboard = cache.get(id)
+ if isNil(dashboard):
return ()
- return workspace
+ return dashboard
-# Post a new app to the user's workspace
+# Post a new app to the user's dashboard
def post(collection, app, user, cache):
id = (str(uuid.uuid1()),)
- workspace = cons((car(app), car(id), caddr(app)), getworkspace(workspaceid(user), cache))
- cache.put(workspaceid(user), workspace)
+ dashboard = cons((car(app), car(id), caddr(app)), getdashboard(dashboardid(user), cache))
+ cache.put(dashboardid(user), dashboard)
return id
-# Put an app into the user's workspace
+# Put an app into the user's dashboard
def put(id, app, user, cache):
- def putapp(app, workspace):
- if isNil(workspace):
+ def putapp(app, dashboard):
+ if isNil(dashboard):
return (app,)
- if cadr(app) == cadr(car(workspace)):
- return cons(app, cdr(workspace))
- return cons(car(workspace), putapp(app, cdr(workspace)))
+ if cadr(app) == cadr(car(dashboard)):
+ return cons(app, cdr(dashboard))
+ return cons(car(dashboard), putapp(app, cdr(dashboard)))
- workspace = putapp(app, getworkspace(workspaceid(user), cache))
- cache.put(workspaceid(user), workspace)
+ dashboard = putapp(app, getdashboard(dashboardid(user), cache))
+ cache.put(dashboardid(user), dashboard)
return True
-# Get apps from the user's workspace
+# Get apps from the user's dashboard
def get(id, user, cache):
- def findapp(id, workspace):
- if isNil(workspace):
+ def findapp(id, dashboard):
+ if isNil(dashboard):
return None
- if car(id) == cadr(car(workspace)):
- return car(workspace)
- return findapp(id, cdr(workspace))
+ if car(id) == cadr(car(dashboard)):
+ return car(dashboard)
+ return findapp(id, cdr(dashboard))
if isNil(id):
- return ("Your Apps", user.id()) + getworkspace(workspaceid(user), cache)
- return findapp(id, getworkspace(workspaceid(user), cache))
+ return ("Your Apps", user.id()) + getdashboard(dashboardid(user), cache)
+ return findapp(id, getdashboard(dashboardid(user), cache))
-# Delete apps from the user's workspace
+# Delete apps from the user's dashboard
def delete(id, user, cache):
if isNil(id):
- return cache.delete(workspaceid(user))
+ return cache.delete(dashboardid(user))
- def deleteapp(id, workspace):
- if isNil(workspace):
+ def deleteapp(id, dashboard):
+ if isNil(dashboard):
return ()
- if car(id) == cadr(car(workspace)):
- return cdr(workspace)
- return cons(car(workspace), deleteapp(id, cdr(workspace)))
+ if car(id) == cadr(car(dashboard)):
+ return cdr(dashboard)
+ return cons(car(dashboard), deleteapp(id, cdr(dashboard)))
- workspace = deleteapp(id, getworkspace(workspaceid(user), cache))
- cache.put(workspaceid(user), workspace)
+ dashboard = deleteapp(id, getdashboard(dashboardid(user), cache))
+ cache.put(dashboardid(user), dashboard)
return True
diff --git a/sca-cpp/trunk/modules/edit/workspaces/joe@localhost b/sca-cpp/trunk/modules/edit/dashboards/joe@localhost
index b9419e75d0..b9419e75d0 100644
--- a/sca-cpp/trunk/modules/edit/workspaces/joe@localhost
+++ b/sca-cpp/trunk/modules/edit/dashboards/joe@localhost
diff --git a/sca-cpp/trunk/modules/edit/edit.composite b/sca-cpp/trunk/modules/edit/edit.composite
index c73ac82037..49a5c84a56 100644
--- a/sca-cpp/trunk/modules/edit/edit.composite
+++ b/sca-cpp/trunk/modules/edit/edit.composite
@@ -39,6 +39,7 @@
<component name="EditWidget">
<t:implementation.widget location="/index.html"/>
<reference name="dashboard" target="Dashboard"/>
+ <reference name="palettes" target="Palettes"/>
<reference name="apps" target="Apps"/>
</component>
@@ -48,7 +49,7 @@
<t:binding.http uri="dashboard"/>
</service>
<reference name="user" target="User"/>
- <reference name="cache" target="WorkspaceCache"/>
+ <reference name="cache" target="DashboardCache"/>
</component>
<component name="Apps">
@@ -56,46 +57,74 @@
<service name="Apps">
<t:binding.http uri="apps"/>
</service>
- <reference name="cache" target="DomainCache"/>
+ <reference name="cache" target="AppCache"/>
</component>
- <component name="WorkspaceCache">
+ <component name="Palettes">
+ <t:implementation.python script="palettes.py"/>
+ <service name="Palettes">
+ <t:binding.http uri="palettes"/>
+ </service>
+ <reference name="cache" target="PaletteCache"/>
+ </component>
+
+ <component name="DashboardCache">
<implementation.cpp path="../../components/cache" library="libdatacache"/>
- <service name="WorkspaceCache">
- <t:binding.http uri="workspacecache"/>
+ <service name="DashboardCache">
+ <t:binding.http uri="dashboardcache"/>
</service>
<reference name="l1reader" target="Memcache"/>
<reference name="l1writer" target="Memcache"/>
- <reference name="l2reader" target="WorkspaceDB"/>
- <reference name="l2writer" target="WorkspaceDB"/>
+ <reference name="l2reader" target="DashboardDB"/>
+ <reference name="l2writer" target="DashboardDB"/>
</component>
- <component name="WorkspaceDB">
+ <component name="DashboardDB">
<implementation.cpp path="../../components/filedb" library="libfiledb"/>
- <property name="dbname">workspaces</property>
+ <property name="dbname">dashboards</property>
<property name="format">scheme</property>
- <service name="WorkspaceDB">
- <t:binding.http uri="workspaces"/>
+ <service name="DashboardDB">
+ <t:binding.http uri="dashboarddb"/>
+ </service>
+ </component>
+
+ <component name="AppCache">
+ <implementation.cpp path="../../components/cache" library="libdatacache"/>
+ <service name="AppCache">
+ <t:binding.http uri="appcache"/>
+ </service>
+ <reference name="l1reader" target="Memcache"/>
+ <reference name="l1writer" target="Memcache"/>
+ <reference name="l2reader" target="AppDB"/>
+ <reference name="l2writer" target="AppDB"/>
+ </component>
+
+ <component name="AppDB">
+ <implementation.cpp path="../../components/filedb" library="libfiledb"/>
+ <property name="dbname">apps</property>
+ <property name="format">xml</property>
+ <service name="AppDB">
+ <t:binding.http uri="appdb"/>
</service>
</component>
- <component name="DomainCache">
+ <component name="PaletteCache">
<implementation.cpp path="../../components/cache" library="libdatacache"/>
- <service name="DomainCache">
- <t:binding.http uri="domaincache"/>
+ <service name="PaletteCache">
+ <t:binding.http uri="palettecache"/>
</service>
<reference name="l1reader" target="Memcache"/>
<reference name="l1writer" target="Memcache"/>
- <reference name="l2reader" target="DomainDB"/>
- <reference name="l2writer" target="DomainDB"/>
+ <reference name="l2reader" target="PaletteDB"/>
+ <reference name="l2writer" target="PaletteDB"/>
</component>
- <component name="DomainDB">
+ <component name="PaletteDB">
<implementation.cpp path="../../components/filedb" library="libfiledb"/>
- <property name="dbname">domains</property>
+ <property name="dbname">palettes</property>
<property name="format">xml</property>
- <service name="DomainDB">
- <t:binding.http uri="domains"/>
+ <service name="PaletteDB">
+ <t:binding.http uri="palettedb"/>
</service>
</component>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html b/sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html
index b69c760c99..60d869abde 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/dash/dashboard.html
@@ -82,7 +82,7 @@ function getapps(sync) {
title = car(entry);
apps += '<tr>';
- apps += '<td><input name="apps" type="checkbox" value="' + name + '">' + '<a href=\"' + '/edit/?app=' + name + '\">' + name + '</a></td>';
+ apps += '<td><input name="apps" type="checkbox" value="' + name + '">' + '<a href=\"' + '/graph/?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 0abb384d75..d1da06d71c 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/dash/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/dash/index.html
@@ -30,14 +30,11 @@
<h1>Welcome to your App Dashboard!</h1>
<div id="dashboard"></div>
-<iframe id="menuFrame" src="/menu.html"></iframe>
-<iframe id="dashboardFrame" src="dashboard.html"></iframe>
-
<script type="text/javascript">
-ui.bindwidget('menuFrame', 'menu');
+ui.loadwidget('menu', '/menu.html');
// Display the dashboard widget
-ui.bindwidget('dashboardFrame', 'dashboard');
+ui.loadwidget('dashboard', 'dashboard.html');
</script>
</body>
</html>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.html b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.html
new file mode 100644
index 0000000000..618d638e7d
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.html
@@ -0,0 +1,112 @@
+<!--
+ * 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>
+<script type="text/javascript" src="graph.js"></script>
+</head>
+<body>
+
+<script type="text/javascript">
+var editWidget = sca.component("EditWidget");
+var dashboard = sca.reference(editWidget, "dashboard");
+var palettes = sca.reference(editWidget, "palettes");
+var apps = sca.reference(editWidget, "apps");
+
+/**
+ * Return the current app name.
+ */
+function appname() {
+ return ui.queryParams()['app'];
+}
+
+/**
+ * Return the composite in an ATOM entry.
+ */
+function atomcomposite(doc) {
+ var entry = atom.readATOMEntryDocument(doc);
+ var item = caddr(entry);
+ return cddr(item);
+}
+
+/**
+ * Load and display an app.
+ */
+function getapp(name, g) {
+ if (isNil(name))
+ return;
+ apps.get(name, function(doc) {
+ graph.append(graph.composite(atomcomposite(doc), graph.mkpath().move(300,0)), g);
+ });
+}
+
+/**
+ * Load and display a palette content.
+ */
+
+function getpalette(name, g, bg, palette, gpalettes) {
+ if (isNil(name))
+ return;
+ palettes.get(name, function(doc) {
+ gpalettes[name] = graph.composite(atomcomposite(doc), graph.mkpath().move(150,0));
+ graph.append(gpalettes[name], name == spalette? g : bg);
+ });
+}
+
+/**
+ * Install a palette button and content.
+ */
+function installpalette(name, pos, g, bg, palette, gpalettes) {
+ var b = graph.mkbutton(name, pos);
+ graph.append(mklist(b), g);
+ b.onclick = function() {
+ // Display the selected palette
+ spalette = name;
+ for (var pn in gpalettes)
+ graph.append(gpalettes[pn], pn == spalette? g : bg);
+ }
+ getpalette(name, g, bg, palette, gpalettes);
+}
+
+// Create editor graph area
+var g = graph.mkgraph();
+var bg = graph.mkgroup(graph.mkpath());
+
+// Install the palettes.
+var gpalettes = new Array();
+var spalette = 'variables';
+installpalette('variables', graph.mkpath().move(0,10), g, bg, spalette, gpalettes);
+installpalette('control', graph.mkpath().move(0,80), g, bg, spalette, gpalettes);
+installpalette('operators', graph.mkpath().move(0,150), g, bg, spalette, gpalettes);
+installpalette('social', graph.mkpath().move(0,220), g, bg, spalette, gpalettes);
+installpalette('sensors', graph.mkpath().move(0,290), g, bg, spalette, gpalettes);
+
+// Display the current app
+getapp(appname(), g);
+
+</script>
+</body>
+</html>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/edit/graph.js b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
index 5f122ac498..88a2efd50b 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/edit/graph.js
+++ b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
@@ -18,32 +18,12 @@
*/
/**
- * SVG and VML component rendering functions.
+ * SVG and VML composite rendering functions.
*/
var graph = new Object();
/**
- * Detect browser VML support.
- */
-graph.supportsVML = function() {
- if (typeof graph.supportsVML.supported != 'undefined')
- return graph.supportsVML.supported;
- graph.supportsVML.supported = navigator.appName == 'Microsoft Internet Explorer';
- return graph.supportsVML.supported;
-};
-
-/**
- * Detect browser SVG support.
- */
-graph.supportsSVG = function() {
- if (typeof graph.supportsSVG.supported != 'undefined')
- return graph.supportsSVG.supported;
- graph.supportsSVG.supported = navigator.appName != 'Microsoft Internet Explorer';
- return graph.supportsSVG.supported;
-};
-
-/**
* Basic colors
*/
graph.colors = new Object();
@@ -51,7 +31,7 @@ graph.colors.black = '#000000';
graph.colors.blue = '#0000ff';
graph.colors.cyan = '#00ffff';
graph.colors.gray = '#808080'
-graph.colors.green = '#008000';
+graph.colors.green = '#00ff00';
graph.colors.magenta = '#ff00ff';
graph.colors.orange = '#ffa500';
graph.colors.pink = '#ffc0cb';
@@ -106,7 +86,7 @@ graph.BasePath = function() {
/**
* VML rendering.
*/
-if (graph.supportsVML()) {
+if (ui.isIE()) {
graph.vmlns='urn:schemas-microsoft-com:vml';
document.write('<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />');
@@ -120,9 +100,9 @@ if (graph.supportsVML()) {
document.body.appendChild(div);
var vmlg = document.createElement('v:group');
- vmlg.style.width = 2000;
- vmlg.style.height = 2000;
- vmlg.coordsize = '2000,2000';
+ vmlg.style.width = 5000;
+ vmlg.style.height = 5000;
+ vmlg.coordsize = '5000,5000';
div.appendChild(vmlg);
graph.dragging = null;
@@ -130,17 +110,24 @@ if (graph.supportsVML()) {
function draggable(n) {
if (n == vmlg)
return null;
- if (n.nodeName == 'group')
+ if (n.nodeName == 'group' && n.id != '')
return n;
return draggable(n.parentNode);
}
+ function bringtotop(n) {
+ if (n == vmlg)
+ return null;
+ n.parentNode.appendChild(n);
+ return bringtotop(n.parentNode);
+ }
+
vmlg.onmousedown = function() {
window.event.returnValue = false;
graph.dragging = draggable(window.event.srcElement);
if (graph.dragging == null)
return false;
- graph.dragging.parentNode.appendChild(graph.dragging);
+ bringtotop(graph.dragging);
graph.dragX = window.event.clientX;
graph.dragY = window.event.clientY;
vmlg.setCapture();
@@ -164,6 +151,13 @@ if (graph.supportsVML()) {
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);
return false;
};
@@ -217,27 +211,36 @@ if (graph.supportsVML()) {
};
/**
- * Return an element representing the title of a component.
+ * Return an element representing a title.
*/
- graph.comptitle = function(comp) {
- var t = scdl.name(comp);
- var tsvcs = graph.tsvcs(comp);
- var lsvcs = graph.lsvcs(comp);
+ graph.mktitle = function(t, bold, pos) {
var title = document.createElement('v:textbox');
- title.style.left = '' + (isNil(lsvcs)? 5 : 25);
- title.style.top = '' + (isNil(tsvcs)? 5 : 25);
+ title.style.left = pos.xpos();
+ title.style.top = pos.ypos();
title.style.position = 'absolute';
- title.style.fontWeight = 'bold';
+ if (bold)
+ title.style.fontWeight = 'bold';
var tnode = document.createTextNode(t);
title.appendChild(tnode);
return title;
+ 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)? 5 : 25, isNil(tsvcs)? 5 : 25);
+ return graph.mktitle(graph.title(comp), true, pos);
};
/**
* Return the width of the title of a component.
*/
graph.comptitlewidth = function(comp) {
- var t = scdl.name(comp);
+ var t = graph.title(comp);
graph.comptitlewidthdiv.innerHTML = t;
var twidth = graph.comptitlewidthdiv.offsetWidth;
graph.comptitlewidthdiv.innerHTML = '';
@@ -248,21 +251,14 @@ if (graph.supportsVML()) {
* Return an element representing the title of a reference.
*/
graph.reftitle = function(ref) {
- var t = scdl.name(ref);
- var title = document.createElement('v:textbox');
- title.style.left = '' + 25;
- title.style.top = '' + 25;
- title.style.position = 'absolute';
- var tnode = document.createTextNode(t);
- title.appendChild(tnode);
- return title;
+ return graph.mktitle(graph.title(ref), false, graph.mkpath().move(25,25));
};
/**
* Return the width of the title of a reference.
*/
graph.reftitlewidth = function(ref) {
- var t = scdl.name(ref);
+ var t = graph.title(ref);
graph.reftitlewidthdiv.innerHTML = t;
var twidth = graph.reftitlewidthdiv.offsetWidth;
graph.reftitlewidthdiv.innerHTML = '';
@@ -278,17 +274,17 @@ if (graph.supportsVML()) {
var d = graph.comppath(comp, cassoc).str();
var shape = document.createElement('v:shape');
- shape.style.width = 2000;
- shape.style.height = 2000;
- shape.coordsize = '2000,2000';
+ shape.style.width = 5000;
+ shape.style.height = 5000;
+ shape.coordsize = '5000,5000';
shape.path = d;
shape.fillcolor = graph.color(comp);
shape.stroked = 'false';
var contour = document.createElement('v:shape');
- contour.style.width = 2000;
- contour.style.height = 2000;
- contour.coordsize = '2000,2000';
+ contour.style.width = 5000;
+ contour.style.height = 5000;
+ contour.coordsize = '5000,5000';
contour.setAttribute('path', d);
contour.filled = 'false';
contour.strokecolor = graph.colors.gray;
@@ -301,23 +297,77 @@ if (graph.supportsVML()) {
var g = document.createElement('v:group');
g.id = scdl.name(comp);
- g.style.width = 2000;
- g.style.height = 2000;
- g.coordsize = '2000,2000';
+ 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)
+
+ // Store the component in the shape
+ g.comp = comp;
+
return g;
};
-}
-/**
- * SVG rendering.
- */
-if (graph.supportsSVG()) {
+ /**
+ * 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;
+ };
+ /**
+ * Return a shape representing a button.
+ */
+ graph.mkbutton = function(t, pos) {
+ var title = graph.mktitle(t, true, pos);
+ var d = graph.buttonpath().str();
+
+ 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.stroked = 'false';
+
+ var contour = document.createElement('v:shape');
+ contour.style.width = 5000;
+ contour.style.height = 5000;
+ contour.coordsize = '5000,5000';
+ contour.setAttribute('path', d);
+ contour.filled = 'false';
+ contour.strokecolor = graph.colors.gray;
+ contour.strokeweight = '2';
+ contour.style.left = 1;
+ contour.style.top = 1;
+ var stroke = document.createElement('v:stroke');
+ stroke.opacity = '20%';
+ contour.appendChild(stroke);
+
+ 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;
+ };
+
+} else {
+
+ /**
+ * SVG rendering.
+ */
graph.svgns='http://www.w3.org/2000/svg';
/**
@@ -329,8 +379,8 @@ if (graph.supportsSVG()) {
document.body.appendChild(div);
var svg = document.createElementNS(graph.svgns, 'svg');
- svg.style.height = '100%';
- svg.style.width = '100%';
+ svg.style.height = 5000;
+ svg.style.width = 5000;
div.appendChild(svg);
graph.dragging = null;
@@ -338,20 +388,27 @@ if (graph.supportsSVG()) {
function draggable(n) {
if (n == svg)
return null;
- if (n.nodeName == 'g')
+ if (n.nodeName == 'g' && n.id != '')
return n;
return draggable(n.parentNode);
}
+ function bringtotop(n) {
+ if (n == svg)
+ return null;
+ n.parentNode.appendChild(n);
+ return bringtotop(n.parentNode);
+ }
+
svg.onmousedown = function(e) {
if (e.preventDefault)
e.preventDefault();
else
- e.returnValue= false;
+ e.returnValue = false;
graph.dragging = draggable(e.target);
if (graph.dragging == null)
return false;
- graph.dragging.parentNode.appendChild(graph.dragging);
+ bringtotop(graph.dragging);
var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
graph.dragX = pos.clientX;
graph.dragY = pos.clientY;
@@ -381,6 +438,13 @@ if (graph.supportsSVG()) {
var newY = curY + (pos.clientY - graph.dragY);
graph.dragX = pos.clientX;
graph.dragY = pos.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());
+ graph.dragging.parentNode.appendChild(clone);
+ graph.dragging = clone;
+ }
graph.dragging.setAttribute('transform', 'translate(' + newX + ',' + newY + ')');
return false;
};
@@ -389,8 +453,8 @@ if (graph.supportsSVG()) {
graph.titlewidthsvg = document.createElementNS(graph.svgns, 'svg');
graph.titlewidthsvg.style.visibility = 'hidden';
- graph.titlewidthsvg.style.height = '0px';
- graph.titlewidthsvg.style.width = '0px';
+ graph.titlewidthsvg.style.height = 0;
+ graph.titlewidthsvg.style.width = 0;
div.appendChild(graph.titlewidthsvg);
return svg;
@@ -433,20 +497,27 @@ if (graph.supportsSVG()) {
};
/**
- * Return an element representing the title of a component.
+ * Return an element representing a title.
*/
- graph.comptitle = function(comp) {
- var t = scdl.name(comp);
+ graph.mktitle = function(t, bold) {
var title = document.createElementNS(graph.svgns, 'text');
title.setAttribute('text-anchor', 'start');
title.setAttribute('x', 5);
title.setAttribute('y', 15);
- title.style.fontWeight = 'bold';
+ if (bold)
+ title.style.fontWeight = 'bold';
title.appendChild(document.createTextNode(t));
return title;
};
/**
+ * Return an element representing the title of a component.
+ */
+ graph.comptitle = function(comp) {
+ return graph.mktitle(graph.title(comp), true);
+ };
+
+ /**
* Return the width of the title of a component.
*/
graph.comptitlewidth = function(comp) {
@@ -461,12 +532,7 @@ if (graph.supportsSVG()) {
* Return an element representing the title of a reference.
*/
graph.reftitle = function(ref) {
- var t = scdl.name(ref);
- var title = document.createElementNS(graph.svgns, 'text');
- title.setAttribute('text-anchor', 'start');
- title.setAttribute('x', 5);
- title.setAttribute('y', 15);
- return title;
+ return graph.mktitle(graph.title(ref), false);
};
/**
@@ -506,11 +572,59 @@ if (graph.supportsSVG()) {
g.appendChild(shape);
g.appendChild(contour);
g.appendChild(title);
+
+ // Store the component in the shape.
+ g.comp = comp;
+
+ return g;
+ };
+
+ /**
+ * 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;
+ };
+
+ /**
+ * Return a shape representing a button.
+ */
+ graph.mkbutton = function(t, pos) {
+ var title = graph.mktitle(t, true);
+ var d = graph.buttonpath().str();
+
+ var shape = document.createElementNS(graph.svgns, 'path');
+ shape.setAttribute('d', d);
+ shape.setAttribute('fill', graph.colors.blue);
+
+ 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', '4');
+ contour.setAttribute('stroke-opacity', '0.20');
+ contour.setAttribute('transform', 'translate(1,1)');
+
+ 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;
};
}
/**
+ * Return the title of a SCDL element.
+ */
+graph.title = function(e) {
+ var d = scdl.documentation(e);
+ return d != null? d : scdl.name(e);
+};
+
+/**
* Return the services and references of a component.
*/
graph.tsvcs = function(comp) {
@@ -707,8 +821,8 @@ graph.tsvcpath = function(svc, cassoc, path) {
};
/**
-* Return a path representing a component.
-*/
+ * Return a path representing a component.
+ */
graph.comppath = function(comp, cassoc) {
var height = graph.compheight(comp, cassoc);
var width = graph.compwidth(comp, cassoc);
@@ -742,22 +856,39 @@ graph.comppath = function(comp, cassoc) {
};
/**
+ * Return a path representing a button.
+ */
+graph.buttonpath = function(t) {
+ var height = 60;
+ var width = 120;
+ var path = graph.mkpath().move(10,0);
+ path = path.line(width - 10,path.ypos()).rcurve(10,0,0,10);
+ path = path.line(path.xpos(),height - 10).rcurve(0,10,-10,0).line(10, path.ypos());
+ path = path.line(10,path.ypos()).rcurve(-10,0,0,-10).line(path.xpos(), 10);
+ path = path.line(0,10).rcurve(0,-10,10,0);
+ return path.end();
+};
+
+/**
+ * Append a list of graphical elements to a parent.
+ */
+graph.append = function(nodes, p) {
+ if (isNil(nodes))
+ return p;
+ p.appendChild(car(nodes));
+ return graph.append(cdr(nodes), p);
+};
+
+/**
* Render a composite.
*/
-graph.composite = function(compos) {
- var name = scdl.name(compos);
+graph.composite = function(compos, pos) {
+ var name = scdl.name(scdl.composite(compos));
var comps = scdl.components(compos);
var cassoc = scdl.nameToElementAssoc(comps);
var proms = scdl.promotions(compos);
function rendercomp(comp, cassoc, pos) {
- function appendg(nodes, parent) {
- if (isNil(nodes))
- return parent;
- parent.appendChild(car(nodes));
- return appendg(cdr(nodes), parent);
- }
-
function renderrrefs(refs, cassoc, pos) {
function renderrref(ref, cassoc, pos) {
var target = assoc(scdl.target(ref), cassoc);
@@ -796,36 +927,51 @@ graph.composite = function(compos) {
var rrefs = graph.rrefs(comp);
var rpos = graph.mkpath().rmove(graph.compwidth(comp, cassoc), 0);
- appendg(renderrrefs(rrefs, cassoc, rpos), gcomp);
+ graph.append(renderrrefs(rrefs, cassoc, rpos), gcomp);
var brefs = graph.brefs(comp);
var bpos = graph.mkpath().rmove(0 , graph.compheight(comp, cassoc));
- appendg(renderbrefs(brefs, cassoc, bpos), gcomp);
+ graph.append(renderbrefs(brefs, cassoc, bpos), gcomp);
return mklist(gcomp);
}
function renderproms(svcs, cassoc, pos) {
- function renderprom(svc, cassoc, pos) {
- var comp = assoc(scdl.promote(svc), cassoc);
- if (isNil(comp))
+ function promcomp(svc, cassoc) {
+ var c = assoc(scdl.promote(svc), cassoc);
+ if (isNil(c))
return mklist();
- return rendercomp(cadr(comp), cassoc, pos);
+ return cadr(c);
}
- function rendermove(svc, cassoc, pos) {
- var comp = assoc(scdl.promote(svc), cassoc);
- if (isNil(comp))
- return pos;
- return pos.clone().rmove(0, graph.compclosureheight(cadr(comp), cassoc) + 20);
+ 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());
+ }
+
+ function rendermove(comp, cassoc, pos) {
+ return pos.clone().rmove(0, graph.compclosureheight(comp, cassoc) + 20);
}
if (isNil(svcs))
return mklist();
- return append(renderprom(car(svcs), cassoc, pos), renderproms(cdr(svcs), cassoc, rendermove(car(svcs), cassoc, pos)));
+
+ var comp = promcomp(car(svcs), cassoc);
+ if (isNil(comp))
+ return renderproms(cdr(svcs), cassoc, rendermove(car(svcs), cassoc, pos));
+
+ var cpos = comppos(comp, pos);
+ return append(rendercomp(comp, cassoc, cpos), renderproms(cdr(svcs), cassoc, rendermove(comp, cassoc, cpos)));
}
- var rcomps = renderproms(proms, cassoc, graph.mkpath().rmove(20,20));
- return rcomps;
+ var rproms = renderproms(proms, cassoc, pos.clone().rmove(20,20));
+
+ if (name == 'palette')
+ return map(function(r) {
+ r.id = 'palette:' + r.id;
+ return r;
+ }, rproms);
+ return rproms;
};
diff --git a/sca-cpp/trunk/modules/edit/htdocs/edit/index.html b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
index 34479a37a5..105e240389 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/edit/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
@@ -27,13 +27,12 @@
<body>
<div id="menu"></div>
-<h1><span id="titleDiv"></span></h1>
-<div id="editDiv"></div>
+<h1><span id="title"></span></h1>
-<iframe id="menuFrame" src="/menu.html"></iframe>
+<div id="graph"></div>
<script type="text/javascript">
-ui.bindwidget('menuFrame', 'menu');
+ui.loadwidget('menu', '/menu.html');
/**
* Return the current app name.
@@ -48,9 +47,9 @@ function appname() {
function editapp(name) {
if (isNil(name))
return;
- $('titleDiv').innerHTML = 'Editing: ' + name;
- $('editDiv').innerHTML =
- '<iframe id="editFrame" style="visibility: visible; height: 5000px; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="edit.html?' +
+ $('title').innerHTML = 'Editing: ' + name;
+ $('graph').innerHTML =
+ '<iframe id="graphFrame" style="height: 5000px; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="graph.html?' +
'app=' + name +
'"></iframe>';
}
diff --git a/sca-cpp/trunk/modules/edit/htdocs/index.html b/sca-cpp/trunk/modules/edit/htdocs/index.html
index 52ed6259c7..d9791a8b78 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/index.html
@@ -34,12 +34,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="edit/?app=store">App Editor</a> to edit an app.</p>
+<p>Try the <a href="graph/?app=store">App Editor</a> to edit an app.</p>
-<iframe id="menuFrame" src="menu.html"></iframe>
+<h2>Page Editor</h2>
+<p>Try the <a href="page/?app=store">Page Editor</a> to edit an app page.</p>
<script type="text/javascript">
-ui.bindwidget('menuFrame', 'menu');
+ui.loadwidget('menu', '/menu.html');
</script>
</body>
</html>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/menu.html b/sca-cpp/trunk/modules/edit/htdocs/menu.html
index a4addf1f96..7bf2ef931e 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/menu.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/menu.html
@@ -29,7 +29,7 @@
ui.installwidget();
var mdiv = $('menu');
-mdiv.innerHTML = ui.menubar(mklist(ui.menu('Home', '/'), ui.menu('Dashboard', '/dash'), ui.menu('Editor', '/edit?app=store')), mklist(ui.menu('Sign out', '/logout')));
+mdiv.innerHTML = ui.menubar(mklist(ui.menu('Home', '/'), ui.menu('Dashboard', '/dash')), mklist(ui.menu('Sign out', '/logout')));
</script>
</body>
</html>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/index.html b/sca-cpp/trunk/modules/edit/htdocs/page/index.html
new file mode 100644
index 0000000000..e34aca0bea
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/htdocs/page/index.html
@@ -0,0 +1,41 @@
+<!--
+ * 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 Page Editor</title>
+<meta name="viewport" content="width=device-width user-scalable=no initial-scale=1.0"/>
+<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>
+
+<h1>Editing: HTML Page</h1>
+<div id="page"></div>
+
+<script type="text/javascript">
+ui.loadwidget('menu', '/menu.html');
+
+// Display the page widget
+ui.loadwidget('page', 'page.html');
+</script>
+</body>
+</html>
+
diff --git a/sca-cpp/trunk/modules/edit/htdocs/edit/edit.html b/sca-cpp/trunk/modules/edit/htdocs/page/page.html
index d5618834ba..75405ce163 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/edit/edit.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/page/page.html
@@ -26,43 +26,24 @@
<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="/edit/graph.js"></script>
+<script type="text/javascript" src="page.js"></script>
</head>
<body>
-<script type="text/javascript">
-var editWidget = sca.component("EditWidget");
-var dashboard = sca.reference(editWidget, "dashboard");
-var apps = sca.reference(editWidget, "apps");
+<div id="page" style="position: absolute; width: 5000px; height: 5000px;">
-/**
- * Return the current app name.
- */
-function appname() {
- return ui.queryParams()['app'];
-}
+<input id="palette:button" type="button" value="sample button" style="position: absolute; left:20px; top: 20px;"/>
+<input id="palette:entry" type="text" value="sample value" style="position: absolute; left:20px; top: 60px;"/>
+<span id="palette:text" style="position: absolute; left:20px; top: 100px;">sample text</span>
-/**
- * Get an app and display it.
- */
-function getapp(name) {
- if (isNil(name))
- return;
- apps.get(name, function(doc) {
- var entry = atom.readATOMEntryDocument(doc);
- var item = caddr(entry);
- var composite = cddr(item);
- var comps = scdl.components(composite);
+</div>
- var g = graph.mkgraph();
- var shapes = graph.composite(composite);
- for (var s in shapes)
- g.appendChild(shapes[s]);
- });
-}
+<script type="text/javascript">
+// Install the widget
+ui.installwidget();
-// Display the current app
-getapp(appname());
+// Enable drag&drop on sample UI elements
+page.initpage($('page'));
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/page.js b/sca-cpp/trunk/modules/edit/htdocs/page/page.js
new file mode 100644
index 0000000000..e4554195c1
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/htdocs/page/page.js
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+/**
+ * Page editing functions.
+ */
+var page = new Object();
+
+if (ui.isIE()) {
+
+ /**
+ * Init a page.
+ */
+ page.initpage = function(elem) {
+ page.dragging = null;
+
+ function draggable(n) {
+ if (n == elem)
+ return null;
+ if (n.id != '')
+ return n;
+ return draggable(n.parentNode);
+ }
+
+ function bringtotop(n) {
+ if (n == elem)
+ return null;
+ n.parentNode.appendChild(n);
+ return bringtotop(n.parentNode);
+ }
+
+ elem.onmousedown = function() {
+ window.event.returnValue = false;
+ page.dragging = draggable(window.event.srcElement);
+ if (page.dragging == null)
+ return false;
+ bringtotop(page.dragging);
+ page.dragX = window.event.clientX;
+ page.dragY = window.event.clientY;
+ elem.setCapture();
+ return false;
+ };
+
+ elem.onmouseup = function() {
+ if (page.dragging == null)
+ return false;
+ page.dragging = null;
+ elem.releaseCapture();
+ return false;
+ };
+
+ elem.onmousemove = function() {
+ if (page.dragging == null)
+ return false;
+ var origX = page.dragging.coordorigin.X;
+ var origY = page.dragging.coordorigin.Y;
+ var newX = origX - (window.event.clientX - page.dragX);
+ var newY = origY - (window.event.clientY - page.dragY);
+ page.dragX = window.event.clientX;
+ page.dragY = window.event.clientY;
+
+ if (page.dragging.id.substring(0, 8) == 'palette:') {
+ // Clone the dragged element
+ page.dragging = page.clone(page.dragging);
+ }
+ page.dragging.style.left = newX;
+ page.dragging.style.top = newY;
+ return false;
+ };
+
+ return elem;
+ };
+
+} else {
+
+ /**
+ * Init a page.
+ */
+ page.initpage = function(elem) {
+ page.dragging = null;
+
+ function draggable(n) {
+ if (n == elem)
+ return null;
+ if (n.id != '')
+ return n;
+ return draggable(n.parentNode);
+ }
+
+ function bringtotop(n) {
+ if (n == elem)
+ return null;
+ n.parentNode.appendChild(n);
+ return bringtotop(n.parentNode);
+ }
+
+ elem.onmousedown = function(e) {
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
+ page.dragging = draggable(e.target);
+ if (page.dragging == null)
+ return false;
+ bringtotop(page.dragging);
+ var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
+ page.dragX = pos.clientX;
+ page.dragY = pos.clientY;
+ return false;
+ };
+
+ elem.ontouchstart = elem.onmousedown;
+
+ elem.onmouseup = function(e) {
+ if (page.dragging == null)
+ return false;
+ page.dragging = null;
+ return false;
+ };
+
+ elem.ontouchend = elem.onmouseup;
+
+ elem.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);
+ var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
+ var newX = curX + (pos.clientX - page.dragX);
+ var newY = curY + (pos.clientY - page.dragY);
+ page.dragX = pos.clientX;
+ page.dragY = pos.clientY;
+
+ if (page.dragging.id.substring(0, 8) == 'palette:') {
+ // Clone the dragged element
+ page.dragging = page.clone(page.dragging);
+ }
+ page.dragging.style.left = newX;
+ page.dragging.style.top = newY;
+ return false;
+ };
+
+ elem.ontouchmove = elem.onmousemove;
+
+ return elem;
+ };
+}
+
+/**
+ * Clone an HTML element.
+ */
+page.elemcount = 0;
+
+page.clone = function(e) {
+ function mkclone(e) {
+ if (e.nodeName == 'INPUT' && e.type == 'button') {
+ var ne = document.createElement('input');
+ ne.type = 'button';
+ ne.id = 'button' + (++page.elemcount);
+ ne.value = ne.id;
+ return ne;
+ }
+ if (e.nodeName == 'INPUT' && e.type == 'text') {
+ var ne = document.createElement('input');
+ ne.type = 'text';
+ ne.id = 'entry' + (++page.elemcount);
+ ne.value = ne.id;
+ return ne;
+ }
+ if (e.nodeName == 'SPAN') {
+ var ne = document.createElement('span');
+ ne.id = 'text' + (++page.elemcount);
+ ne.innerHTML = ne.id;
+ return ne;
+ }
+ }
+
+ function posclone(ne, e) {
+ ne.style.position = 'absolute';
+ ne.style.left = ui.posn(e.style.left);
+ ne.style.top = ui.posn(e.style.top);
+ e.parentNode.appendChild(ne);
+ return ne;
+ }
+
+ return posclone(mkclone(e), e);
+};
+
diff --git a/sca-cpp/trunk/modules/edit/palettes.py b/sca-cpp/trunk/modules/edit/palettes.py
new file mode 100644
index 0000000000..9d07973cef
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/palettes.py
@@ -0,0 +1,32 @@
+# 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.
+
+# Palettes collection implementation
+import uuid
+import sys
+from util import *
+
+# Convert an id to a palette id
+def paletteid(id):
+ return ("'" + car(id), "'palette.composite")
+
+# Get a palette from the palettes db
+def get(id, cache):
+ if isNil(id):
+ return ("Palettes", "palettes")
+ return (car(id), car(id), cache.get(paletteid(id)))
+
diff --git a/sca-cpp/trunk/modules/edit/palettes/control/palette.composite b/sca-cpp/trunk/modules/edit/palettes/control/palette.composite
new file mode 100644
index 0000000000..21aa631217
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/palettes/control/palette.composite
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://control"
+ name="palette">
+
+ <service name="if" promote="if"/>
+ <service name="ifelse" promote="ifelse"/>
+ <service name="foreach" promote="foreach"/>
+
+ <component name="if" t:color="yellow">
+ <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">
+ <documentation>if else</documentation>
+ <t:implementation.python script="ifelse.py"/>
+ <service name="ifelse" t:align="top"/>
+ <reference name="condition"/>
+ <reference name="do" t:align="bottom"/>
+ <reference name="else" t:align="bottom"/>
+ </component>
+
+ <component name="foreach" t:color="yellow">
+ <documentation>for each</documentation>
+ <t:implementation.python script="ifelse.py"/>
+ <service name="foreach" t:align="top"/>
+ <reference name="list"/>
+ <reference name="do" t:align="bottom"/>
+ </component>
+
+</composite>
diff --git a/sca-cpp/trunk/modules/edit/palettes/operators/palette.composite b/sca-cpp/trunk/modules/edit/palettes/operators/palette.composite
new file mode 100644
index 0000000000..35f8dfdf9c
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/palettes/operators/palette.composite
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://operators"
+ name="palette">
+
+ <service name="true" promote="true"/>
+ <service name="false" promote="false"/>
+ <service name="and" promote="and"/>
+ <service name="or" promote="or"/>
+ <service name="not" promote="not"/>
+ <service name="equals" promote="equals"/>
+ <service name="greater" promote="greater"/>
+ <service name="lesser" promote="lesser"/>
+ <service name="multiply" promote="multiply"/>
+ <service name="divide" promote="divide"/>
+ <service name="add" promote="add"/>
+ <service name="subtract" promote="subtract"/>
+
+ <component name="true" t:color="green">
+ <t:implementation.python script="true_.py"/>
+ <service name="true"/>
+ </component>
+
+ <component name="false" t:color="green">
+ <t:implementation.python script="false_.py"/>
+ <service name="false"/>
+ </component>
+
+ <component name="and" t:color="green">
+ <t:implementation.python script="and_.py"/>
+ <service name="and"/>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+ <component name="or" t:color="green">
+ <t:implementation.python script="or_.py"/>
+ <service name="or"/>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+ <component name="not" t:color="green">
+ <t:implementation.python script="not_.py"/>
+ <service name="not"/>
+ <reference name="value"/>
+ </component>
+
+ <component name="equals" t:color="green">
+ <documentation>=</documentation>
+ <t:implementation.python script="equals.py"/>
+ <service name="equals">
+ <documentation>=</documentation>
+ </service>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+ <component name="greater" t:color="green">
+ <documentation>gt</documentation>
+ <t:implementation.python script="greater.py"/>
+ <service name="greater">
+ <documentation>gt</documentation>
+ </service>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+ <component name="lesser" t:color="green">
+ <documentation>lt</documentation>
+ <t:implementation.python script="lesser.py"/>
+ <service name="lesser">
+ <documentation>lt</documentation>
+ </service>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+ <component name="multiply" t:color="green">
+ <documentation>*</documentation>
+ <t:implementation.python script="multiply.py"/>
+ <service name="multiply">
+ <documentation>*</documentation>
+ </service>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+ <component name="divide" t:color="green">
+ <documentation>/</documentation>
+ <t:implementation.python script="divide.py"/>
+ <service name="divide">
+ <documentation>/</documentation>
+ </service>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+ <component name="add" t:color="green">
+ <documentation>+</documentation>
+ <t:implementation.python script="add.py"/>
+ <service name="add">
+ <documentation>+</documentation>
+ </service>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+ <component name="subtract" t:color="green">
+ <documentation>-</documentation>
+ <t:implementation.python script="subtract.py"/>
+ <service name="subtract">
+ <documentation>-</documentation>
+ </service>
+ <reference name="value1"/>
+ <reference name="value2"/>
+ </component>
+
+</composite>
diff --git a/sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite b/sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite
new file mode 100644
index 0000000000..20ef8225ce
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/palettes/sensors/palette.composite
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://sensors"
+ name="palette">
+
+ <service name="location" promote="location"/>
+
+ <component name="location" t:color="magenta">
+ <t:implementation.python script="location.py"/>
+ <service name="location"/>
+ </component>
+
+</composite>
diff --git a/sca-cpp/trunk/modules/edit/palettes/social/palette.composite b/sca-cpp/trunk/modules/edit/palettes/social/palette.composite
new file mode 100644
index 0000000000..264e2ed137
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/palettes/social/palette.composite
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://social"
+ name="palette">
+
+ <service name="JSONTwit" promote="JSONTwit"/>
+ <service name="XMLTwit" promote="XMLTwit"/>
+ <service name="RSSTwit" promote="RSSTwit"/>
+ <service name="HTML" promote="HTML"/>
+ <service name="JSONFB" promote="JSONFB"/>
+
+ <component name="JSONTwit" t:color="red">
+ <t:implementation.python script="relay.py"/>
+ <service name="Relay">
+ <t:binding.http uri="jsontwit"/>
+ </service>
+ <reference name="target">
+ <t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.json?screen_name=jsdelfino"/>
+ </reference>
+ </component>
+
+ <component name="XMLTwit" t:color="green">
+ <t:implementation.python script="relay.py"/>
+ <service name="Relay">
+ <t:binding.http uri="xmltwit"/>
+ </service>
+ <reference name="target">
+ <t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=jsdelfino"/>
+ </reference>
+ </component>
+
+ <component name="RSSTwit" t:color="blue">
+ <t:implementation.python script="relay.py"/>
+ <service name="Relay">
+ <t:binding.http uri="rsstwit"/>
+ </service>
+ <reference name="target">
+ <t:binding.http uri="http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=jsdelfino"/>
+ </reference>
+ </component>
+
+ <component name="HTML" t:color="yellow">
+ <t:implementation.python script="relay.py"/>
+ <service name="Relay">
+ <t:binding.http uri="html"/>
+ </service>
+ <reference name="target">
+ <t:binding.http uri="http://people.apache.org/~jsdelfino/"/>
+ </reference>
+ </component>
+
+ <component name="JSONFB" t:color="orange">
+ <t:implementation.python script="relay.py"/>
+ <service name="Relay">
+ <t:binding.http uri="jsonfb"/>
+ </service>
+ <reference name="target">
+ <t:binding.http uri="https://graph.facebook.com/100001053301307"/>
+ </reference>
+ </component>
+
+</composite>
diff --git a/sca-cpp/trunk/modules/edit/palettes/variables/palette.composite b/sca-cpp/trunk/modules/edit/palettes/variables/palette.composite
new file mode 100644
index 0000000000..42fc43525b
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/palettes/variables/palette.composite
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
+ xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"
+ targetNamespace="http://variables"
+ name="palette">
+
+ <service name="number" promote="number"/>
+ <service name="text" promote="text"/>
+ <service name="set" promote="set"/>
+ <service name="list" promote="list"/>
+ <service name="first" promote="first"/>
+ <service name="rest" promote="rest"/>
+
+ <component name="number" t:color="orange">
+ <t:implementation.python script="number.py"/>
+ <service name="number"/>
+ </component>
+
+ <component name="text" t:color="orange">
+ <t:implementation.python script="text.py"/>
+ <service name="text"/>
+ </component>
+
+ <component name="set" t:color="orange">
+ <documentation>set variable</documentation>
+ <t:implementation.python script="set.py"/>
+ <service name="set"/>
+ <reference name="value"/>
+ <reference name="variable"/>
+ </component>
+
+ <component name="list" t:color="orange">
+ <documentation>make a list</documentation>
+ <t:implementation.python script="list_.py"/>
+ <service name="list"/>
+ <reference name="first"/>
+ <reference name="rest"/>
+ </component>
+
+ <component name="first" t:color="orange">
+ <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">
+ <documentation>rest of a list</documentation>
+ <t:implementation.python script="rest.py"/>
+ <service name="rest"/>
+ <reference name="value"/>
+ </component>
+
+</composite>
diff --git a/sca-cpp/trunk/modules/js/htdocs/scdl.js b/sca-cpp/trunk/modules/js/htdocs/scdl.js
index d0b229cae6..561a3e446b 100644
--- a/sca-cpp/trunk/modules/js/htdocs/scdl.js
+++ b/sca-cpp/trunk/modules/js/htdocs/scdl.js
@@ -23,6 +23,16 @@
var scdl = new Object();
/**
+ * Returns a composite element.
+ */
+scdl.composite = function(l) {
+ var cs = namedElementChildren("'composite", l);
+ if (isNil(cs))
+ return cs;
+ return car(cs);
+};
+
+/**
* Returns a list of components in a composite.
*/
scdl.components = function(l) {
@@ -60,6 +70,23 @@ scdl.name = function(l) {
};
/**
+ * Returns the description of a component, componentType, service or reference.
+ */
+scdl.documentation = function(l) {
+ var d = namedElementChildren("'documentation", l);
+ if (isNil(d))
+ return null;
+ if (!elementHasValue(car(d)))
+ return null;
+ var v = elementValue(car(d));
+ if (v == 'gt')
+ return '>'
+ if (v == 'lt')
+ return '<';
+ return v;
+};
+
+/**
* Returns the color of a component or componentType.
*/
scdl.color = function(l) {
diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.css b/sca-cpp/trunk/modules/js/htdocs/ui.css
index d1413018a0..014cc5110d 100644
--- a/sca-cpp/trunk/modules/js/htdocs/ui.css
+++ b/sca-cpp/trunk/modules/js/htdocs/ui.css
@@ -35,10 +35,14 @@ border-style: solid; border-top-color: #a2bae7; border-bottom-color: #d1d3d4;
}
td {
-padding-left: 2px; padding-top: 2px; padding-right: 8px; vertical-align: text-top;
+padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: nowrap; vertical-align: text-top;
}
-iframe {
+.tdw {
+padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: normal; vertical-align: text-top;
+}
+
+.widgetframe {
visibility: hidden; width: 0px; height: 0px;
}
@@ -55,10 +59,6 @@ a:visited {
color: blue;
}
-.tdw {
-padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: normal; vertical-align: text-top;
-}
-
.hd1 {
font-size: 150%; font-weight: bold;
}
diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.js b/sca-cpp/trunk/modules/js/htdocs/ui.js
index d8266c7af6..60ca01568e 100644
--- a/sca-cpp/trunk/modules/js/htdocs/ui.js
+++ b/sca-cpp/trunk/modules/js/htdocs/ui.js
@@ -24,6 +24,16 @@
var ui = new Object();
/**
+ * Return true if the current browser is Internet Explorer.
+ */
+ui.isIE = function() {
+ if (typeof ui.isIE.detected != 'undefined')
+ return ui.isIE.detected;
+ ui.isIE.detected = navigator.appName == 'Microsoft Internet Explorer';
+ return ui.isIE.detected;
+};
+
+/**
* Build a menu bar.
*/
ui.menu = function(name, href) {
@@ -222,7 +232,12 @@ ui.queryParams = function() {
*/
ui.widgets = new Array();
-ui.bindwidget = function(f, el) {
+ui.loadwidget = function(el, doc) {
+ var f = el + 'Frame';
+ var div = document.createElement('div');
+ div.id = f + 'Div';
+ div.innerHTML = '<iframe id="' + f + '" class="widgetframe" src="' + doc + '"></iframe>';
+ document.body.appendChild(div);
window.ui.widgets[f] = el;
return f;
};
@@ -245,3 +260,12 @@ ui.installwidget = function() {
return true;
};
+/**
+ * Convert a CSS position to a numeric position.
+ */
+ui.posn = function(p) {
+ if (p == '')
+ return 0;
+ return Number(p.substr(0, p.length - 2));
+};
+