--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sysmodellibs/sysmodelgen/core/draw.xsl Wed Oct 13 16:21:25 2010 +0100
@@ -0,0 +1,1722 @@
+<?xml version="1.0"?>
+ <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:s="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:exslt="http://exslt.org/common" xmlns:m="http://exslt.org/math" exclude-result-prefixes="s m exslt" >
+ <xsl:output method="xml" cdata-section-elements="script s:script" indent="yes"/>
+ <xsl:param name="Run"/>
+ <!-- Selects the run mode, by default it will draw the model from the given layout data. The output is an SVG diagram.
+ There are two other options:
+ "calc" - Indicates that it should just do all 1st-pass calculations and generate a model with those embedded. The generated XML output is non-standard and has a fragile syntax that cannot be relied upon.
+ "draw" - Draw the model from a pre-caculated result. The output is an SVG diagram. This will fail if run on raw layout data.
+ The run mode options are mostly useful for debugging, though they can also be used for drawing a model
+ in low-memory or very large model situations. In the normal mode, the 1st pass is saved in memory before drawing.
+ Saving to disk instead could greatly reduce the run-time memory usage. -->
+
+ <xsl:param name="Use-as-name" select="'name'"/> <!-- The attribute to use as the item name. Falls back to 'name' -->
+ <xsl:key name="lgrp-bottom" match="layer-group" use="@from"/>
+ <xsl:key name="lgrp-top" match="layer-group" use="@to"/>
+
+
+ <xsl:variable name="large-width" select="500"/> <!-- cutoff width to be considered a wide model and thus need larger title size -->
+
+<xsl:variable name="Versions">
+ <xsl:choose>
+ <xsl:when test="/SystemDefinition/*/meta[@rel='version-list']">
+ <xsl:copy-of select="/SystemDefinition/*/meta[@rel='version-list']"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <v>ER5</v><v>ER5U</v>
+ <v>6.0</v> <v>6.1</v> <v>6.2</v>
+ <v>7.0</v> <v>7.0s</v>
+ <v>8.0</v> <v>8.0a 8.0b</v><v>8.1 8.1a 8.1b</v>
+ <v>9.0</v> <v>9.1</v> <v>9.2</v> <v>9.3</v>
+ <v>9.4 ^1</v><v>tb91 ^2</v> <v>tb92 9.5 ^3</v> <v>tb101 9.6 ^4</v>
+ <v>^5</v> <v>^6</v> <v>^7</v> <v>^8</v> <v>^9</v> <v>^10</v>
+ <v>Future</v>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:variable>
+
+<xsl:template match="/SystemDefinition" priority="2">
+ <!-- see above for Run usage -->
+ <xsl:choose>
+ <xsl:when test="$Run = 'calc' ">
+ <!-- just do 1st pass calculations like sizing and legend generation -->
+ <xsl:apply-templates select="." mode="sizing"/>
+ </xsl:when>
+ <xsl:when test="$Run = 'draw' ">
+ <!-- draw from pre-calculated data -->
+ <xsl:apply-templates select="." mode="draw"/>
+ </xsl:when>
+ <xsl:otherwise> <!-- the normal case, run w/1st pass for sizing, then draw -->
+ <xsl:variable name="sysdef">
+ <xsl:apply-templates select="." mode="sizing"/>
+ </xsl:variable>
+ <xsl:apply-templates select="exslt:node-set($sysdef)/SystemDefinition" mode="draw"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+
+<xsl:template match="SystemDefinition" mode="draw">
+ <xsl:if test="@resolution"><xsl:processing-instruction name="AdobeSVGViewer">resolution="<xsl:value-of select="@resolution"/>"</xsl:processing-instruction></xsl:if>
+ <!-- groupDy padding around whole thing -->
+ <svg version="1.1" onload="wrapalltext()" viewBox="{-$groupDy} {-$groupDy} {@width + $groupDy} {@height + 2* $groupDy}">
+ <xsl:attribute name="class">
+ <xsl:if test="not(@detail)">component</xsl:if>
+ <xsl:value-of select="@detail"/>
+ <xsl:if test="@detail-type">-<xsl:value-of select="@detail-type"/></xsl:if>
+ </xsl:attribute>
+ <xsl:copy-of select="@xml:lang"/> <!-- localized language -->
+ <xsl:if test="not(@static='true') and (@navctrl or */meta/legend/@float)">
+ <xsl:attribute name="onscroll">resized()</xsl:attribute>
+ <xsl:attribute name="onzoom">resized()</xsl:attribute>
+ <xsl:attribute name="onresize">resized()</xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="." mode="title"/>
+
+ <defs>
+
+ <style type="text/css">
+ text.layer, text.package, text.collection, text.component,
+ text.cbox, text.lgrp, text.label, text.lgd {
+ fill:black;
+ font-family: <xsl:call-template name="default-font"/>;
+ }
+ text.title {
+ fill:red;
+ font-weight: bold;
+ font-size: <xsl:call-template name="title-line-height"/>px;
+ font-family: <xsl:call-template name="default-font"/>;
+ }
+ text.component {
+ font-size: 1.940px; /* 5.5pt */
+ font-weight: bold;
+ }
+ text.lgd,
+ text.layer, text.package {
+ font-size: 4.233px; /* 12pt */
+ font-weight: bold;
+ }
+ text.label {
+ font-size: 1.940px; /* 5.5pt */
+ font-weight: bold
+ }
+ text.level {
+ font-style: italic;
+ fill: blue;
+ }
+ g.layer text.level {
+ font-size: 7.055px; /* 20pt */
+ font-style: italic;
+ fill: red;
+ }
+ g.package text.level {
+ font-size: 4.233px; /* 12pt */
+ }
+ g.nested text.level {
+ font-size: 3.175px; /* 8pt */
+ }
+
+ text.cbox {
+ font-size: 1.411px; /* 4pt */
+ font-weight: bold
+ }
+ text.lgrp {
+ font-size: 12.699px; /* 36pt */
+ font-weight: normal;
+ }
+<!-- package font sizes: larger if there is no displayed children -->
+g.placeholder text.package,
+svg.package text.package,
+svg.package-fixed text.package {
+ font-size: 11.288px; /* 32pt */
+ font-weight: normal;
+ }
+
+
+<!-- subpackage font sizes -->
+ g.nested text.package {
+ font-size: 2.822px; /* 8pt */
+ }
+
+ svg.collection g.nested text.package,
+ svg.collection-fixed g.nested text.package {
+ font-size: 4.233px; /* 12pt */
+ }
+
+ svg.package g.nested text.package,
+ svg.package-fixed g.nested text.package {
+ font-size: 7.055px; /* 20pt */
+ }
+<!-- collection font sizes -->
+ text.collection {
+ font-size: 2.469px; /* 7pt */
+ }
+
+ g.placeholder text.collection,
+ svg.collection text.collection,
+ svg.collection-fixed text.collection {
+ font-size: 3.7035px; /* 10.5pt */
+ }
+<!-- borders -->
+ /* thin border */
+ rect.legend, rect.collection, rect.cbox {
+ stroke-width: 0.0882px; /* 0.25pt */
+ stroke: black
+ }
+ /* thick border */
+ rect.layer, rect.package {
+ stroke-width: 0.2469px; /* 0.7pt */
+ stroke: black
+ }
+ rect.layer {
+ fill: #e6e6e6
+ }
+ rect.package {
+ fill: #b3b3b3
+ }
+ g.nested rect.package {
+ fill: #e6e6e6
+ }
+ rect.collection {
+ fill: white
+ }
+ rect.legend {
+ fill: white
+ }
+ <!-- opera does not support <style media="print">, so must use @media instead -->
+ @media print {
+ #Zoom {visibility: hidden}
+ }
+ </style>
+ <xsl:apply-templates select="." mode="shapes"/>
+
+ </defs>
+
+<script type="text/ecmascript">
+<!-- for creating / finding elements by namespace -->
+var svgns="http://www.w3.org/2000/svg";
+
+<xsl:call-template name="script-wrapping"/>
+<xsl:call-template name="script-popups"/> <!-- dependencies use this and they override @static -->
+<xsl:if test="not(@static='true')">
+ <xsl:if test="@navctrl">
+ <xsl:call-template name="script-navcontrol"/>
+ </xsl:if>
+function resized()
+ {
+ var viewbox = document.documentElement.getAttribute("viewBox").split(' ');
+ var x = Number(viewbox[0]);
+ var y = Number(viewbox[1]);
+ var width = Number(viewbox[2]);
+ var height = Number(viewbox[3]);
+ if( window.innerWidth==0 || window.innerHeight ==0 || height ==0) {return}
+ var s = width / window.innerWidth;
+ if ( width / height < window.innerWidth / window.innerHeight)
+ {
+ s = height / window.innerHeight;
+ width = window.innerWidth * s;
+ }
+ else
+ {
+ height = window.innerHeight * s;
+ }
+<xsl:if test="@navctrl">
+ var e = document.getElementById('Zoom');
+ var trans = 'translate(';
+ trans+= x - 0.5* (width - viewbox[2]) + ( -document.rootElement.currentTranslate.x ) * s / document.rootElement.currentScale ;
+ trans+=' ';
+ trans+= y - 0.5* (height - viewbox[3]) + ( -document.rootElement.currentTranslate.y ) * s / document.rootElement.currentScale ;
+ trans+=') scale(';
+ trans+= (height / window.innerHeight) *3.2 / document.rootElement.currentScale;
+ trans+=')';
+ e.setAttribute('transform',trans);
+</xsl:if>
+<xsl:if test="*/meta/legend/@float">
+ e = document.getElementById('legend-display');
+ var ctrl = document.getElementById('legend-ctrl');
+ var wBox = Number(ctrl.getAttribute('width'));
+ scale = (width / window.innerWidth) * (window.innerWidth / ( wBox+3)) / document.rootElement.currentScale;
+ trans = 'translate(';
+ trans+= x + (1.5 *scale ) -0.5* (width - viewbox[2]) + ( -document.rootElement.currentTranslate.x ) * s / document.rootElement.currentScale ;
+ trans+=' ';
+ trans+= y -(14.3 +0.3)* scale - 0.5* (height - viewbox[3] ) + ( -document.rootElement.currentTranslate.y ) * s / document.rootElement.currentScale
+ + height / document.rootElement.currentScale
+ trans+=') scale(';
+ trans+= scale;
+ trans+=')';
+ e.setAttribute('transform',trans);</xsl:if>
+ }
+ <xsl:if test="*/meta/legend/@float">
+ <xsl:call-template name="script-float-legend"/>
+ </xsl:if>
+</xsl:if>
+</script>
+ <xsl:variable name="model-bottom">
+ <!-- The y-location of the bottom of the model itself -->
+ <xsl:for-each select="*[1]"> <!-- should only be one child -->
+ <xsl:choose>
+ <xsl:when test="meta[@rel='model-logo']/@height and (meta[@rel='model-logo']/@height >meta[@rel='model-legend']/@height or not(meta[@rel='model-legend']))">
+ <xsl:value-of select="../@height - sum (meta[@rel='model-footer' or @rel='model-logo']/@height) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="../@height - sum (meta[@rel='model-footer' or @rel='model-legend']/@height) "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <!-- these meta go under the model -->
+ <xsl:apply-templates select="*/meta[not(starts-with(@rel,'model-'))]" mode="global"/>
+
+ <xsl:apply-templates select="*"/>
+
+ <!-- do these meta last so that it could obscure the model if it needs to -->
+
+ <xsl:apply-templates select="*/meta[starts-with(@rel,'model-')]" mode="global">
+ <xsl:sort select="@rel"/>
+ <xsl:with-param name="bottom" select="$model-bottom"/>
+ </xsl:apply-templates>
+ <xsl:if test="not(@static='true') and @navctrl">
+ <xsl:call-template name="navctrl"/>
+ </xsl:if>
+<!--
+<rect x="0" y="0" width="{@width}" height="{@height}" fill="none" stroke="black" stroke-width="1"/>
+<rect x="{@padding-left}" y="0" width="{@model-width}" height="{@model-height}" fill="none" stroke="black" stroke-width="1"/>
+<xsl:for-each select="meta[@rel='model-footer']">
+ <rect x="0" y="{../@height - @height}" width="{../@width}" height="{@height}" fill="none" stroke="green" stroke-width="1"/>
+</xsl:for-each>
+<xsl:for-each select="meta[@rel='model-logo']">
+ <rect x="0" y="{$model-bottom}" width="{@width}" height="{@height}" fill="none" stroke="green" stroke-width="1"/>
+</xsl:for-each>
+<xsl:for-each select="meta[@rel='model-legend']">
+ <rect x="{../@width - legend/@title-width * @scaled}" y="{$model-bottom}" width="{legend/@title-width * @scaled }" height="{legend/@title-height * @scaled}" fill="none" stroke="green" stroke-width="1"/>
+</xsl:for-each>
+-->
+ <xsl:apply-templates mode="validate"/>
+</svg>
+</xsl:template>
+
+<xsl:template match="systemModel">
+ <xsl:apply-templates select="*"/>
+</xsl:template>
+
+
+<xsl:template match="*" mode="filter"/> <!-- filters for all items -->
+<xsl:template match="*" mode="text-filter"/> <!-- fitler for just text -->
+
+
+<!-- scripts -->
+<xsl:template name="script-popups">
+<!-- for pop-ups which can only appear one at a time.
+In general, one would want to use
+ onmouseover="on('blah') onmouseout="off('blah')"
+for stuff which appears and disappears based on the position of the mouse (like dependency arrows)
+
+for stuff which appears based on a mouseover or button press, but does not
+disappear until some other trigger (and only one can appear at a time), use one of:
+ onmouseover="on(clear('blah'))"
+ onclick="on(clear('blah'))"
+-->
+var curId = '';
+function clear(id) {
+ if(curId != '') off(curId);
+ return curId=id;
+}
+
+<!-- for showing and hiding :
+ not used by default, but used by higher-detailed versions when Static is not set
+ also used by post-processed versions for showing pop-up data.-->
+function on(id) {
+ var cur =document.getElementById(id)
+ cur.setAttribute('visibility','visible');
+ <xsl:if test="not(@detail='component')"><!-- this is needed to wrap text which is initially hidden -->
+ if(!cur.hasAttribute('wrapenated')) {
+ cur.setAttribute('wrapenated','true');
+ wrapalltext(cur)
+ }
+ </xsl:if>
+ return cur;
+}
+
+function off(id) {
+ document.getElementById(id).setAttribute('visibility','hidden');
+}
+</xsl:template>
+
+
+<xsl:template name="script-wrapping">
+<!-- for wrapping: breaks text up into an array of words -->
+function splitup(txt) {
+ var a = new Array;
+ var t = txt;
+ var found <!-- \u4e00-\ufa2 is the unicode range for kanjii, \u3041-\u309 is katakana and e\u30a1-\u30fe is hiragana-->
+ while((found = t.match(/(^[\u3041-\u309e\u30a1-\u30fe\u4e00-\ufa2d])([\u3041-\u309e\u30a1-\u30fe\u4e00-\ufa2d].*)$/))|| ( found = t.match(/^([^ \u200b\xad-]+[ \u200b\xad-]+)(.*)$/))) {
+ a.push(found[1]);
+ t=found[2];
+ }
+ a.push(t);
+ return a;
+}
+<!-- the remainder of the scripts also are for wrapping
+
+Note that comments are kept to an absolute minimum inline since it's a waste of
+ space in the generated file to duplicate the unused text
+-->
+<![CDATA[
+function splitable(node) {
+ return node.firstChild.nodeType == 3 && node.firstChild.data.match(/[\t\n\r \u200b\xad-]/);
+}
+
+function crush(node, len) {
+ node.setAttribute('letter-spacing','-0.075em');
+ if( node.getComputedTextLength() > len)
+ node.setAttribute('letter-spacing','-0.15em');
+}
+
+function whatSize(txt) { // convert a length into pixels
+ if(txt.match(/^[0-9.-]+$/)) return txt;
+ return;
+}
+
+
+function wrapalltext(node) {
+ if(!node) node= document;
+ var all = node.getElementsByTagNameNS(svgns,'text');
+ var i=0;
+ for (i=0; i<all.length; i++) {
+ var cur = all.item(i);
+ var w=0;
+ if (cur.hasAttribute('width')) {
+ w = whatSize(cur.getAttribute('width'));
+ }
+ if (w) wraptext(cur,w)
+ }
+}
+
+
+function wraptext(cur,l) {
+ if(cur.firstChild.nodeType != 3) return; // must be just a text node
+ if(cur.getBBox().width < l ) {
+ cur.firstChild.data = cur.firstChild.data.replace(/[\xad\u200b]/g,"");
+ return; // no need -- won't wrap
+ }
+ var t = cur.firstChild.data.replace(/\s+/," "); // normalize all spaces
+ t = t.replace(/^ +/,"").replace(/ +$/,""); // trim spaces
+ var words =splitup(t); // each word ends with the split character (if any)
+ if (words.length<2) {
+ crush(cur, l);
+ return;
+ }
+ cur.removeChild(cur.firstChild)
+ var tspan = document.createElementNS(svgns,'tspan');
+ var first = tspan;
+ cur.appendChild(tspan);
+ var txt = document.createTextNode(words[0]);
+ tspan.appendChild(txt);
+ tspan.setAttribute('x',cur.getAttribute('x')); // Opera needs this
+ var nlines=1;
+ var zero =0;
+ for (i =1;i< words.length;i++) {
+ var was = txt.data;
+ txt.data+=words[i];
+ if (tspan.getComputedTextLength() -zero > l) { // if the line with this word at the end is bigger than the available space...
+ txt.data=was.replace(/ +$/,"").replace(/\xad(.)/,"$1").replace(/\u200b/g,""); // remove zero-width spaces and trailing spaces and soft hyphens
+ // if it's still too big then decrease the letter spacing
+ if( tspan.getComputedTextLength() > l ) crush(tspan,l);
+ tspan = document.createElementNS(svgns,'tspan');
+ tspan.setAttribute('dy',"1em");
+ nlines++;
+ tspan.setAttribute('x',cur.getAttribute('x'));
+ cur.appendChild(tspan);
+ txt = document.createTextNode('');
+ tspan.appendChild(txt);
+ zero = tspan.getComputedTextLength();
+ txt.data+=words[i];
+ }
+ }
+ txt.data=txt.data.replace(/ +$/,"").replace(/\xad(.)/,"$1").replace(/\u200b/g,""); // remove zero-width spaces and trailing spaces and soft hyphens
+ if( tspan.getComputedTextLength() > l ) crush(tspan,l);
+ var align =cur.getAttribute('dy');
+ if(align=='0.375em') { // middle aligned
+ first.setAttribute('dy',((1-nlines ) / 2 + 0.375 )+"em");
+ } else if(align=='0.75em' || align=='1em') { // top (or above) aligned
+ first.setAttribute('dy',align)
+ } else { // bottom aligned (default)
+ first.setAttribute('dy',(1-nlines)+"em");
+ }
+}
+]]>
+ <!--
+ dominant-baseline is not widely supported, but should indicate the vertical alignment of the text
+ mathematical = middle-aligned
+ hanging = top-aligned
+ ideographic = bottom aligned
+ Since they're not widely supported, using dy is used instead.
+ Ideally we'd have
+ top aligned: dy="1.5ex"
+ middle aligned: dy="0.75ex"
+ bottom aligned: dy="0ex"
+ since in most fonts the top of the captial letters is about 0.5ex higher than the
+ top of the lower case letters (1ex), hence 1.5ex for top-algined and half that for middle
+ However, you can't add the em-based offset of multiple lines to the ex-based alignment,
+ so we have to make the reasonably valid assumption that 1em = 2ex
+ Which gives us:
+ top aligned: dy="0.75em"
+ middle aligned: dy="0.375em"
+ bottom aligned: dy="0em"
+ Since this is supported is Firefox 3.5, ASV and Opera 9, it's a much better way to handle
+ he alighment than using the dominant-baseline approach
+ -->
+</xsl:template>
+
+<xsl:template name="script-navcontrol">
+<!-- this should only be called on the SystemDefinition element -->
+var pandandzoom=null;
+function endpanning()
+ {
+ if(pandandzoom)
+ {
+ window.clearInterval(pandandzoom)
+ pandandzoom=null
+ }
+ }
+
+function repeatpan(x,y)
+ {
+ endpanning()
+ panning(x,y)
+ pandandzoom = window.setInterval('panning('+x+','+y+')', 100);
+ }
+
+function panning(x,y)
+ {
+ document.rootElement.currentTranslate.x += x
+ document.rootElement.currentTranslate.y += y
+ }
+
+function repeatzoom(z)
+ {
+ endpanning()
+ zoom(z)
+ pandandzoom = window.setInterval('zoom('+z+')', 100);
+ }
+<![CDATA[
+function zoom(z)
+ {
+ var viewbox = document.documentElement.getAttribute("viewBox").split(' ');
+ var x = Number(viewbox[0]);
+ var y = Number(viewbox[1]);
+ var width = Number(viewbox[2]);
+ var height = Number(viewbox[3]);
+ if( window.innerWidth==0 || window.innerHeight ==0 || height ==0) {return}
+ var s = width / window.innerWidth;
+ if ( width / height < window.innerWidth / window.innerHeight)
+ {
+ s = height / window.innerHeight;
+ width = window.innerWidth * s;
+ }
+ else
+ {
+ height = window.innerHeight * s;
+ }
+
+ x = x - 0.5* (width - viewbox[2]) + ( -document.rootElement.currentTranslate.x ) * s / document.rootElement.currentScale ;
+ y = y - 0.5* (height - viewbox[3]) + ( -document.rootElement.currentTranslate.y ) * s / document.rootElement.currentScale ;
+ width = width / document.rootElement.currentScale;
+ height = height / document.rootElement.currentScale;
+ document.rootElement.currentTranslate.x=
+ document.rootElement.currentTranslate.x *z - 0.5*window.innerWidth* (z -1 )
+ document.rootElement.currentTranslate.y=
+ document.rootElement.currentTranslate.y *z - 0.5*window.innerHeight* (z -1 )
+ document.rootElement.currentScale*=z
+ }
+]]>
+</xsl:template>
+
+<xsl:template name="script-float-legend">
+function movelegend(id)
+ {
+ var parent = document.getElementById(id);
+ var legend = document.getElementById('legend-box');
+ parent.appendChild(legend);
+ }
+</xsl:template>
+
+<!-- well known patterns -->
+
+<xsl:template name="default-new-pattern">
+ <radialGradient id="Patternradial-grad" gradientUnits="objectBoundingBox" cx="50%" cy="50%" r="70%">
+ <stop offset="0%" stop-color="white" stop-opacity="1"/>
+ <stop offset="100%" stop-opacity="0" stop-color="white" />
+ </radialGradient>
+</xsl:template>
+
+<xsl:template name="default-ref-pattern"> <!-- diagonal line pattern -->
+ <linearGradient id="Patternstriped-diag-up" spreadMethod="repeat" gradientUnits="userSpaceOnUse" x1="0" x2="3" y1="0" y2="3">
+ <stop offset="0%" stop-opacity="0" stop-color="white" />
+ <stop offset="20%" stop-color="#ccc" stop-opacity="1" />
+ <stop offset="40%" stop-opacity="0" stop-color="white" />
+ <stop offset="100%" stop-opacity="0" stop-color="white" />
+ </linearGradient>
+</xsl:template>
+
+<xsl:template name="default-X-pattern"> <!-- big dark X -->
+ <pattern id="Patternbig-X" patternUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%" viewBox="0 0 10 10">
+ <path d="M 1 1 L 9 9 M 1 9 L 9 1" stroke="#555" stroke-width="1.15" stroke-linecap="round"/>
+ </pattern>
+</xsl:template>
+
+
+
+<xsl:template name="nav-control-patterns"> <!-- patterns needed for the naviagiton control -->
+ <radialGradient id="Patternoutgrad" cx="50%" cy="50%" r="100%" fx="50%" fy="50%">
+ <stop offset="36%" stop-color="white" stop-opacity="0"/>
+ <stop offset="43%" stop-color="white" stop-opacity="0.6" />
+ <stop offset="50%" stop-color="white" stop-opacity="0"/>
+ <stop offset="100%" stop-color="black" stop-opacity="0"/>
+ </radialGradient>
+ <radialGradient id="Patterningrad" cx="50%" cy="50%" r="100%" fx="50%" fy="50%">
+ <stop offset="0%" stop-color="white" stop-opacity="0.45"/>
+ <stop offset="36%" stop-color="yellow" stop-opacity="0"/>
+ <stop offset="43%" stop-color="yellow" stop-opacity="0.6" />
+ <stop offset="50%" stop-color="yellow" stop-opacity="0"/>
+ <stop offset="100%" stop-color="black" stop-opacity="0"/>
+ </radialGradient>
+</xsl:template>
+
+
+<!-- well-known border shapes -->
+
+
+<xsl:template name="default-box-border">
+ <symbol id="Borderbox" viewBox="0 0 20 20">
+ <path d="M 0 0 L 0 20 L 20 20 L 20 0 z" stroke="black"/>
+ </symbol>
+</xsl:template>
+<xsl:template name="default-clipLB-border">
+ <symbol id="Borderbox-clipLB" viewBox="0 0 20 20">
+ <path d="M 0 0 L 0 15 L 5 20 L 20 20 L 20 0 z" stroke="black"/>
+ </symbol>
+</xsl:template>
+<xsl:template name="default-clipLT-border">
+ <symbol id="Borderbox-clipLT" viewBox="0 0 20 20">
+ <path d="M 5 0 L 0 5 L 0 20 L 20 20 L 20 0 z" stroke="black"/>
+ </symbol>
+</xsl:template>
+<xsl:template name="default-clipRB-border">
+ <symbol id="Borderbox-clipRB" viewBox="0 0 20 20">
+ <path d="M 0 0 L 0 20 L 15 20 L 20 15 L 20 0 z" stroke="black"/>
+ </symbol>
+</xsl:template>
+<xsl:template name="default-clipRT-border">
+ <symbol id="Borderbox-clipRT" viewBox="0 0 20 20">
+ <path d="M 0 0 L 0 20 L 20 20 L 20 5 L 15 0 z" stroke="black"/>
+ </symbol>
+</xsl:template>
+<xsl:template name="default-clipAll-border">
+ <symbol id="Borderbox-clipAll" viewBox="0 0 20 20">
+ <path d="M 5 0 L 0 5 L 0 15 L 5 20 L 15 20 L 20 15 L 20 5 L 15 0 z" stroke="black"/>
+ </symbol>
+</xsl:template>
+<xsl:template name="default-round-border">
+ <symbol id="Borderround" viewBox="0 0 20 20">
+ <circle cx="10" cy="10" r="10" stroke="black" />
+ </symbol>
+</xsl:template>
+<xsl:template name="default-hexagon-border">
+ <symbol id="Borderhexagon" viewBox="0 0 20 20">
+ <path d="M 0 10 L 5.8 0 L 14.2 0 L 20 10 L 14.2 20 L 5.8 20 z" stroke="black" />
+ </symbol>
+</xsl:template>
+
+<!-- end borders -->
+
+ <!-- overridden by output of shapes.xsl -->
+<xsl:template match="SystemDefinition" mode="shapes">
+ <xsl:call-template name="default-new-pattern"/>
+ <xsl:call-template name="default-ref-pattern"/>
+ <xsl:call-template name="default-X-pattern"/>
+ <xsl:if test="not(@static='true') and (@navctrl)">
+ <xsl:call-template name="nav-control-patterns"/>
+ </xsl:if>
+ <!-- borders to use for OSD components -->
+
+ <xsl:call-template name="default-box-border"/>
+ <xsl:call-template name="default-clipLB-border"/>
+ <xsl:call-template name="default-clipLT-border"/>
+ <xsl:call-template name="default-clipRB-border"/>
+ <xsl:call-template name="default-clipRT-border"/>
+ <xsl:call-template name="default-clipAll-border"/>
+</xsl:template>
+
+
+<xsl:template match="component|collection|package|layer" mode="id"><xsl:value-of select="@id"/></xsl:template>
+
+<xsl:template name="linkable-content"><xsl:param name="show"/>
+ <xsl:variable name="found">
+ <xsl:apply-templates select="." mode="has-link"/>
+ </xsl:variable>
+ <xsl:choose> <!-- don't use <a> unless there is a valid link -->
+ <xsl:when test="$found='' or parent::legend">
+ <xsl:copy-of select="$show"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <a>
+ <xsl:apply-templates select="." mode="link-label"/>
+ <xsl:copy-of select="$show"/>
+ </a>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template mode="validate" match="node()" priority="-4"/>
+<xsl:template mode="validate" match="*" priority="-2"><xsl:apply-templates mode="validate" select="*"/></xsl:template>
+
+
+<xsl:template name="display-name">
+ <xsl:apply-templates select="." mode="text-filter"/>
+ <xsl:if test="@font">
+ <xsl:attribute name="style">font-family: '<xsl:value-of select="@font"/>'</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="name-value"/>
+</xsl:template>
+
+<xsl:template name="name-value">
+ <xsl:choose>
+ <xsl:when test="self::cmp or self::cbox or self::legend or self::note or self::layer[legend|note]">
+ <xsl:apply-templates select="." mode="name"/>
+ </xsl:when>
+ <xsl:when test="@abbrev"><xsl:value-of select="@abbrev"/></xsl:when>
+ <xsl:when test="@label"><xsl:value-of select="@label"/></xsl:when> <!-- for legends -->
+ <xsl:when test="@lookup"><xsl:value-of select="@lookup"/></xsl:when> <!-- for legends -->
+ <xsl:when test="$Use-as-name!='name' and @*[name()=$Use-as-name]"><xsl:value-of select="@*[name()=$Use-as-name]"/></xsl:when>
+ <xsl:when test="@name"><xsl:value-of select="@name"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="@id"/></xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+<!-- ============ hyperlinks ============ -->
+
+<xsl:template match="*" mode="has-link"/>
+<xsl:template match="*[@id and ancestor::SystemDefinition/@base]" mode="has-link">1</xsl:template>
+
+<xsl:template match="*" mode="link-label"/>
+<xsl:template match="*[@id]" mode="link-label">
+ <xsl:attribute name="target">details</xsl:attribute>
+ <xsl:attribute name="xlink:href"><xsl:value-of select="ancestor::SystemDefinition/@base"/>/<xsl:choose>
+ <xsl:when test="self::package[parent::package]">SubBlocks</xsl:when>
+ <xsl:when test="self::package">Blocks</xsl:when>
+ <xsl:when test="self::layer">Layers</xsl:when>
+ <xsl:when test="self::component">Components</xsl:when>
+ <xsl:when test="self::collection">Collections</xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="Caller-Error">
+ <xsl:with-param name="text">Invalid element <xsl:value-of select="name()"/> id="<xsl:value-of select="@id"/>". Cannot generate link.</xsl:with-param>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>/<xsl:value-of select="@name"/>.html</xsl:attribute>
+</xsl:template>
+
+<!-- ============ styles ============ -->
+
+
+<xsl:template name="default-font">
+ <xsl:choose>
+ <xsl:when test="ancestor-or-self::SystemDefinition[@font]">'<xsl:value-of select="ancestor-or-self::SystemDefinition/@font"/>'</xsl:when>
+ <xsl:otherwise>Arial</xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="title-line-height">
+ <xsl:choose>
+ <xsl:when test="number(ancestor-or-self::SystemDefinition/systemModel/meta/legend/@title-scale)">
+ <xsl:value-of select="4.3 * ancestor-or-self::SystemDefinition/systemModel/meta/legend/@title-scale"/> <!-- scale 12pt by specified factor-->
+ </xsl:when>
+ <xsl:when test="ancestor-or-self::SystemDefinition/systemModel/meta/legend[@percent-width or @maxscale]">4.233</xsl:when> <!-- 12pt -->
+ <xsl:when test="ancestor-or-self::SystemDefinition/@width > $large-width">6.3495</xsl:when> <!-- 18 pt -->
+ <xsl:otherwise>4.3</xsl:otherwise> <!-- 12pt -->
+ </xsl:choose>
+</xsl:template>
+
+
+<!-- ============ display styles ============ -->
+
+<xsl:template name="styles"><xsl:param name="for" select="'bg'"/>
+ <xsl:variable name="st0">
+ <xsl:apply-templates select="." mode="display-style"/></xsl:variable>
+ <xsl:variable name="st1">
+ <xsl:choose>
+ <xsl:when test="$for='label' and @label-bg">fill:<xsl:value-of select="@label-bg"/>!important;</xsl:when>
+ <xsl:when test="@bg">fill:<xsl:value-of select="@bg"/>!important;</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$st0!='' or $st1!=''">
+ <xsl:attribute name="style">
+ <xsl:value-of select="$st0"/>
+ <xsl:if test="$st0!='' and $st1!='' and substring($st0,string-length($st0))!=';'">;</xsl:if>
+ <xsl:value-of select="$st1"/>
+ </xsl:attribute>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template name="gradient-direction"> <!-- calaulate the x1, etc attrbiutes from the dir ratio string. clip each to the range -1..1 -->
+ <xsl:param name="dx" select="1"/>
+ <xsl:param name="dy" select="0"/>
+ <xsl:if test="$dx!='' and $dy!=''">
+ <xsl:attribute name="x1">
+ <xsl:choose>
+ <xsl:when test="$dx < -1">100%</xsl:when>
+ <xsl:when test="$dx >= 0">0%</xsl:when>
+ <xsl:otherwise><xsl:value-of select="-$dx * 100"/>%</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="x2">
+ <xsl:choose>
+ <xsl:when test="$dx > 1">100%</xsl:when>
+ <xsl:when test="$dx <= 0">0%</xsl:when>
+ <xsl:otherwise><xsl:value-of select="$dx * 100"/>%</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="y1">
+ <xsl:choose>
+ <xsl:when test="$dy < -1">100%</xsl:when>
+ <xsl:when test="$dy >= 0">0%</xsl:when>
+ <xsl:otherwise><xsl:value-of select="-$dy * 100"/>%</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="y2">
+ <xsl:choose>
+ <xsl:when test="$dy >1">100%</xsl:when>
+ <xsl:when test="$dy <= 0">0%</xsl:when>
+ <xsl:otherwise><xsl:value-of select="$dy * 100"/>%</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template name="gradient-angle"> <!-- calaulate the x1, etc attrbiutes from the dir ratio string. clip each to the range -1..1 -->
+ <xsl:param name="theta" select="0"/>
+ <xsl:call-template name="gradient-direction">
+ <xsl:with-param name="dx" select="m:cos($theta * m:constant('PI',6) div 180)"/>
+ <xsl:with-param name="dy" select="-m:sin($theta * m:constant('PI',6) div 180)"/>
+ </xsl:call-template>
+</xsl:template>
+
+
+<!-- provide a gradient of multiple colours for the fill of an item -->
+<xsl:template name="multi-color-grad">
+ <xsl:param name="c" /> <!-- nodeset of either values or values to look up in $key -->
+ <xsl:param name="key" /> <!-- the style ID to lookup the value. Optional. If not set, the value of $c is the value -->
+ <xsl:param name="blur" /> <!-- % to blur 100% mean to blur to the full size of each gradient section -->
+ <xsl:param name="dir" /> <!-- direction ratio in the form dx:dy, where each has a range from -1..1 -->
+ <xsl:param name="angle" /> <!-- angle : use this instead of dir when possible -->
+ <xsl:if test="($key!='' and count(key($key,$c)/@value) > 1) or ($key='' and count($c) > 1) "><!-- only define if there's more than one match -->
+ <linearGradient>
+ <xsl:attribute name="id">bg<xsl:apply-templates select="." mode="id"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="function-available('m:sin') and function-available('m:cos') and function-available('m:constant') and $angle!=''">
+ <xsl:call-template name="gradient-angle">
+ <xsl:with-param name="theta" select="$angle" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="gradient-direction">
+ <xsl:with-param name="dx" select="substring-before($dir,':')"/>
+ <xsl:with-param name="dy" select="substring-after($dir,':')"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:variable name="blur0" select="$blur div count($c)" />
+ <xsl:for-each select="$c">
+ <xsl:sort />
+ <xsl:variable name="value">
+ <xsl:choose>
+ <xsl:when test="$key=''"><xsl:value-of select="."/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="key($key,.)/@value"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <stop offset="{100* (position()-1) div last() + $blur0}%" stop-color="{$value}" />
+ <xsl:if test="position()!=last()">
+ <stop offset="{100* position() div last() - $blur0}%" stop-color="{$value}" />
+ </xsl:if>
+ </xsl:for-each>
+ </linearGradient>
+ </xsl:if>
+</xsl:template>
+<xsl:template mode="multi-color" match="*" priority="-1"/> <!-- this is handled in the generated XSLT, so do nothing by default -->
+
+<xsl:template mode="multi-color" match="*[meta/generator-color]">
+ <xsl:call-template name="multi-color-grad">
+ <xsl:with-param name="key" select="'styled'"/>
+ <xsl:with-param name="c" select="meta/generator-color/@ref"/>
+ <xsl:with-param name="blur" select="0"/>
+ </xsl:call-template>
+</xsl:template>
+
+
+<xsl:template match="*" mode="display-style-color" priority="-2"/>
+<xsl:template match="*" mode="animate-color" priority="-2"/><!-- change from -2 to disable -->
+
+
+<xsl:template match="*[@generator-color]" mode="animate-color" priority="4">
+ <xsl:if test="not(ancestor::SystemDefinition/@static='true')">
+ <set attributeName="opacity" attributeType="XML" to="0.5" fill="remove" begin="{@generator-color}.mouseover" end="{@generator-color}.mouseout"/>
+ </xsl:if>
+</xsl:template>
+<xsl:template match="*[meta/generator-color]" mode="animate-color" priority="4">
+ <xsl:if test="not(ancestor::SystemDefinition/@static='true')">
+ <xsl:for-each select="meta/generator-color">
+ <set attributeName="opacity" attributeType="XML" to="0.5" fill="remove" begin="{@ref}.mouseover" end="{@ref}.mouseout"/>
+ </xsl:for-each>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- generated overrides -->
+
+
+<xsl:template match="*[@generator-color]" mode="display-style-color" priority="8">
+ <xsl:for-each select="key('styled',@generator-color)">
+ <xsl:value-of select="@value | @default"/> <!-- can't have both -->
+ </xsl:for-each>
+</xsl:template>
+
+
+<xsl:template match="*[count(meta/generator-color)=1]" mode="display-style-color" priority="8">
+ <xsl:for-each select="key('styled',meta/generator-color/@ref)">
+ <xsl:value-of select="@value | @default"/> <!-- can't have both -->
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="*[count(meta/generator-color) > 1]" mode="display-style-color" priority="8">
+ <xsl:variable name="ref" select="key('styled',meta/generator-color/@ref)"/>
+ <xsl:choose>
+ <xsl:when test="count($ref/@value)=1">
+ <xsl:value-of select="$ref/@value"/>
+ </xsl:when>
+ <xsl:when test="count($ref/@value)=0">
+ <xsl:value-of select="$ref/@default[last()]"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>url(#bg</xsl:text><xsl:apply-templates select="." mode="id"/><xsl:text>)</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+
+<xsl:template match="*[@generator-text-highlight]" mode="text-filter" priority="8">
+ <xsl:attribute name="filter">url(<xsl:for-each select="key('styled',@generator-text-highlight)">
+ <xsl:value-of select="@value | @default"/> <!-- can't have both -->
+ </xsl:for-each>)</xsl:attribute>
+</xsl:template>
+
+<xsl:template match="*[@generator-highlight]" mode="filter" priority="8">
+ <xsl:attribute name="filter">url(<xsl:for-each select="key('styled',@generator-highlight)">
+ <xsl:value-of select="@value | @default"/> <!-- can't have both -->
+ </xsl:for-each>)</xsl:attribute>
+</xsl:template>
+
+<xsl:template match="*[@generator-overlay|meta/generator-overlay]" mode="overlays" priority="8">
+ <xsl:for-each select="key('styled',@generator-overlay|meta/generator-overlay/@ref)">
+ <o>
+ <xsl:value-of select="@value | @default"/> <!-- can't have both -->
+ </o>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="*[@generator-border]" mode="shape" priority="8">
+ <xsl:for-each select="key('styled',@generator-border)">
+ <xsl:value-of select="@value | @default"/> <!-- can't have both -->
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="*" mode="display-style">
+ <xsl:variable name="color"><xsl:apply-templates select="." mode="display-style-color"/></xsl:variable>
+ <xsl:if test="$color!=''">fill:<xsl:value-of select="$color"/>;</xsl:if>
+ <xsl:for-each select="@generator-style | meta/generator-style/@ref">
+ <xsl:for-each select="key('styled',.)">
+ <xsl:value-of select="concat(@value | @default,';')"/><!-- can't have both -->
+ </xsl:for-each>
+ </xsl:for-each>
+ <xsl:apply-templates select="." mode="display-style-aux"/>
+</xsl:template>
+
+<!-- defaults -->
+
+<xsl:template match="*" mode="display-style-aux" priority="-2"/>
+<xsl:template match="component" mode="display-style-aux" priority="-1">stroke-width:<xsl:choose>
+ <xsl:when test="@plugin">2</xsl:when>
+ <xsl:otherwise>0.4</xsl:otherwise>
+</xsl:choose>;</xsl:template>
+
+<xsl:template match="component|cmp" mode="display-style-color" priority="-1">grey</xsl:template>
+
+<xsl:template match="*" mode="overlay-styles">
+ <!-- overlays just retruns each overlay pattern, this turns them into actual styles -->
+ <xsl:variable name="o">
+ <xsl:apply-templates select="." mode="overlays"/>
+ </xsl:variable>
+ <xsl:for-each select="exslt:node-set($o)/*">
+ <xsl:copy>fill:<xsl:if test=".=''">none</xsl:if>
+ <xsl:if test=".!=''">url(<xsl:value-of select="."/>)</xsl:if>
+ <xsl:text>; stroke: none; stroke-width: 0;</xsl:text>
+ </xsl:copy>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="*" mode="overlays" priority="-3"/>
+
+<xsl:template match="component" mode="overlays" priority="-2">
+ <xsl:if test="@introduced = ancestor::SystemDefinition/@ver"><o>#Patternradial-grad</o></xsl:if>
+ <xsl:if test="@purpose='development' "><o>#Patternstriped-diag-up</o></xsl:if>
+</xsl:template>
+
+<xsl:template match="component|cmp" mode="overlays" priority="-3"/>
+
+<xsl:template match="component|cmp" mode="shape" priority="-1">#Borderbox</xsl:template>
+
+<!-- ====== legend ============= -->
+
+<xsl:include href="legend.xsl"/>
+<!-- end legend -->
+
+
+<!-- ====== drawing ============= -->
+
+<xsl:template match="*" priority="-1">
+ <xsl:call-template name="Caller-Error">
+ <xsl:with-param name="text">Unrecognised elementn <xsl:value-of select="name()"/> not supported</xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<xsl:template match="meta" priority="-1">
+ <xsl:if test="not(following::meta[@rel=current()/@rel])">
+ <xsl:call-template name="Caller-Note">
+ <xsl:with-param name="text">meta rel="<xsl:value-of select="@rel"/>" not supported</xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:call-template name="Caller-Debug">
+ <xsl:with-param name="text">meta rel="<xsl:value-of select="@rel"/>" in <xsl:value-of select="../@id"/> not supported</xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<xsl:template match="meta[@rel='styling' or @rel='Generic' or not(@rel) or @rel='Dependencies' or starts-with(@rel,'model-') or @rel='layer-group' or @rel='config' or @rel='testbuild']"/>
+ <!-- no diagram data in these-->
+
+<xsl:template match="meta[@rel='model-levels']"/> <!-- by default, show no level titles -->
+
+<!-- global stuff is stuff which is drawn outside of any system model item -->
+<xsl:template match="*" mode="global" priority="-1"/>
+
+<!-- ====== layer groups ============= -->
+
+<xsl:template match="meta[@rel='layer-group']" mode="global">
+ <xsl:apply-templates select="layer-group" mode="lgrp">
+ <!-- start as wide as possible and go inward -->
+ <xsl:with-param name="left" select="0"/>
+ <xsl:with-param name="right" select="ancestor::SystemDefinition/@width"/>
+ </xsl:apply-templates>
+</xsl:template>
+
+
+<xsl:template match="layer-group" mode="lgrp">
+ <xsl:param name="left"/><xsl:param name="right"/>
+ <xsl:variable name="From" select="ancestor::systemModel/layer[@id=current()/@from]"/>
+ <xsl:variable name="To" select="ancestor::systemModel/layer[@id=current()/@to]"/>
+ <xsl:choose>
+ <xsl:when test="not($From)">
+ <xsl:call-template name="Caller-Error">
+ <xsl:with-param name="text">layer "<xsl:value-of select="@from"/>" does not exist</xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="not($To)">
+ <xsl:call-template name="Caller-Error">
+ <xsl:with-param name="text">layer "<xsl:value-of select="@to"/>" does not exist</xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="not($From/following-sibling::layer[@id=current()/@to])">
+ <xsl:call-template name="Caller-Error">
+ <xsl:with-param name="text">"<xsl:value-of select="@from"/>" is after "<xsl:value-of select="@to"/>"</xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$To[@span]">
+ <xsl:call-template name="Caller-Error">
+ <xsl:with-param name="text">Layer group cannot be bounded by spanned layer "<xsl:value-of select="@to"/>"</xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$From[@span]">
+ <xsl:call-template name="Caller-Error">
+ <xsl:with-param name="text">Layer group cannot be bounded by spanned layer "<xsl:value-of select="@from"/>"</xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="parent-to" select="count(ancestor::layer-group[@to=current()/@to])"/>
+ <xsl:variable name="child-to" select="1+ count(descendant::layer-group[@to=current()/@to])"/>
+ <xsl:variable name="child-from" select="1+ count(descendant::layer-group[@from=current()/@from])"/>
+ <xsl:variable name="between" select="$From/following-sibling::layer[following-sibling::layer[@id=current()/@to]]"/>
+ <xsl:variable name="height" select="sum($From/@height | $From/@padding-top | $To/@height | $To/@padding-bottom |$between/@height | $between/@padding-top | $between/@padding-bottom) +
+ $lgrpDx * ($child-to+ $child-from) + $groupDy * (1 + count($between))"/>
+ <xsl:variable name="start">
+ <xsl:choose>
+ <xsl:when test="$To/following-sibling::layer[not(@span)]">
+ <xsl:value-of select="sum($To/following-sibling::layer[not(@span)]/@*[name()='height' or name()='padding-bottom' or name()='padding-top'])
+ + $groupDy * count($To/following-sibling::layer[not(@span)]) + $lgrpDx * $parent-to "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$lgrpDx * $parent-to"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="to-name" select="@to"/>
+ <xsl:variable name="from-name" select="@from"/>
+ <g class="{name()}">
+ <rect width="{$right - $left}" height="{$height}" x="{$left}" y="{$start}" rx="{$lyrTitleBox*0.5}" fill="{@color}"/>
+ <xsl:if test="@label">
+ <text text-anchor="middle" dy="0.375em" class="lgrp" transform="rotate(-90)" y="{$left + 0.5 * $lgrpLabelDx}" width="{$height}" x="{- ($start + 0.5 * $height)}">
+ <xsl:value-of select="@label"/>
+ </text>
+ </xsl:if>
+ </g>
+ <xsl:variable name="dx">
+ <xsl:choose>
+ <xsl:when test="@label"><xsl:value-of select="$lgrpLabelDx"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="$lgrpDx * 0.75"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:apply-templates select="layer-group" mode="lgrp">
+ <xsl:with-param name="left" select="$left + $dx"/>
+ <xsl:with-param name="right" select="$right - $lgrpDx"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+
+</xsl:template>
+
+<!-- ====== layers ============= -->
+
+<xsl:template match="layer">
+ <xsl:variable name="y" select="sum(@padding-top|following-sibling::layer[not(@span)]/@*[name()='height' or name()='padding-bottom' or name()='padding-top']) + count(following::layer[not(@span)]) * $groupDy"/>
+
+ <g id="{@id}" transform="translate({ancestor::SystemDefinition/@padding-left - 3.5 - $lyrTitleBox } {$y})">
+ <xsl:call-template name="my-class"/>
+ <xsl:apply-templates select="." mode="filter"/>
+ <xsl:apply-templates select="." mode="animate-color"/>
+ <xsl:apply-templates select="." mode="multi-color"/>
+ <xsl:variable name="show-content" select="not(ancestor::SystemDefinition[@detail='layer' and not(@levels='show')])"/> <!-- only show if showing content -->
+ <xsl:if test="$show-content"> <!-- only show if showing content -->
+ <xsl:call-template name="linkable-content">
+ <xsl:with-param name="show">
+ <rect x="0.3" y="0.3" width="{$lyrTitleBox}" rx="{$lyrTitleBox * 0.5}" ry="{$lyrTitleBox * 0.5}" class="{name()}" height="{@height}">
+ <xsl:call-template name="styles"><xsl:with-param name="for" select="'label'"/></xsl:call-template>
+ </rect>
+ <text text-anchor="middle" dy="0.375em" class="layer" transform="rotate(-90)"
+ y="{$lyrTitleBox * 0.5 + 0.3}" width="{@height}" height="{$lyrTitleBox}" x="{ -(@height div 2 ) - 0.3}">
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:variable name="spans" select="following-sibling::layer[@span and position() - @span <= 0]"/>
+ <xsl:variable name="w" select="ancestor::SystemDefinition/@model-width - sum($spans/@width) - $groupDx * count($spans)"/>
+
+ <xsl:variable name="x-off">
+ <xsl:choose>
+ <xsl:when test="$w <= @width">0</xsl:when> <!-- should never be less than 0 -->
+ <xsl:when test="@align='left'">0</xsl:when>
+ <xsl:when test="@align='right'"><xsl:value-of select="$w - @width"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="0.5 * ($w - @width)"/></xsl:otherwise> <!-- align='center' -->
+ </xsl:choose>
+ </xsl:variable>
+ <g class="layer-detail" transform="translate({3.5 + $lyrTitleBox + $x-off} {sum(@ipad) *0.5})">
+ <xsl:apply-templates select="." mode="detail-stuff"><xsl:with-param name="s" select="'mouseover'"/></xsl:apply-templates>
+ <rect x="{-$x-off}" class="{name()}" y="{-0.5 * sum(@ipad)}" width="{$w}" height="{@height}">
+ <xsl:call-template name="styles"/>
+ <xsl:if test="not($show-content)">
+ <xsl:attribute name="rx"><xsl:value-of select="$lyrTitleBox*0.5"/></xsl:attribute>
+ <xsl:attribute name="ry"><xsl:value-of select="$lyrTitleBox*0.5"/></xsl:attribute>
+ </xsl:if>
+ </rect>
+
+ <xsl:variable name="overlay"><xsl:apply-templates select="." mode="overlay-styles"/></xsl:variable>
+ <xsl:variable name="cur" select="."/>
+
+
+ <xsl:for-each select="exslt:node-set($overlay)/*">
+ <rect x="{-$x-off}" y="{-0.5 * sum($cur/@ipad)}" width="{$w}" height="{$cur/@height}" style="{.}"/>
+ </xsl:for-each>
+
+ <xsl:if test="not($show-content)">
+ <xsl:call-template name="linkable-content">
+ <xsl:with-param name="show">
+ <text text-anchor="middle" dy="0.375em" class="layer"
+ y="{0.5 * @height}" width="{@width}" height="{@height}" x="{ 0.5 * @width}">
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <g><xsl:apply-templates select="." mode="detail-stuff"/>
+ <xsl:apply-templates select="*"/>
+ </g>
+ </g>
+ </g>
+</xsl:template>
+
+<!-- print levels for fixed or non-fixed width -->
+<xsl:template match="layer/meta[@rel='model-levels' and ancestor::SystemDefinition[@levels='show' and @detail='layer']]">
+ <xsl:for-each select="level[@name]">
+ <text text-anchor="middle" class="level" x="{../../@width * 0.5}" width="{../../@width}" dy="0.375em">
+ <xsl:attribute name="y">
+ <xsl:choose>
+ <xsl:when test="ancestor::SystemDefinition/@detail-type='fixed'">
+ <xsl:value-of select="(count(following-sibling::level) + 0.5)* $mHeight * 1.5"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="sum(following-sibling::level/@height) +count(following-sibling::level/@height) + 0.5* @height "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="layer/meta[@rel='model-levels' and ancestor::SystemDefinition[@levels='expand']]">
+ <xsl:variable name="spans" select="../following-sibling::layer[@span and position() - @span <= 0]"/>
+ <xsl:variable name="w" select="ancestor::SystemDefinition/@model-width - sum($spans/@width) - $groupDx * count($spans)"/>
+
+ <xsl:for-each select="level[@name]">
+ <xsl:variable name="y" select="sum(following-sibling::level/@height) + $groupDy * count(following-sibling::level) + 0.5 * @height"/>
+ <text text-anchor="middle" class="level" x="{$w - $levelExpandName * 0.2 - ($w - ../../@width) * 0.5}" width="{@height}" y="{$y}" height="{$levelExpandName}" dy="0em" transform="rotate(-90 {$w - $levelExpandName * 0.2 - ($w - ../../@width) * 0.5} {$y})">
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:for-each>
+</xsl:template>
+
+
+<xsl:template match="layer[@span > 0]">
+ <xsl:variable name="y" select="sum(@padding-top|following-sibling::layer[not(@span)]/@*[name()='height' or name()='padding-bottom' or name()='padding-top']) + count(following::layer[not(@span)]) * $groupDy"/>
+
+ <xsl:variable name="spans" select="following-sibling::layer[@span and position() - @span <= 0]"/>
+ <xsl:variable name="w" select="ancestor::SystemDefinition/@model-width - sum($spans/@width) - $groupDx * count($spans)"/>
+ <xsl:variable name="show-content" select="not(ancestor::SystemDefinition[@detail='layer' and not(@levels='show')])"/> <!-- only show if showing content -->
+
+ <xsl:variable name="x-off" select="$w - @width"/>
+ <g class="{name()}" id="{@id}" transform="translate({$x-off + $groupDx} {$y})">
+ <xsl:apply-templates select="." mode="filter"/>
+ <g class="layer-detail" transform ="translate({$lyrTitleBox + 3.5} {sum(@ipad) *0.5})">
+ <xsl:apply-templates select="." mode="detail-stuff"><xsl:with-param name="s" select="'mouseover'"/></xsl:apply-templates>
+ <rect x="0" class="{name()}" y="{-0.5 * sum(@ipad)}" width="{@width}" height="{@height}">
+ <xsl:call-template name="styles"/>
+ <xsl:if test="not($show-content)">
+ <xsl:attribute name="rx"><xsl:value-of select="$lyrTitleBox*0.5"/></xsl:attribute>
+ <xsl:attribute name="ry"><xsl:value-of select="$lyrTitleBox*0.5"/></xsl:attribute>
+ </xsl:if>
+ </rect>
+
+ <xsl:variable name="overlay"><xsl:apply-templates select="." mode="overlay-styles"/></xsl:variable>
+ <xsl:variable name="cur" select="."/>
+ <xsl:for-each select="exslt:node-set($overlay)/*">
+ <rect x="0" width="{$cur/@width}" height="{$cur/@height}" y="{-0.5 * sum($cur/@ipad)}" style="{.}"/>
+ </xsl:for-each>
+
+ <xsl:call-template name="linkable-content">
+ <xsl:with-param name="show">
+ <text text-anchor="middle" class="layer" width="{@width}" x="{@width div 2}">
+ <xsl:attribute name="y">
+ <xsl:choose>
+ <xsl:when test="ancestor::SystemDefinition[@detail='layer']">
+ <xsl:value-of select="@height * 0.5"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@height - $groupDy - 2.3"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:if test="ancestor::SystemDefinition[@detail='layer']"> <!-- middle align if no content, otherwise text goes at bottom -->
+ <xsl:attribute name="dy">0.375em</xsl:attribute>
+ <xsl:copy-of select="@height"/>
+ </xsl:if>
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:with-param>
+ </xsl:call-template>
+ <g><xsl:apply-templates select="." mode="detail-stuff"/>
+ <xsl:apply-templates select="*"/>
+ </g>
+ </g>
+ </g>
+
+</xsl:template>
+
+<xsl:template name="my-class">
+ <xsl:attribute name="class">
+ <xsl:value-of select="name()"/>
+ <xsl:if test="not(*[not(self::meta)])"> placeholder</xsl:if>
+ <xsl:if test="name()=name(..)"> nested</xsl:if>
+ </xsl:attribute>
+</xsl:template>
+
+<!-- ====== packages ============= -->
+<xsl:template match="package">
+
+ <xsl:variable name="match" select="../meta[@rel='model-levels']/level[@name=current()/@level or not(current()/@level) or (current()/@span and following-sibling::level[position() < current()/@span][@name=current()/@level or (not(@name) and current()/@level='*')]) or (current()/@level='*' and not(@name))]"/>
+
+ <xsl:variable name="h">
+ <xsl:choose>
+ <xsl:when test="$match"> <!-- get height from height of (spanned) levels -->
+ <xsl:value-of select="sum($match/@height) + $groupDy * (count($match) - 1)"/>
+ </xsl:when>
+ <xsl:when test="parent::layer/@span or count(../package)!=1"> <!-- has siblings, so height of layer will do (- padding) -->
+ <xsl:value-of select="../@height - sum(../@ipad)"/>
+ </xsl:when>
+ <xsl:otherwise><xsl:value-of select="@height"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="x">
+ <xsl:choose>
+ <xsl:when test="../meta[@rel='model-levels']/level/step[@ref=current()/@id]">
+ <xsl:value-of select="../meta[@rel='model-levels']/level/step[@ref=current()/@id]/@x"/>
+ </xsl:when>
+ <xsl:otherwise><xsl:value-of select="sum(preceding-sibling::package/@width) + count(preceding-sibling::package) * $groupDx"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="lev" select="../meta[@rel='model-levels']/level[@name=current()/@level or (current()/@level='*' and not(@name))]"/>
+ <xsl:variable name="y" select="sum($lev/following-sibling::level/@height) + $groupDy * count($lev/following-sibling::level)"/>
+
+ <xsl:variable name="translate-y">
+ <xsl:choose>
+ <xsl:when test="@levels or not(collection/@level)"><xsl:value-of select="$y"/></xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <g id="{@id}">
+ <xsl:call-template name="my-class"/>
+ <xsl:apply-templates select="." mode="detail-stuff"><xsl:with-param name="s" select="'mouseover'"/></xsl:apply-templates>
+ <xsl:apply-templates select="." mode="filter"/>
+ <xsl:attribute name="transform">translate( <xsl:value-of select="concat($x,' ',$translate-y)"/>)</xsl:attribute>
+ <xsl:apply-templates select="." mode="animate-color"/>
+ <xsl:apply-templates select="." mode="multi-color"/>
+ <rect class="{name()}" x="0" width="{@width}" height="{$h}" y="{$y - $translate-y }">
+ <xsl:call-template name="styles"/>
+ </rect>
+
+ <xsl:variable name="overlay"><xsl:apply-templates select="." mode="overlay-styles"/></xsl:variable>
+ <xsl:variable name="cur" select="."/>
+ <xsl:for-each select="exslt:node-set($overlay)/*">
+ <rect x="0" width="{$cur/@width}" height="{$h}" y="{$y - $translate-y }" style="{.}"/>
+ </xsl:for-each>
+ <xsl:variable name="middle" select="not(collection|package) or (ancestor::SystemDefinition[@detail='package' and not(@levels='show')] and not(package))"/>
+
+ <xsl:variable name="text-off"> <!-- middle-align if not showing children -->
+ <xsl:choose>
+ <xsl:when test="$middle"><xsl:value-of select="$h *0.5"/></xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="padding" select="sum(@ipad) + number($h - @height > 2 * $groupDy) * 2 * $groupDy * (1 - count(@ipad))"/>
+ <!-- use @ipad or 2groupdy if h is significantly bigger then @height -->
+ <!-- label goes here -->
+ <xsl:call-template name="linkable-content">
+ <xsl:with-param name="show">
+ <text text-anchor="middle" class="package" width="{@width}" x="{@width div 2}" y="{ $y + $h - $text-off - $translate-y - 1 }">
+ <xsl:apply-templates select="." mode="detail-stuff"><xsl:with-param name="s" select="'text'"/></xsl:apply-templates>
+ <!-- centre-align if not showing children -->
+ <xsl:if test="$middle">
+ <xsl:attribute name="dy">0.375em</xsl:attribute>
+ <xsl:attribute name="height"><xsl:value-of select="@height"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="txt"><xsl:call-template name="name-value"/></xsl:variable>
+ <xsl:variable name="level-h" select="count(meta[@rel='model-levels']/level) * ($mHeight + $groupDy) - $groupDy + $padding"/>
+ <xsl:choose>
+ <!-- the $cSize * string-length($txt) * 0.25 assumes 4 chars per component-width is a good
+ determinant of the amount of pkg text that can fit in a given width. This fails, of course, when
+ the font or font size changes via CSS, something that can't be resolved here at all, however
+ it's not a bad failsafe condition, since it just puts text where there is the most room for it
+ It just might look funny if the font is smaller than expected and there'd be plenty of room for
+ it at the bottom.
+ The ".../level[1]/@width != 0 and count(...) > 1" means that if the first level has nothing in it,
+ then there's plenty of room and no need for an inline label
+ The ($h - $level-h < $mHeight)" bit means the same thing, except it takes into account that the
+ levels might not go all the way to the bottom of the pkg
+ -->
+ <xsl:when test="package"/> <!-- can't be inline -->
+ <xsl:when test="@width < $cSize * string-length($txt) * 0.25 and meta[@rel='model-levels']/level[1]/@width != 0 and count(meta[@rel='model-levels']/level) > 1 and ($h - $level-h < $mHeight)">
+ <xsl:variable name="min-width">
+ <xsl:for-each select="meta[@rel='model-levels']/level">
+ <xsl:sort select="@width" order="ascending" data-type="number"/>
+ <xsl:if test="position()=1"><xsl:value-of select="@width"/></xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:if test="$min-width = @width or @width - $min-width > $inlineLabel and string-length($txt) > 12">
+ <xsl:call-template name="inline-label">
+ <xsl:with-param name="y0" select="$y - $translate-y "/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="$pkgLabelSize <= $h - $level-h "/> <!-- plenty of room on bottom, no need for inline label -->
+ <xsl:when test="ancestor::SystemDefinition[@detail='collection' or @detail='component' or @detail='layer']">
+ <xsl:call-template name="inline-label">
+ <xsl:with-param name="y0" select="$y - $translate-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:with-param>
+ </xsl:call-template>
+
+
+
+ <g>
+ <xsl:if test="$padding !=0"><xsl:attribute name="transform">translate(0 <xsl:value-of select="0.5* $padding"/>)</xsl:attribute></xsl:if>
+ <xsl:apply-templates select="." mode="detail-stuff"/>
+ <xsl:apply-templates select="*"/>
+ </g>
+
+ </g>
+</xsl:template>
+
+<!-- print pkg levels if desired -->
+<xsl:template match="package/meta[@rel='model-levels' and ancestor::SystemDefinition[@levels='show' and @detail='package']]" >
+ <xsl:for-each select="level">
+ <xsl:if test="@name">
+ <text text-anchor="start" class="level" x="{$groupDx}" width="{../../@width - 2 * $groupDx}" y="{count(../../parent::package) *$groupDy + (last() - position()) * ($mHeight + $groupDy) }" dy="0.75em">
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template match="package/meta[@rel='model-levels' and ancestor::SystemDefinition[@levels='expand']]">
+ <xsl:for-each select="level">
+ <xsl:if test="@name">
+ <xsl:variable name="y" select="count(../../parent::package) * $groupDy + (last() - position()) * ($mHeight + $groupDy) + 0.5 * $mHeight"/>
+ <text text-anchor="middle" class="level" x="{../../@width - $levelExpandName * 0.2 }" width="{$mMinWidth}" height="{$levelExpandName}" y="{$y}" transform="rotate(-90 {../../@width - $levelExpandName * 0.2 } {$y})" dy="0em">
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="inline-label"><xsl:param name="y0"/>
+ <xsl:variable name="thin-level">
+ <xsl:for-each select="meta[@rel='model-levels']/level">
+ <xsl:sort select="@width" order="ascending" data-type="number"/>
+ <xsl:sort select="count(preceding-sibling::level)" order="ascending" data-type="number"/> <!-- to make sure it's at the lowest level if there is a choice -->
+ <xsl:if test="position()=1"><xsl:value-of select="@name"/></xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="lev" select="meta[@rel='model-levels']/level[@name=$thin-level or $thin-level='' and not(@name)]"/>
+ <xsl:variable name="y" select="$y0 + count($lev/following-sibling::level) * ($mHeight + $groupDy) + sum(@ipad) *0.5 "/>
+ <xsl:attribute name="dy">0.375em</xsl:attribute>
+ <xsl:attribute name="width"><xsl:value-of select="@width - $lev/@width"/></xsl:attribute>
+ <xsl:attribute name="x"><xsl:value-of select="0.5 * (@width + $lev/@width)"/></xsl:attribute> <!-- centre-aligned -->
+ <xsl:attribute name="y"><xsl:value-of select="$y + 0.5 * $mHeight"/></xsl:attribute> <!-- middle-algined -->
+</xsl:template>
+
+
+
+<!--- sub-packages -->
+
+<xsl:template match="package/package" priority="2">
+ <xsl:variable name="x">
+ <xsl:call-template name="sum-list">
+ <xsl:with-param name="list">
+ <xsl:value-of select="sum(preceding-sibling::package/@width) + $groupDx * count(preceding-sibling::package)"/>
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates mode="effective-width" select="preceding-sibling::collection[following-sibling::*[1][self::package]]">
+ <xsl:with-param name="levels"><xsl:copy-of select="../meta[@rel='model-levels']/level"/></xsl:with-param>
+ </xsl:apply-templates>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <g id="{@id}" transform="translate({$x})">
+ <xsl:call-template name="my-class"/>
+ <xsl:apply-templates select="." mode="filter"/>
+ <xsl:apply-templates select="." mode="detail-stuff"><xsl:with-param name="s" select="'mouseover'"/></xsl:apply-templates>
+ <xsl:apply-templates select="." mode="animate-color"/>
+ <xsl:apply-templates select="." mode="multi-color"/>
+ <rect class="{name()}" x="0" height="{@height}" width="{@width}" y ="0">
+ <xsl:if test="not(collection) or ancestor::SystemDefinition/@detail=name()">
+ <!-- to make room for the block label -->
+ <xsl:attribute name="height"><xsl:value-of select="@height"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="styles"/>
+ </rect>
+
+
+ <xsl:variable name="overlay"><xsl:apply-templates select="." mode="overlay-styles"/></xsl:variable>
+ <xsl:variable name="cur" select="."/>
+ <xsl:for-each select="exslt:node-set($overlay)/*">
+ <rect x="0" height="{$cur/@height}" width="{$cur/@width}" y ="0" style="{.}">
+ <xsl:if test="not($cur/collection) or $cur/ancestor::SystemDefinition/@detail=name($cur)">
+ <!-- to make room for the block label -->
+ <xsl:attribute name="height"><xsl:value-of select="$cur/@height"/></xsl:attribute>
+ </xsl:if>
+ </rect>
+ </xsl:for-each>
+ <xsl:call-template name="linkable-content">
+ <xsl:with-param name="show">
+ <!-- default is for not showing detail, since it's easy to calculate -->
+ <text text-anchor="middle" class="{name()}" dy="0.375em" x="{@width * 0.5}" width="{@width}" y="{0.5 * @height}">
+ <xsl:apply-templates select="." mode="detail-stuff"><xsl:with-param name="s" select="'text'"/></xsl:apply-templates>
+ <xsl:if test="not(ancestor::SystemDefinition/@detail='package')">
+ <xsl:call-template name="inline-label">
+ <xsl:with-param name="y0" select="0"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:with-param>
+ </xsl:call-template>
+ <g><xsl:apply-templates select="." mode="detail-stuff"/>
+ <xsl:apply-templates select="*"/>
+ </g>
+ </g>
+</xsl:template>
+
+
+<!-- ====== collections ============= -->
+
+<xsl:template match="collection">
+<xsl:variable name="y" >
+ <xsl:choose>
+ <xsl:when test="ancestor::package/@levels or not(ancestor::layer/meta[@rel='model-levels'])">
+ <!-- the positions come from the pkg only -->
+ <xsl:value-of select="count(../meta[@rel='model-levels']/level[(current()[not(@level)] and not(@name)) or @name=current()/@level]/following-sibling::level) * ($mHeight + $groupDy)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- the positions come from the levels from the layer -->
+ <xsl:variable name="lev" select="ancestor::layer/meta[@rel='model-levels']/level[(current()[not(@level)] and not(@name)) or @name=current()/@level]/following-sibling::level"/>
+ <xsl:value-of select="sum($lev/@height) + $groupDy * count($lev)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:variable>
+
+ <xsl:variable name="on-level" select="preceding-sibling::collection[(current()[not(@level)] and not(@level)) or @level=current()/@level]"/>
+
+
+<xsl:variable name="x">
+ <xsl:choose>
+ <xsl:when test="../package and not(preceding-sibling::package)">
+ <!-- treat as if it's a normal collection-->
+ <xsl:value-of select="sum($on-level/@width) + $groupDx * count($on-level) "/>
+ </xsl:when>
+ <xsl:when test="../package">
+ <xsl:call-template name="sum-list">
+ <xsl:with-param name="list">
+ <xsl:value-of select="sum(preceding-sibling::package/@width) + $groupDx * count(preceding-sibling::package)"/>
+ <xsl:text> </xsl:text>
+ <xsl:apply-templates mode="effective-width" select="preceding-sibling::collection[following-sibling::*[1][self::package]]">
+ <xsl:with-param name="levels"><xsl:apply-templates select=".." mode="levels"/></xsl:with-param>
+ </xsl:apply-templates>
+ <xsl:variable name="prev" select="preceding-sibling::collection[preceding-sibling::package[@id=current()/preceding-sibling::package[1]/@id]][@level = current()/@level or (not(@level) and not(current()/@level))]"/>
+ <xsl:if test="$prev">
+ <xsl:value-of select="concat(sum($prev/@width) + $groupDx * count($prev), ' ')"/>
+ </xsl:if>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="sum($on-level/@width) + $groupDx * count($on-level) "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+
+ <g id="{@id}" transform="translate({$x} {$y})"><xsl:apply-templates select="." mode="filter"/>
+ <xsl:call-template name="my-class"/>
+ <xsl:apply-templates select="." mode="detail-stuff"><xsl:with-param name="s" select="'mouseover'"/></xsl:apply-templates>
+ <xsl:apply-templates select="." mode="animate-color"/>
+ <xsl:apply-templates select="." mode="multi-color"/>
+ <rect class="{name()}" x="0" y="0" height="{@height}" width="{@width}">
+ <xsl:call-template name="styles"/>
+ </rect>
+ <xsl:variable name="overlay"><xsl:apply-templates select="." mode="overlay-styles"/></xsl:variable>
+ <xsl:variable name="cur" select="."/>
+ <xsl:for-each select="exslt:node-set($overlay)/*">
+ <rect width="{$cur/@width}" height="{$cur/@height}" x="0" y="0" style="{.}"/>
+ </xsl:for-each>
+
+
+
+ <xsl:call-template name="linkable-content">
+ <xsl:with-param name="show">
+ <!-- dy=1em means top align, but leave a bit of space up there so the top of the text is not flush against the border
+ The alternative would be set y to a fixed offset (like the 1.4 x-offset) and use dy="0.75em" to make the text be
+ flush against this offset, but I suspect the 1em method will look better in a wider variety of fonts-->
+ <text text-anchor="start" dy="1em" class="collection" y="0" x="1.4" width="{@width - 1.4}">
+ <xsl:apply-templates select="." mode="detail-stuff"><xsl:with-param name="s" select="'text'"/></xsl:apply-templates>
+ <xsl:choose>
+ <xsl:when test="not(component) or ancestor::SystemDefinition/@detail='collection' ">
+ <xsl:attribute name='text-anchor'>middle</xsl:attribute>
+ <xsl:attribute name='x'><xsl:value-of select="@width * 0.5"/></xsl:attribute>
+ <xsl:attribute name='dy'>0.375em</xsl:attribute> <!-- middle align if no content -->
+ <xsl:attribute name="y"><xsl:value-of select="@height * 0.5"/></xsl:attribute>
+ <xsl:attribute name="height"><xsl:value-of select="@height"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="height"><xsl:value-of select="@height - component/@height"/></xsl:attribute> <!--all children are the same size -->
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:with-param>
+ </xsl:call-template>
+ <g transform="translate(0 {@height - $cSize})">
+ <xsl:apply-templates select="." mode="detail-stuff"/>
+ <xsl:apply-templates select="*"/>
+ </g>
+ </g>
+</xsl:template>
+
+
+<!-- ====== components ============= -->
+
+<xsl:template match="component|cmp">
+ <xsl:param name="spacing" select="0"/>
+ <!-- the bulk of the following is for cmp, not component -->
+ <xsl:variable name="x-pos">
+ <xsl:choose>
+ <xsl:when test="self::cmp">
+ <xsl:value-of select="sum(preceding-sibling::*/@width | preceding-sibling::*/@rpad | ../@label-width) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="sum(preceding-sibling::component/@width) "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <g id="{@id}">
+ <xsl:call-template name="my-class"/>
+ <xsl:apply-templates select="." mode="filter"/>
+ <xsl:if test="parent::collection">
+ <xsl:apply-templates select="." mode="animate-color"/>
+ <xsl:apply-templates select="." mode="multi-color"/>
+ </xsl:if>
+ <xsl:variable name="ref"><xsl:apply-templates select="." mode="shape"/></xsl:variable>
+ <use width="{@width}" height="{@height}" x="{$x-pos}" y="0" xlink:href="{$ref}">
+ <xsl:variable name="style"><xsl:apply-templates select="." mode="display-style"/></xsl:variable>
+ <xsl:if test="string-length($style) > 1">
+ <xsl:attribute name="style"><xsl:value-of select="$style"/></xsl:attribute>
+ </xsl:if>
+ </use>
+ <xsl:variable name="overlay"><xsl:apply-templates select="." mode="overlay-styles"/></xsl:variable>
+ <xsl:variable name="cur" select="."/>
+ <xsl:for-each select="exslt:node-set($overlay)/*">
+ <use width="{$cur/@width}" height="{$cur/@height}" x="{$x-pos}" y="0" style="{.}" xlink:href="{$ref}"/>
+ </xsl:for-each>
+ <xsl:call-template name="linkable-content">
+ <xsl:with-param name="show">
+ <text text-anchor="middle" dy="0.375em" class="component" y="{@height * 0.5 + 0.15}" width="{@width}" height="{@height}" x="{$x-pos + 0.5 * @width}">
+ <xsl:call-template name="display-name"/>
+ </text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </g>
+</xsl:template>
+
+
+<!-- ============ Detail options============ -->
+
+<!-- don't show when not enough detail -->
+<xsl:template match="component[not(ancestor::SystemDefinition[@detail='component' or not(@static='true' or @detail-type='fixed')]) ]" priority="9"/>
+<xsl:template match="collection[ ancestor::SystemDefinition[(@detail='layer' or @detail='package') and (@static='true' or @detail-type='fixed')] ]" priority="9"/>
+<xsl:template match="package[ancestor::SystemDefinition[@detail='layer' and (@static='true' or @detail-type='fixed')] ]" priority="9"/>
+
+<xsl:template match="*[ancestor::SystemDefinition/@detail='component']" mode="detail-stuff" priority="9"/>
+<xsl:template match="*" mode="detail-stuff" priority="-5"/>
+
+<xsl:template match="*[ancestor::SystemDefinition/@static='true']" mode="detail-stuff" priority="7"/>
+<xsl:template match="*[ancestor::SystemDefinition/@detail-type='fixed']" mode="detail-stuff" priority="8"/>
+
+<xsl:template match="collection[ancestor::SystemDefinition/@detail!='collection'] | *[(ancestor::SystemDefinition/@detail='collection') and not(self::collection)]" mode="detail-stuff" priority="5"/>
+
+<xsl:template match="collection|package[ancestor::SystemDefinition/@detail='package' and not(package)] | layer[ancestor::SystemDefinition/@detail=name()]" mode="detail-stuff">
+ <xsl:param name="s" select="'content'"/>
+ <xsl:choose>
+ <xsl:when test="$s='mouseover'">
+ <xsl:attribute name="onmouseover">on('<xsl:value-of select="name()"/>-content-<xsl:value-of select="@id"/>');off('<xsl:value-of select="name()"/>-label-<xsl:value-of select="@id"/>');</xsl:attribute>
+ <xsl:attribute name="onmouseout">off('<xsl:value-of select="name()"/>-content-<xsl:value-of select="@id"/>');on('<xsl:value-of select="name()"/>-label-<xsl:value-of select="@id"/>');</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$s='text'">
+ <xsl:attribute name="id"><xsl:value-of select="name()"/>-label-<xsl:value-of select="@id"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="id"><xsl:value-of select="name()"/>-content-<xsl:value-of select="@id"/></xsl:attribute>
+ <xsl:attribute name="visibility">hidden</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template priority="8" match="package[package and ancestor::SystemDefinition/@detail='package']/collection" mode="detail-stuff"><xsl:param name="s" select="'content'"/>
+ <xsl:if test="$s='mouseover'">
+ <xsl:attribute name="id"><xsl:value-of select="name()"/>-content-<xsl:value-of select="@id"/></xsl:attribute>
+ <xsl:attribute name="visibility">hidden</xsl:attribute>
+ </xsl:if>
+</xsl:template>
+
+
+<xsl:template match="layer[ancestor::SystemDefinition/@detail=name() or not(package)]" mode="detail-stuff"><xsl:param name="s" select="'content'"/>
+ <xsl:choose>
+ <xsl:when test="$s='mouseover'">
+ <xsl:attribute name="onmouseover">on('<xsl:value-of select="name()"/>-content-<xsl:value-of select="@id"/>')</xsl:attribute>
+ <xsl:attribute name="onmouseout">off('<xsl:value-of select="name()"/>-content-<xsl:value-of select="@id"/>')</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$s!='text'">
+ <xsl:attribute name="id"><xsl:value-of select="name()"/>-content-<xsl:value-of select="@id"/></xsl:attribute>
+ <xsl:attribute name="visibility">hidden</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+<xsl:template match="*[ancestor::systemModel/@detail='layer' and not(self::layer)]" mode="detail-stuff"/>
+
+
+<xsl:template name="navctrl">
+ <g id="Zoom" onload="resized()">
+ <set attributeType="CSS" attributeName="opacity" to="0.8" fill="freeze" begin="Zoom.mouseover"/>
+ <set attributeType="CSS" attributeName="opacity" to="0.8" fill="freeze" begin="Zoomin.mouseover"/>
+ <set attributeType="CSS" attributeName="opacity" to="0.8" fill="freeze" begin="Zoomout.mouseover"/>
+ <animate attributeType="CSS" attributeName="opacity" from="0.8" to="0" fill="freeze" dur="0.5s" begin="10s"/>
+ <animate attributeType="CSS" attributeName="opacity" from="0.8" to="0" fill="freeze" dur="0.2s" begin="Zoom.mouseout" />
+ <animate attributeType="CSS" attributeName="opacity" from="0.8" to="1" fill="freeze" dur="0.5s" begin="0.3s" />
+
+ <path d="M0,0 l15,0 l0,30 a 7.5,7.5 18 0,1 -15, 0Z" fill="rgb(0,102,153)" opacity="0.8"/>
+ <g onclick="zoom(1.25)">
+ <path d="M7.5,4.5 l0,3 m1.5,-1.5 l-3,0" stroke="yellow" stroke-width="1" pointer-events="none" />
+ <circle id="Zoomin" r="4.5" cx="7.5" cy="6" fill="url(#Patternoutgrad)">
+ <set attributeType="XML" attributeName="fill" to="url(#Patterningrad)" fill="freeze" begin="Zoomin.mouseover" />
+ <set attributeType="XML" attributeName="fill" to="url(#Patternoutgrad)" fill="freeze" begin="Zoomin.mouseout" />
+ </circle>
+ </g>
+ <g onclick="zoom(0.8)">
+ <path d="M5.5,18 l4,0" stroke="yellow" stroke-width="1" pointer-events="none" />
+ <circle r="4.5" cx="7.5" cy="18" fill="url(#Patternoutgrad)" id="Zoomout">
+ <set attributeType="XML" attributeName="fill" to="url(#Patterningrad)" fill="freeze" begin="Zoomout.mouseover" />
+ <set attributeType="XML" attributeName="fill" to="url(#Patternoutgrad)" fill="freeze" begin="Zoomout.mouseout" />
+ </circle>
+ </g>
+ <path id="MoveUp" d="M7.5,25 l1.5,3 l-3,0 Z" fill-opacity="0.2" stroke-opacity="0.7" stroke-linejoin="round" fill="white" stroke="white" stroke-width="0.4" onmousedown="repeatpan(0,20)" onmouseup="endpanning()">
+ <set attributeType="XML" attributeName="stroke" to="yellow" end="MoveUp.mouseout" begin="MoveUp.mouseover" />
+ </path>
+ <path id="MoveDown" d="M6,33 l3,0 l-1.5,3 Z" fill-opacity="0.2" stroke-linejoin="round" stroke-opacity="0.7" fill="white" stroke="white" stroke-width="0.4" onmousedown="repeatpan(0,-20)" onmouseup="endpanning()">
+ <set attributeType="XML" attributeName="stroke" to="yellow" end="MoveDown.mouseout" begin="MoveDown.mouseover" />
+ </path>
+ <path id="MoveRight" d="M10,29 l3,1.5 l-3,1.5 Z" fill-opacity="0.2" stroke-linejoin="round" stroke-opacity="0.7" fill="white" stroke="white" stroke-width="0.4" onmousedown="repeatpan(-20,0)" onmouseup="endpanning()">
+ <set attributeType="XML" attributeName="stroke" to="yellow" end="MoveRight.mouseout" begin="MoveRight.mouseover" />
+ </path>
+ <path id="MoveLeft" d="M5,29 l0,3 l-3,-1.5 Z" fill-opacity="0.2" stroke-linejoin="round" stroke-opacity="0.7" fill="white" stroke="white" stroke-width="0.4" onmousedown="repeatpan(20,0)" onmouseup="endpanning()">
+ <set attributeType="XML" attributeName="stroke" to="yellow" end="MoveLeft.mouseout" begin="MoveLeft.mouseover" />
+ </path>
+ </g>
+</xsl:template>
+
+
+<xsl:include href="draw-model.xsl"/>
+</xsl:stylesheet>
\ No newline at end of file