diff options
Diffstat (limited to '')
-rw-r--r-- | sca-cpp/trunk/modules/edit/htdocs/graph/graph.html | 39 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/edit/htdocs/graph/graph.js | 400 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/edit/htdocs/graph/index.html | 12 |
3 files changed, 378 insertions, 73 deletions
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> |