sysmodellibs/sysmodelgen/core/draw-model.xsl
changeset 7 3c36c452f013
equal deleted inserted replaced
6:5b32dc297d05 7:3c36c452f013
       
     1 <?xml version="1.0"?>
       
     2  <xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"   xmlns:s="http://www.w3.org/2000/svg" xmlns:exslt="http://exslt.org/common" xmlns:m="http://exslt.org/math" exclude-result-prefixes="s m exslt" >
       
     3 <!--Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 	All rights reserved.
       
     5 	This component and the accompanying materials are made available
       
     6 	under the terms of the License "Eclipse Public License v1.0"
       
     7 	which accompanies this distribution, and is available
       
     8 	at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     9 
       
    10 	Initial Contributors:
       
    11 	Nokia Corporation - initial contribution.
       
    12 	Contributors:
       
    13 	Description:
       
    14 	Create a stand-alone sysdef from a linked set of fragments
       
    15 -->
       
    16 	  <xsl:key name="color" match="legend/cbox" use="@value"/>
       
    17 
       
    18 	<xsl:output method="xml" cdata-section-elements="script s:script" indent="yes"/>
       
    19 
       
    20 <xsl:param name="pkgLabelSize" select="4.23"/> <!-- the height needed at the bottom of a package for the label (mm) -->
       
    21 
       
    22 <!-- /SystemDefinition/@detail  = The level of detail to show in the diagram. 
       
    23 	The value is the name of the lowest element to show. If @static  is set to false, mousing-over an item will show its detailed content. 
       
    24 	By default this is equivalent to 'component' -->
       
    25 
       
    26 <!-- ====== Constants ============= -->
       
    27 <xsl:param name="groupDx" select="2.1"/> <!-- the horizontal distance between groups (mm) -->
       
    28 <xsl:param name="groupDy" select="3.2"/> <!-- the vertical distance between groups (mm) -->
       
    29 <xsl:param name="cSize" select="9.3"/> <!-- the width and height of a component (mm) -->
       
    30 <xsl:param name="mHeight" select="15.6"/> <!-- the height of a collection (mm) -->
       
    31 <xsl:param name="mMinWidth" select="15.6"/> <!-- the minimum width of a collection (mm) -->
       
    32 <xsl:param name="lyrFixedWidth" select="$mMinWidth * 6"/><!-- fixed width of a layer (mm)-->
       
    33 <xsl:param name="pkgMinWidth" select="$cSize * 3"/><!-- small pkg, use min width of 2 * smallest possible collection -->
       
    34 <xsl:param name="subpkgMinWidth" select="$cSize * 3"/> <!-- small nested pkg, use min width of  3 components -->
       
    35 <xsl:param name="pkgFixedWidth" select="$mMinWidth * 5"/><!-- fixed width of a  pacakge (mm) -->
       
    36 <xsl:param name="pkgAuxWidth" select="0"/><!-- Additional width on the right side of each package (mm) -->
       
    37 <xsl:param name="subpkgFixedWidth" select="$mMinWidth * 3"/> <!-- fixed width nested pkg (mm) -->
       
    38 <xsl:variable name="inlineLabel" select="3 * $cSize"/> <!-- the max width of an inline label. 3 times the width of a collection by default 
       
    39 	I don't like this. Should compute somehow and make local variable. -->
       
    40 <xsl:variable name="detail-block-space" select="6"/>
       
    41 <xsl:param name="lyrTitleBox" select="9.3"/> <!-- the width of the layer's title box (mm) -->
       
    42 <xsl:variable name="lgrpDx" select="5"/> <!-- the width of a layer group border (mm)-->
       
    43 <xsl:variable name="lgrpLabelDx" select="$lyrTitleBox + 5.7"/> <!-- the width of a layer group title (mm) -->
       
    44 <xsl:variable name="levelExpandName" select="$cSize"/> <!-- the height of the name when levels are being shown inline (mm) -->
       
    45 
       
    46 <xsl:param name="Verbose" select="0"/> <!-- Verbosity level of messages. Set to 1 (or higher) to get runtime comments  -->
       
    47 
       
    48 <!-- ====== Computed values ============= -->
       
    49 
       
    50 
       
    51 <xsl:template name="Caller-Debug"><xsl:param name="text"/>
       
    52 	<xsl:if test="$Verbose &gt; 4"><xsl:message>&#xa;Note: <xsl:value-of select="$text"/></xsl:message></xsl:if>
       
    53 </xsl:template>
       
    54 <xsl:template name="Caller-Note"><xsl:param name="text"/>
       
    55 	<xsl:message>&#xa;Note: <xsl:value-of select="$text"/></xsl:message>
       
    56 </xsl:template>
       
    57 <xsl:template name="Caller-Warning"><xsl:param name="text"/>
       
    58 	<xsl:message>&#xa;Warning: <xsl:value-of select="$text"/></xsl:message>
       
    59 </xsl:template>
       
    60 <xsl:template name="Caller-Error"><xsl:param name="text"/>
       
    61 	<xsl:message>&#xa;Error: <xsl:value-of select="$text"/></xsl:message>
       
    62 </xsl:template>
       
    63 <xsl:template name="Critical-Error"><xsl:param name="text"/>
       
    64 	<xsl:message terminate="yes">&#xa;Error: <xsl:value-of select="$text"/></xsl:message>
       
    65 </xsl:template>
       
    66 
       
    67 
       
    68 <xsl:template match="/SystemDefinition">
       
    69 		<xsl:apply-templates select="." mode="sizing"/>
       
    70 </xsl:template>
       
    71 
       
    72 
       
    73 <xsl:template match="node()" mode="sizing"><xsl:copy-of select="."/></xsl:template>
       
    74 
       
    75 <xsl:template match="systemModel" mode="sizing">
       
    76 	<!-- 1st pass to compute the sizes of everything -->
       
    77 	<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
    78 		<xsl:apply-templates select="*" mode="sizing"/>
       
    79 	</xsl:copy>
       
    80 </xsl:template>
       
    81 
       
    82 <xsl:template match="meta" mode="sizing">
       
    83 	<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
    84 		<xsl:attribute name="width">0</xsl:attribute>
       
    85 		<xsl:attribute name="height">0</xsl:attribute>
       
    86 		<xsl:copy-of select="node()"/>
       
    87 	</xsl:copy>
       
    88 </xsl:template>
       
    89 
       
    90 <xsl:template name="full-width">
       
    91 	<xsl:param name="w0" select="@width"/>
       
    92 	<xsl:param name="lscale"/>
       
    93 	<!-- call from item which contains the global metas -->
       
    94 	<xsl:variable name="logo-w" select="sum(meta[@rel='model-logo']/@width) + $groupDx * count(meta[@rel='model-logo'])"/>
       
    95 	<xsl:choose>
       
    96 		<xsl:when test="not(meta[@rel='model-legend']) and meta[@rel='model-logo'] and meta[@rel='model-logo']/@width &gt; $w0 ">
       
    97 			<!-- no legend, but a logo that's wider than the model, use logo width -->
       
    98 			<xsl:value-of select="meta[@rel='model-logo']/@width"/>
       
    99 		</xsl:when>
       
   100 		<xsl:when test="not(meta[@rel='model-legend']/legend)">
       
   101 			<!-- no legend, and if there is a logo it's narrower than the model, use model width -->
       
   102 			<xsl:value-of select="$w0"/>
       
   103 		</xsl:when>
       
   104 		<xsl:when test="meta[@rel='model-legend']/legend/@percent-width and meta[@rel='model-legend']/legend/@percent-width &lt;= 100">
       
   105 			<!-- legend takes up less than the full width of the model, so it can be ignored -->
       
   106 			<xsl:value-of select="$w0"/>
       
   107 		</xsl:when>
       
   108 		<xsl:when test="meta[@rel='model-legend']/@width * $lscale + $logo-w &gt; $w0">
       
   109 			<!-- if the legend is scaled so that it's wider than the model, then use that width -->
       
   110 			<xsl:value-of select="meta[@rel='model-legend']/@width * $lscale + $logo-w"/>
       
   111 		</xsl:when>
       
   112 		<xsl:otherwise> <!-- legend scaling is smaller than the width, so use model width-->
       
   113 			<xsl:value-of select="$w0"/>
       
   114 		</xsl:otherwise>
       
   115 	</xsl:choose>
       
   116 </xsl:template>
       
   117 
       
   118 <xsl:template name="full-height"><xsl:param name="lscale"/>
       
   119 <!--
       
   120  HEIGHT:
       
   121  if there is no scaling, add max(legend height , logo height) to the page height
       
   122  if there is scaling use max(legend height * scale , logo height) 
       
   123 -->
       
   124 	<xsl:call-template name="sum-list">
       
   125 		<xsl:with-param name="list">
       
   126 			<xsl:value-of select="concat($groupDy,' ')"/>
       
   127 			<xsl:choose>
       
   128 			
       
   129 				<xsl:when test="not(meta[@rel='model-legend']/legend) and meta[@rel='model-logo'] ">
       
   130 					<!-- no legend, but there's a logo, so add that height -->
       
   131 					<xsl:value-of select="meta[@rel='model-logo']/@height"/>
       
   132 				</xsl:when>
       
   133 				<xsl:when test="not(meta[@rel='model-legend']/legend)">0</xsl:when>			<!-- no legend and no logo -->
       
   134 				<xsl:when test="meta[@rel='model-legend']/@height * $lscale &gt; sum(meta[@rel='model-logo']/@height)">
       
   135 					<!-- legend is taller than the logo, use legend -->
       
   136 					<xsl:value-of select="meta[@rel='model-legend']/@height * $lscale"/>
       
   137 				</xsl:when>
       
   138 				<xsl:otherwise> <!-- legend is not at tall as the logo, use logo -->
       
   139 					<xsl:value-of select="meta[@rel='model-logo']/@height"/>
       
   140 				</xsl:otherwise>
       
   141 			</xsl:choose><xsl:text> </xsl:text>
       
   142 			<xsl:if test="meta[@rel='model-footer']">
       
   143 				<xsl:value-of select="concat(meta[@rel='model-footer']/@height,' ')"/>
       
   144 			</xsl:if>
       
   145 	
       
   146 			<xsl:if test="not(layer)">  <!-- not a full model, just use this one item -->
       
   147 				<xsl:value-of select="@height"/> 
       
   148 			</xsl:if>
       
   149 			<!-- padding + extra padding from layer groups for full model-->
       
   150 			<xsl:if test="layer"> 
       
   151 				<xsl:value-of select="concat(sum(layer[not(@span) or @span=0]/@height), ' ')"/>
       
   152 				<xsl:value-of select="count(layer[not(@span) or @span=0]) * $groupDy + sum(layer[not(@span) or @span=0]/@*[name()='padding-bottom' or name()='padding-top'])"/>
       
   153 			</xsl:if>
       
   154 			<xsl:text> </xsl:text>
       
   155 		</xsl:with-param>
       
   156 	</xsl:call-template>
       
   157 </xsl:template>			
       
   158 
       
   159 <xsl:template match="/SystemDefinition" mode="sizing">
       
   160 	<!-- not full model, just one item  -->
       
   161 	<!-- 1st pass to compute the sizes of everything -->
       
   162 
       
   163 	<xsl:variable name="content">
       
   164 		<xsl:apply-templates mode="sizing"/>
       
   165 	</xsl:variable>
       
   166 
       
   167 	<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   168 		<xsl:attribute name="padding-left">0</xsl:attribute>
       
   169 		<xsl:attribute name="padding-right">0</xsl:attribute>
       
   170 
       
   171 		<xsl:for-each select="exslt:node-set($content)/*">
       
   172 			<xsl:attribute name="model-width"><xsl:value-of select="@width"/></xsl:attribute>
       
   173 			<xsl:attribute name="model-height"><xsl:value-of select="@height"/></xsl:attribute>
       
   174 			<!-- the width without taking the legend into account -->
       
   175 			<xsl:variable name="lscale"> <!-- legend scaling --> 
       
   176 				<xsl:apply-templates select="meta[@rel='model-legend']/legend" mode="scale-factor">
       
   177 					<xsl:with-param name="full-width" select="current()/@width + $groupDy"/>
       
   178 				</xsl:apply-templates>
       
   179 			</xsl:variable>
       
   180 
       
   181 			<xsl:attribute name="width">
       
   182 				<xsl:call-template name="full-width">
       
   183 					<xsl:with-param name="w0" select="current()/@width + $groupDy"/>
       
   184 					<xsl:with-param name="lscale" select="$lscale"/>
       
   185 				</xsl:call-template>
       
   186 			</xsl:attribute>
       
   187 			<xsl:attribute name="height">
       
   188 				<xsl:call-template name="full-height">
       
   189 					<xsl:with-param name="lscale" select="$lscale"/>
       
   190 				</xsl:call-template>
       
   191 			</xsl:attribute>
       
   192 			<xsl:copy><xsl:copy-of select="@*"/> 	<!--  the root item  -->
       
   193 				<xsl:for-each select="meta[@rel='model-legend']">
       
   194 					<!-- copy legend 1st and add scaling -->
       
   195 					<xsl:copy>
       
   196 						<xsl:copy-of select="@*[name()!='width' and name()!='height']"/>
       
   197 						<xsl:attribute name="width"><xsl:value-of select="@width * $lscale"/></xsl:attribute>
       
   198 						<xsl:attribute name="height"><xsl:value-of select="@height * $lscale"/></xsl:attribute>
       
   199 						<xsl:attribute name="scaled"><xsl:value-of select="$lscale"/></xsl:attribute>
       
   200 						<xsl:copy-of select="node()"/>
       
   201 					</xsl:copy>
       
   202 				</xsl:for-each>
       
   203 				<!-- copy everything else -->
       
   204 				<xsl:copy-of select="*[not(self::meta and @rel='model-legend')]"/>
       
   205 			</xsl:copy>
       
   206 		</xsl:for-each>
       
   207 	</xsl:copy>
       
   208 </xsl:template>
       
   209 
       
   210 
       
   211 <xsl:template match="/SystemDefinition[systemModel]" mode="sizing">
       
   212 	<!-- 1st pass to compute the sizes of everything -->
       
   213 
       
   214 	<xsl:variable name="content0">
       
   215 		<xsl:apply-templates mode="sizing"/>
       
   216 	</xsl:variable>
       
   217 
       
   218 	<xsl:variable name="heights">
       
   219 		<xsl:call-template name="layer-height">
       
   220 			<xsl:with-param name="layers">
       
   221 				<xsl:for-each select="exslt:node-set($content0)/systemModel/layer">
       
   222 					<xsl:copy><xsl:copy-of select="@id|@height|@span"/></xsl:copy>
       
   223 				</xsl:for-each>
       
   224 			</xsl:with-param>
       
   225 			<xsl:with-param name="spans" select="exslt:node-set($content0)/systemModel/layer[@span and @span!=0]"/>
       
   226 		</xsl:call-template>
       
   227 	</xsl:variable>
       
   228 
       
   229 	<xsl:variable name="content">
       
   230 		<xsl:apply-templates select="exslt:node-set($content0)/*" mode="adjust-layer-height">
       
   231 			<xsl:with-param name="new-layers" select="exslt:node-set($heights)/layer"/>
       
   232 		</xsl:apply-templates>
       
   233 	</xsl:variable>	 
       
   234 
       
   235 
       
   236 	<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   237 		<xsl:for-each select="exslt:node-set($content)/systemModel">
       
   238 			<xsl:variable name="m-width">
       
   239 				<xsl:call-template name="max-from-list">
       
   240 					<xsl:with-param name="list">		
       
   241 						<xsl:for-each select="layer[not(@span) or @span=0]">
       
   242 							<xsl:value-of select="concat(sum(@width | following-sibling::layer[@span and position() - @span &lt;= 0]/@width) + $groupDx * (count(@width | following-sibling::layer[@span and position() - @span &lt;= 0]/@width)  - 1), ' ')"/>					
       
   243 						</xsl:for-each>
       
   244 					</xsl:with-param> 
       
   245 				</xsl:call-template>
       
   246 			</xsl:variable>
       
   247 			<xsl:attribute name="model-width"><xsl:value-of select="$m-width"/></xsl:attribute>
       
   248 
       
   249 			<xsl:variable name="right-borders">
       
   250 				<xsl:call-template name="max-from-list">
       
   251 					<xsl:with-param name="list">
       
   252 						<xsl:text>0 </xsl:text>
       
   253 						<xsl:for-each select="meta[@rel='layer-group']/layer-group">
       
   254 							<xsl:apply-templates select="." mode="right-border"/><xsl:text> </xsl:text>
       
   255 						</xsl:for-each>
       
   256 					</xsl:with-param>
       
   257 				</xsl:call-template>
       
   258 			</xsl:variable>
       
   259 			<xsl:variable name="left-borders">
       
   260 				<xsl:call-template name="max-from-list">
       
   261 					<xsl:with-param name="list">
       
   262 						<xsl:text>0 </xsl:text>
       
   263 						<xsl:for-each select="meta[@rel='layer-group']/layer-group">
       
   264 							<xsl:apply-templates select="." mode="left-border"/><xsl:text> </xsl:text>
       
   265 						</xsl:for-each>
       
   266 					</xsl:with-param>
       
   267 				</xsl:call-template>
       
   268 			</xsl:variable>
       
   269 			<xsl:attribute name="padding-left"><xsl:value-of select="$left-borders + $lyrTitleBox + 3.5 + $groupDy"/></xsl:attribute>
       
   270 			<xsl:attribute name="padding-right"><xsl:value-of select="$right-borders + $groupDy"/></xsl:attribute>
       
   271 
       
   272 			<!-- the width without taking the legend into account -->
       
   273 			<xsl:variable name="w0"  select="$m-width+ $lyrTitleBox + 3.5 +  2 * $groupDy + $left-borders + $right-borders"/>
       
   274 
       
   275 			<!--
       
   276 			Options for scaling the legend:
       
   277 			WIDTH: 
       
   278 			if the legend has @percent-width, then don't count the legend width in the list
       
   279 			if @percent-width < 100 ignore entirely
       
   280 			if @percent-width > 100 then width = (full width - logo width) * @percent-width % + logo width 
       
   281 			@maxscale is set, then clamp scale to that and recalc width if scale > 1
       
   282 			
       
   283 			if there is no legend scaling
       
   284 			take into account legend width + logo width +padding
       
   285 			-->
       
   286 			
       
   287 			<xsl:variable name="lscale"> <!-- legend scaling --> 
       
   288 				<xsl:apply-templates select="meta[@rel='model-legend']/legend" mode="scale-factor">
       
   289 					<xsl:with-param name="full-width" select="$w0"/>
       
   290 				</xsl:apply-templates>
       
   291 			</xsl:variable>
       
   292 			
       
   293 <!--
       
   294  HEIGHT:
       
   295  if there is no scaling, add max(legend height , logo height) to the page height
       
   296  if there is scaling use max(legend height * scale , logo height) 
       
   297 
       
   298 -->
       
   299 
       
   300 		<xsl:attribute name="model-height">
       
   301 			<xsl:value-of select="count(layer[not(@span) or @span=0]) * $groupDy + sum(layer[not(@span) or @span=0]/@*[name()='height'  or name()='padding-bottom' or name()='padding-top'])"/>
       
   302 		</xsl:attribute>
       
   303 		
       
   304 		<xsl:attribute name="width">
       
   305 				<xsl:call-template name="full-width">
       
   306 					<xsl:with-param name="w0" select="$w0"/>
       
   307 					<xsl:with-param name="lscale" select="$lscale"/>
       
   308 				</xsl:call-template>
       
   309 
       
   310 		</xsl:attribute>
       
   311 		<xsl:attribute name="height">
       
   312 			<xsl:call-template name="full-height">
       
   313 				<xsl:with-param name="lscale" select="$lscale"/>
       
   314 			</xsl:call-template>
       
   315 		</xsl:attribute>
       
   316 		<xsl:copy><xsl:copy-of select="@*"/>
       
   317 			<xsl:for-each select="meta[@rel='model-legend']">
       
   318 				<!-- copy legend 1st and add scaling -->
       
   319 				<xsl:copy>
       
   320 					<xsl:copy-of select="@*[name()!='width' and name()!='height']"/>
       
   321 					<xsl:attribute name="width"><xsl:value-of select="@width * $lscale"/></xsl:attribute>
       
   322 					<xsl:attribute name="height"><xsl:value-of select="@height * $lscale"/></xsl:attribute>
       
   323 					<xsl:attribute name="scaled"><xsl:value-of select="$lscale"/></xsl:attribute>
       
   324 					<xsl:copy-of select="node()"/>
       
   325 				</xsl:copy>
       
   326 			</xsl:for-each>
       
   327 			<!-- copy everything else -->
       
   328 			<xsl:copy-of select="*[not(self::meta and @rel='model-legend')]"/>
       
   329 		</xsl:copy>
       
   330 	</xsl:for-each>
       
   331 	</xsl:copy>
       
   332 </xsl:template>
       
   333 
       
   334 <xsl:template name="layer-height-step">
       
   335 	<xsl:param name="layers"/>
       
   336 	<xsl:param name="span"/>
       
   337 
       
   338 	<xsl:variable name="spanning" select="$span/preceding-sibling::layer[not(@span) and position() &lt;= $span/@span]"/>
       
   339 	
       
   340 	<xsl:variable name="h" select="sum($spanning/@height) + (count($spanning) - 1) * $groupDy"/>
       
   341 	<xsl:variable name="even" select="($span/@height - $h) div count($spanning)"/>
       
   342 	
       
   343 	<xsl:for-each select="exslt:node-set($layers)/layer">
       
   344 		<xsl:copy><xsl:copy-of select="@id|@span"/>
       
   345 			<xsl:choose>
       
   346 				<xsl:when test="0"/> <!-- why? was something removed or should something be here?-->
       
   347 				<xsl:otherwise> <!-- layers smaller than spanned -->
       
   348 					<xsl:choose>
       
   349 						<xsl:when test="$spanning[@id=current()/@id] and $span/@height &gt; $h">
       
   350 							<!-- layers are smaller than spanned layer -->
       
   351 							<xsl:attribute name="height"><xsl:value-of select="@height + $even"/></xsl:attribute>
       
   352 						</xsl:when>
       
   353 						<xsl:when test="@id=$span/@id and $span/@height &lt; $h">
       
   354 							<!-- layers are bigger than spanned layer -->
       
   355 							<xsl:attribute name="height"><xsl:value-of select="$h"/></xsl:attribute>
       
   356 						</xsl:when>
       
   357 						<xsl:otherwise><xsl:copy-of select="@height"/></xsl:otherwise>
       
   358 					</xsl:choose>
       
   359 				</xsl:otherwise>
       
   360 			</xsl:choose>
       
   361 		</xsl:copy>
       
   362 	</xsl:for-each>
       
   363 </xsl:template>
       
   364 
       
   365 <xsl:template name="layer-height">
       
   366 	<xsl:param name="layers"/>
       
   367 	<xsl:param name="spans"/>
       
   368 	<xsl:choose>
       
   369 		<xsl:when test="not($spans)">
       
   370 			<!-- layers are bigger than spanned layer -->
       
   371 			<xsl:copy-of select="$layers"/>
       
   372 		</xsl:when>
       
   373 		<xsl:when test="count($spans)=1">
       
   374 			<xsl:call-template name="layer-height-step">
       
   375 				<xsl:with-param name="layers" select="$layers"/>
       
   376 				<xsl:with-param name="span" select="$spans[1]"/>
       
   377 			</xsl:call-template>
       
   378 		</xsl:when>
       
   379 		<xsl:otherwise>
       
   380 			<xsl:call-template name="layer-height">
       
   381 				<xsl:with-param name="layers">
       
   382 					<xsl:call-template name="layer-height-step">
       
   383 						<xsl:with-param name="layers" select="$layers"/>
       
   384 						<xsl:with-param name="span" select="$spans[1]"/>
       
   385 					</xsl:call-template>
       
   386 				</xsl:with-param>
       
   387 				<xsl:with-param name="spans" select="$spans[position() &gt; 1]"/>
       
   388 			</xsl:call-template>
       
   389 		</xsl:otherwise>
       
   390 	</xsl:choose>
       
   391 </xsl:template>
       
   392 
       
   393 <xsl:template match="legend" mode="scale-factor">
       
   394 	<!--
       
   395 	Options for scaling the legend:
       
   396 	WIDTH: 
       
   397 	if the legend has @percent-width, then don't count the legend width in the list
       
   398 	if @percent-width < 100 ignore entirely
       
   399 	if @percent-width > 100 then width = (full width - logo width) * @percent-width % + logo width 
       
   400 	@maxscale is set, then clamp scale to that and recalc width if scale > 1
       
   401 	
       
   402 	if there is no legend scaling
       
   403 	take into account legend width + logo width +padding
       
   404 	-->
       
   405 	
       
   406 	<xsl:param name="full-width"/>
       
   407 	<!-- the space avialble for the legend -->
       
   408 	<xsl:variable name="available-width" select="$full-width - sum(../../meta[@rel='model-logo']/@width) - $groupDx * count(../../meta[@rel='model-logo'])"/>
       
   409 
       
   410 
       
   411 	<!-- the space the legend wants to take up -->
       
   412 	<xsl:variable name="want-width">
       
   413 		<xsl:choose>
       
   414 			<xsl:when test="@percent-width"><xsl:value-of select="0.01* @percent-width * $available-width"/></xsl:when>
       
   415 			<xsl:otherwise><xsl:value-of select="$available-width"/></xsl:otherwise> <!-- assume 100% in relevent cases where % not set -->
       
   416 		</xsl:choose>
       
   417 	</xsl:variable>	
       
   418 	<xsl:choose>
       
   419 		<xsl:when test="@maxscale and ($want-width &gt; ../@width * @maxscale)"><xsl:value-of select="@maxscale"/></xsl:when> <!-- desired space requires too much scaling, so limit the scale to maxscale -->
       
   420 		<xsl:when test="@maxscale or @percent-width"><xsl:value-of select="$want-width div ../@width"/></xsl:when> <!-- scaling = desired size / available size -->
       
   421 		<xsl:otherwise>1</xsl:otherwise> <!-- don't scale unless asked to -->
       
   422 	</xsl:choose>
       
   423 </xsl:template>
       
   424 
       
   425 <xsl:template match="node()" mode="adjust-layer-height">
       
   426 	<xsl:copy-of select="."/>
       
   427 </xsl:template>
       
   428 
       
   429 <xsl:template match="systemModel" mode="adjust-layer-height">	<xsl:param name="new-layers"/>
       
   430 	<xsl:copy><xsl:copy-of select="@*"/>
       
   431 		<xsl:apply-templates select="*" mode="adjust-layer-height">
       
   432 			<xsl:with-param name="new-layers" select="$new-layers"/>
       
   433 		</xsl:apply-templates>		
       
   434 	</xsl:copy>
       
   435 </xsl:template>
       
   436 
       
   437 
       
   438 <xsl:template match="layer" mode="adjust-layer-height">	<xsl:param name="new-layers"/>
       
   439 	<xsl:copy><xsl:copy-of select="@*[name()!='height']"/>
       
   440 		<xsl:choose>
       
   441 			<xsl:when test="$new-layers[@id=current()/@id]/@height">
       
   442 				<xsl:copy-of select="$new-layers[@id=current()/@id]/@height"/>
       
   443 			</xsl:when>
       
   444 			<xsl:otherwise>
       
   445 				<xsl:copy-of select="@height"/>
       
   446 			</xsl:otherwise>
       
   447 		</xsl:choose>
       
   448 		<xsl:copy-of select="node()"/>
       
   449 	</xsl:copy>
       
   450 </xsl:template>
       
   451 
       
   452 <xsl:template match="layer" mode="sizing">
       
   453 	<!-- 1st pass to compute the sizes of everything -->
       
   454 	<xsl:variable name="content">
       
   455 		<xsl:apply-templates mode="sizing"/>
       
   456 	</xsl:variable>	 
       
   457 
       
   458 	<!-- if there's no content, only show if forced to by placeholder-detail -->
       
   459 	<xsl:if test="/SystemDefinition[@placeholder-detail]	or exslt:node-set($content)/*[self::package]">  	
       
   460 		<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   461 			<xsl:if test="not(@span) or @span=0  or count(exslt:node-set($content)/package)!=1">
       
   462 				<xsl:attribute name="ipad"><xsl:value-of select="2* $groupDy"/></xsl:attribute>
       
   463 			</xsl:if>		
       
   464 			<xsl:attribute name="width">
       
   465 						<xsl:value-of select="sum(exslt:node-set($content)/*/@width) + $groupDx * ( count(exslt:node-set($content)/*/@width)  - 1 )"/>
       
   466 			</xsl:attribute>
       
   467 			<xsl:attribute name="height">
       
   468 				<xsl:for-each select="exslt:node-set($content)/*">
       
   469 					<xsl:sort select="@height" order="descending" data-type="number"/>
       
   470 					<xsl:if test="position()=1"><xsl:value-of select="@height"/></xsl:if>
       
   471 				</xsl:for-each>
       
   472 			</xsl:attribute>
       
   473 			<xsl:call-template name="layer-padding"/>
       
   474 			<xsl:copy-of select="$content"/>
       
   475 		</xsl:copy>
       
   476 	</xsl:if>
       
   477 </xsl:template>
       
   478 
       
   479 <xsl:template name="layer-padding">
       
   480 	<xsl:variable name="top" select="count(../meta[@rel='layer-group']/descendant::layer-group[@to=current()/@id])"/>
       
   481 	<xsl:variable name="bottom" select="count(../meta[@rel='layer-group']/descendant::layer-group[@from=current()/@id])"/>
       
   482 	<xsl:if test="$top!=0">
       
   483 		<xsl:attribute name="padding-top">
       
   484 			<xsl:value-of select="$top * $lgrpDx"/>
       
   485 		</xsl:attribute>
       
   486 	</xsl:if>
       
   487 	<xsl:if test="$bottom!=0">
       
   488 		<xsl:attribute name="padding-bottom">
       
   489 			<xsl:value-of select="$bottom * $lgrpDx"/>
       
   490 		</xsl:attribute>
       
   491 	</xsl:if>
       
   492 </xsl:template>
       
   493 
       
   494 
       
   495 <xsl:template name="spanned-levels-step">
       
   496 	<xsl:param name="pkg"/>
       
   497 	<xsl:param name="levels"/>
       
   498 	<xsl:variable name="named" select="exslt:node-set($levels)/level[@name=$pkg/@level] or not($pkg/@level)"/>
       
   499 	<!-- it's this level, or it spans all by not having any level defined, or by being in the span range for level  or it's the unnamed error level-->
       
   500 	<xsl:variable name="match" select="exslt:node-set($levels)/level[
       
   501 		@name=$pkg/@level  or 
       
   502 		not($pkg/@level)  or 
       
   503 		($pkg/@span and following-sibling::level[position() &lt; $pkg/@span][@name=$pkg/@level or (not(@name) and not($named))]) or 
       
   504 		(not($named) and not(@name))
       
   505 		]"/>
       
   506 	
       
   507 	<xsl:variable name="h" select="(sum($match/@height) + $groupDy * (count($match) - 1))"/> <!--height of all levels spanned by this -->
       
   508 	<xsl:variable name="even" select="($pkg/@height - $groupDy * (count($match) - 1) - sum($match/@min-height)) div count($match)"/>
       
   509 	
       
   510 	
       
   511 	<xsl:for-each select="exslt:node-set($levels)/level">
       
   512 		<xsl:choose>
       
   513 			<xsl:when test="$even &lt;= 0">
       
   514 				<!-- this is too small to have an impact, ignore this -->
       
   515 				<xsl:copy-of select="."/>
       
   516 			</xsl:when>
       
   517 			<xsl:when test="$match[@name=current()/@name or (not(@name) and not(current()/@name))]">
       
   518 				<xsl:choose>
       
   519 					<xsl:when test="$h &gt;= $pkg/@height">
       
   520 							<xsl:copy-of select="."/> <!-- no change -->
       
   521 					</xsl:when>
       
   522 						<xsl:otherwise>
       
   523 							<xsl:copy><xsl:copy-of select="@*[name()!='height']"/>
       
   524 								<xsl:attribute name="height">
       
   525 									<xsl:value-of select="sum(@min-height) + $even"/>
       
   526 								</xsl:attribute>
       
   527 								<xsl:copy-of select="*"/>
       
   528 							</xsl:copy>
       
   529 						</xsl:otherwise>
       
   530 				</xsl:choose>
       
   531 			</xsl:when>
       
   532 			<xsl:otherwise>
       
   533 				<xsl:copy-of select="."/>
       
   534 			</xsl:otherwise>
       
   535 		</xsl:choose>
       
   536 	</xsl:for-each>
       
   537 </xsl:template>
       
   538 
       
   539 <xsl:template name="spanned-levels">
       
   540 	<xsl:param name="pkgs"/>
       
   541 	<xsl:param name="levels"/>
       
   542 	<xsl:choose>
       
   543 		<xsl:when test="not($pkgs)">
       
   544 			<xsl:copy-of select="$levels"/>
       
   545 		</xsl:when>
       
   546 		<xsl:when test="count($pkgs) =1">
       
   547 			<xsl:call-template name="spanned-levels-step">
       
   548 				<xsl:with-param name="pkg" select="$pkgs[1]"/>
       
   549 				<xsl:with-param name="levels" select="$levels"/>
       
   550 			</xsl:call-template>
       
   551 		</xsl:when>
       
   552 		<xsl:otherwise>
       
   553 			<xsl:call-template name="spanned-levels">
       
   554 				<xsl:with-param name="pkgs" select="$pkgs[position() &gt; 1]"/>
       
   555 				<xsl:with-param name="levels">
       
   556 					<xsl:call-template name="spanned-levels-step">
       
   557 						<xsl:with-param name="pkg" select="$pkgs[1]"/>
       
   558 						<xsl:with-param name="levels" select="$levels"/>
       
   559 					</xsl:call-template>
       
   560 				</xsl:with-param>
       
   561 			</xsl:call-template>
       
   562 		</xsl:otherwise>
       
   563 	</xsl:choose>
       
   564 </xsl:template>
       
   565 
       
   566 
       
   567 <xsl:template match="layer[@levels]" mode="sizing">
       
   568 	<!-- layer has levels and packages, at least some with a level set, so determine height and width of each level -->
       
   569 
       
   570 	<xsl:variable name="content">
       
   571 		<xsl:apply-templates mode="sizing"/>
       
   572 	</xsl:variable>	 
       
   573 	 
       
   574 	<!-- if there's no content, only show if forced to by placeholder-detail -->
       
   575 	<xsl:if test="/SystemDefinition[@placeholder-detail]	or exslt:node-set($content)/*[self::package]">  	
       
   576 
       
   577 		<!-- the levels without taking into account spanned pkgs -->
       
   578 		<xsl:variable name="levels0">
       
   579 			<xsl:call-template name="levels-size">
       
   580 				<xsl:with-param name="levels">
       
   581 					<xsl:apply-templates select="." mode="levels"/>
       
   582 				</xsl:with-param>		
       
   583 				<xsl:with-param name="items" select="exslt:node-set($content)/package"/>
       
   584 			</xsl:call-template>
       
   585 		</xsl:variable>
       
   586 	<!-- figure out which spanned pkgs actually have an impact. This excludes:
       
   587 		* pkgs which span the same levels, but are smaller than another pkg
       
   588 		* pkgs which have collections that use the layer's levels (already taken into account)
       
   589 	-->
       
   590 		
       
   591 
       
   592 	<xsl:variable name="b"> <!--all spanning pkgs with set of levels they cover -->
       
   593 		<xsl:for-each select="exslt:node-set($content)/package[((@span and @span!=1) or not(@level)) and not(not(@levels) and meta[@rel='model-levels']/level[@name])]">
       
   594 			<!-- all pkgs which span and have levels -->
       
   595 			<xsl:variable name="named" select="exslt:node-set($levels0)/level[@name=current()/@level] or not(@level)"/>
       
   596 			<xsl:variable name="pkg" select="."/>
       
   597 			<!-- it's this level, or it spans all by not having any level defined, or by being in the span range for level  or it's the unnamed error level-->
       
   598 			<xsl:variable name="match" select="exslt:node-set($levels0)/level[@name=$pkg/@level  or not($pkg/@level)  or ($pkg/@span and following-sibling::level[position() &lt; $pkg/@span][@name=$pkg/@level or (not(@name) and not($named))]) or (not($named) and not(@name))]"/>
       
   599 			<b id="{@id}">
       
   600 				<xsl:attribute name="levs"> 
       
   601 					<!-- just a space separated list of level indexs : don't use names, since one name can be blank -->
       
   602 					<xsl:for-each select="$match">
       
   603 						<xsl:value-of select="count(preceding-sibling::level)+1"/>
       
   604 						<xsl:if test="position()!=last()"><xsl:text> </xsl:text></xsl:if>
       
   605 					</xsl:for-each>
       
   606 				</xsl:attribute>
       
   607 			</b>
       
   608 		</xsl:for-each>
       
   609 	</xsl:variable>
       
   610 	<xsl:variable name="impacting"> <!-- just the list of remaining pkgs which have an impact on the levels -->
       
   611 		<xsl:for-each select="exslt:node-set($b)/b">
       
   612 			<xsl:variable name="pkg" select="exslt:node-set($content)/package[@id=current()/@id]"/> <!-- the actual pkg -->
       
   613 			<xsl:variable name="ignore"> <!-- non-empty if this should be ingnored -->
       
   614 				<xsl:for-each select="following-sibling::b[@levs=current()/@levs]"> <!-- compare against pkgs with same set of levels-->
       
   615 					<!-- ignore if a later pkg is taller or the same size-->
       
   616 					<xsl:if test="exslt:node-set($content)/package[@id=current()/@id]/@height &gt;= $pkg/@height">*</xsl:if>
       
   617 				</xsl:for-each>
       
   618 			</xsl:variable>
       
   619 			<xsl:if test="$ignore=''"><xsl:copy-of select="."/></xsl:if> <!--only keep the un-ignored -->
       
   620 		</xsl:for-each>
       
   621 	</xsl:variable>
       
   622 	
       
   623 	<!-- adjust the list of levels to take into account the impacting packages which span levels -->
       
   624 	<xsl:variable name="levels">
       
   625 		<xsl:call-template name="spanned-levels">
       
   626 			<xsl:with-param name="pkgs" select="exslt:node-set($content)/package[@id=exslt:node-set($impacting)/b/@id]"/>
       
   627 			<xsl:with-param name="levels" select="$levels0"/>
       
   628 		</xsl:call-template>
       
   629 	</xsl:variable>
       
   630 
       
   631 		 <xsl:variable name="ext-w"  select="count(ancestor::SystemDefinition[@levels='expand'])*$levelExpandName"/>
       
   632 	 
       
   633 		<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   634 			<xsl:if test="not(@span) or @span=0  or count(exslt:node-set($content)/package)!=1">
       
   635 				<xsl:attribute name="ipad"><xsl:value-of select="2 *$groupDy"/></xsl:attribute>
       
   636 			</xsl:if>
       
   637 			<xsl:attribute name="width">
       
   638 				<xsl:for-each select="exslt:node-set($levels)/level">
       
   639 					<xsl:sort select="@width" order="descending" data-type="number"/>
       
   640 					<xsl:if test="position()=1"><xsl:value-of select="@width + $ext-w"/></xsl:if>
       
   641 				</xsl:for-each>
       
   642 			</xsl:attribute>
       
   643 
       
   644 			<xsl:attribute name="height">
       
   645 					<!-- +1 for padding on top and bottom  -->
       
   646 				<xsl:value-of select="sum(exslt:node-set($levels)/level/@height) + $groupDy * (count(exslt:node-set($levels)/level/@height) + 1)"/>
       
   647 			</xsl:attribute>
       
   648 			<xsl:call-template name="layer-padding"/>
       
   649 			<meta rel="model-levels">
       
   650 				<xsl:copy-of select="$levels"/>
       
   651 			</meta>
       
   652 			<xsl:copy-of select="$content"/>
       
   653 		</xsl:copy>
       
   654 	</xsl:if>
       
   655 </xsl:template>
       
   656 
       
   657 
       
   658 <xsl:template match="layer[ancestor::SystemDefinition[@detail-type='fixed' and @detail='layer']]" mode="sizing" priority="2">
       
   659 	<!-- no displayed content and fixed with, so don't even look at the pkgs -->
       
   660 	<xsl:variable name="content">
       
   661 		<xsl:apply-templates mode="sizing"/>
       
   662 	</xsl:variable>
       
   663 	<xsl:variable name="levels">
       
   664 		<xsl:apply-templates select="." mode="levels"/>
       
   665 	</xsl:variable>
       
   666 	<xsl:if test="/SystemDefinition[@placeholder-detail]	or exslt:node-set($content)/*[self::package]">  	
       
   667 		<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   668 			<xsl:attribute name="width">
       
   669 				<xsl:value-of select="$lyrFixedWidth + count(ancestor::SystemDefinition[@levels='expand'])*$levelExpandName"/>
       
   670 			</xsl:attribute>
       
   671 			<xsl:attribute name="height">
       
   672 				<xsl:value-of select="count(exslt:node-set($levels)/level) * $mHeight * 1.5 "/>
       
   673 			</xsl:attribute>
       
   674 			<xsl:call-template name="layer-padding"/>		
       
   675 			<meta rel="model-levels">
       
   676 				<xsl:copy-of select="$levels"/>
       
   677 			</meta>	
       
   678 			<xsl:copy-of select="$content"/>
       
   679 		</xsl:copy>
       
   680 	</xsl:if>
       
   681 </xsl:template>
       
   682 
       
   683 
       
   684 <xsl:template match="layer[not(package/@level)]" mode="sizing" priority="1">
       
   685 	<!-- any levels apply to the collections, the pkgs all span full height of the layer => in a row on the same line
       
   686 		height = max height of all pkgs + padding
       
   687 		width = sum of all pkg widths, plus any internal padding -->
       
   688 	<xsl:variable name="content">
       
   689 		<xsl:apply-templates mode="sizing"/>
       
   690 	</xsl:variable>
       
   691 	
       
   692 	<!-- if there's no content, only show if forced to by placeholder-detail -->
       
   693 	<xsl:if test="/SystemDefinition[@placeholder-detail]	or exslt:node-set($content)/*[self::package]">  	
       
   694 		<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   695 		<xsl:if test="not(@span) or @span=0  or count(exslt:node-set($content)/package)!=1">
       
   696 			<xsl:attribute name="ipad"><xsl:value-of select="2 * $groupDy"/></xsl:attribute>
       
   697 		</xsl:if>
       
   698 			<xsl:variable name="h">
       
   699 				<xsl:for-each select="exslt:node-set($content)/*">
       
   700 					<xsl:sort select="@height" order="descending" data-type="number"/>
       
   701 					<xsl:if test="position()=1"><xsl:value-of select="@height"/></xsl:if>
       
   702 				</xsl:for-each>			
       
   703 			</xsl:variable>
       
   704 			<xsl:attribute name="width">
       
   705 				<!-- sum of all widths + padding -->
       
   706 				<xsl:value-of select="sum(exslt:node-set($content)/*/@width) +  $groupDx * (count(exslt:node-set($content)/*) - 1) + count(ancestor::SystemDefinition[@levels='expand'])*$levelExpandName"/>
       
   707 			</xsl:attribute>
       
   708 			<xsl:attribute name="height">
       
   709 				<xsl:choose>
       
   710 					<xsl:when test="count(package)=1 and @span and @span!=0">
       
   711 						<!-- same height as contents, no room for layer name -->
       
   712 						<xsl:value-of select="$h"/>
       
   713 					</xsl:when>
       
   714 					<xsl:when test="@span and @span!=0">
       
   715 						<!-- padding on top, room for name on bottom -->
       
   716 						<xsl:value-of select="$h  +  $groupDy + $pkgLabelSize"/>
       
   717 					</xsl:when>
       
   718 					<xsl:otherwise> <!-- padding on top and bottom, name outside -->
       
   719 						<xsl:value-of select="$h + 2 * $groupDy"/>
       
   720 					</xsl:otherwise>
       
   721 				</xsl:choose>
       
   722 			</xsl:attribute>
       
   723 			<xsl:call-template name="layer-padding"/>
       
   724 			<xsl:copy-of select="$content"/>
       
   725 		</xsl:copy>
       
   726 	</xsl:if>
       
   727 </xsl:template>
       
   728 
       
   729 
       
   730 <xsl:template match="collection" mode="effective-width"><xsl:param name="levels"/>  
       
   731 	<!-- called on the last in a set of collections -->
       
   732 	<xsl:variable name="id" select="preceding-sibling::package[1]/@id"/>
       
   733 	<xsl:variable name="lev">
       
   734 		<xsl:call-template name="levels-widths">
       
   735 			<xsl:with-param name="levels" select="$levels"/>
       
   736 			<xsl:with-param name="items" select=". | preceding-sibling::collection[preceding-sibling::package/@id=$id]"/>
       
   737 		</xsl:call-template>
       
   738 	</xsl:variable>
       
   739 	<xsl:for-each select="exslt:node-set($lev)/level">
       
   740 		<xsl:sort select="@width" order="descending" data-type="number"/>
       
   741 		<xsl:if test="position()=1"><xsl:value-of select="concat(@width + $groupDx,' ')"/></xsl:if>
       
   742 	</xsl:for-each>
       
   743 </xsl:template>
       
   744 
       
   745 
       
   746 <xsl:template match="collection[not(preceding-sibling::package)]" mode="effective-width">
       
   747 	<xsl:param name="levels"/>  <!-- there is nothing but collections before this -->
       
   748 	<xsl:variable name="lev">
       
   749 		<xsl:call-template name="levels-widths">
       
   750 			<xsl:with-param name="levels" select="$levels"/>
       
   751 			<xsl:with-param name="items" select="preceding-sibling::collection | ."/>
       
   752 		</xsl:call-template>
       
   753 	</xsl:variable>	
       
   754 	<xsl:for-each select="exslt:node-set($lev)/level">
       
   755 		<xsl:sort select="@width" order="descending" data-type="number"/>
       
   756 		<xsl:if test="position()=1"><xsl:value-of select="concat(@width + $groupDx, ' ')"/></xsl:if>
       
   757 	</xsl:for-each>
       
   758 </xsl:template>
       
   759 
       
   760 
       
   761 <xsl:template match="package" mode="sizing">
       
   762 	<!-- height is explicitly set by levels -->
       
   763 
       
   764 	<xsl:variable name="content">
       
   765 		<xsl:apply-templates mode="sizing"/>
       
   766 	</xsl:variable>
       
   767 	<!-- if there's no content, only show if forced to by placeholder-detail -->
       
   768 	<xsl:if test="/SystemDefinition[@placeholder-detail='package' or @placeholder-detail='component' or @placeholder-detail='collection'] 
       
   769 		or exslt:node-set($content)/*[self::package or self::collection]">  	
       
   770 		<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   771 			<xsl:variable name="levels0">
       
   772 				<xsl:apply-templates select="." mode="levels"/>
       
   773 			</xsl:variable>
       
   774 			<xsl:variable name="levels">
       
   775 				<xsl:call-template name="levels-widths">
       
   776 					<xsl:with-param name="levels" select="$levels0"/>
       
   777 					<xsl:with-param name="items" select="exslt:node-set($content)/collection"/>
       
   778 				</xsl:call-template>
       
   779 			</xsl:variable>
       
   780 
       
   781 			<xsl:variable name="max-width">
       
   782 				<xsl:for-each select="exslt:node-set($levels)/level">
       
   783 					<xsl:sort select="@width" order="descending" data-type="number"/>
       
   784 					<xsl:if test="position()=1"><xsl:value-of select="@width"/></xsl:if>
       
   785 				</xsl:for-each>
       
   786 			</xsl:variable>					
       
   787 			<xsl:variable name="min-width">
       
   788 				<xsl:for-each select="exslt:node-set($levels)/level">
       
   789 					<xsl:sort select="@width" order="ascending" data-type="number"/>
       
   790 					<xsl:if test="position()=1"><xsl:value-of select="@width"/></xsl:if>
       
   791 				</xsl:for-each>
       
   792 			</xsl:variable>
       
   793 			<xsl:variable name="h0" select="count(exslt:node-set($levels)/level) * ($mHeight +  $groupDy) - $groupDy"/> <!-- height of just levels, no padding -->
       
   794 			
       
   795 			<xsl:variable name="padding" select="number(
       
   796 					not(parent::package or  
       
   797 							count(exslt:node-set($levels)/level) &lt; 2 or
       
   798 								(not(@level) and descendant::collection/@level and ../package/@level) )
       
   799 					) * 2 * $groupDy
       
   800 				"/>
       
   801 
       
   802 			<xsl:if test="$padding != 0 ">
       
   803 				<xsl:attribute name="ipad"><xsl:value-of select="$padding"/></xsl:attribute>
       
   804 			</xsl:if> <!--
       
   805 				Perhaps needs this rule for padding too:
       
   806 					this has no level, but children have levels and siblings have levels, ie
       
   807 					not(@level) and descendant::collection/@level and ../package/@levels				
       
   808 				-->
       
   809 			
       
   810 			<xsl:variable name="h">
       
   811 				<xsl:choose>
       
   812 					<xsl:when test="exslt:node-set($content)/package and /SystemDefinition/@detail='package'">
       
   813 						<xsl:value-of select="$h0 + $pkgLabelSize + $padding + $detail-block-space"/>  <!-- padding plus extra room for larger itle  -->
       
   814 					</xsl:when>
       
   815 					<xsl:when test="exslt:node-set($content)/package">
       
   816 						<xsl:value-of select="$h0 + $pkgLabelSize + $padding"/>  <!-- padding plus room for title  -->
       
   817 					</xsl:when>
       
   818 					<xsl:when test="/SystemDefinition/@detail='package' and parent::layer">
       
   819 						<xsl:value-of select="$h0 + $padding"/>  <!-- needs padding   -->
       
   820 					</xsl:when>
       
   821 					<xsl:when test="/SystemDefinition/@detail='package'">
       
   822 						<xsl:value-of select="$h0"/>  <!-- plenty of room for title  (nested pkg) -->
       
   823 					</xsl:when>
       
   824 					<xsl:when test="parent::SystemDefinition and not( exslt:node-set($levels)/level[1]/@width=0)">
       
   825 						<xsl:value-of select="$h0 + $padding  + $pkgLabelSize "/>  <!-- padding plus room for title -->
       
   826 					</xsl:when>
       
   827 					<xsl:when test="parent::layer and ($max-width - $min-width &gt; $inlineLabel)">
       
   828 						<xsl:value-of select="$h0 + $padding"/>  <!-- padding plus room for title -->
       
   829 					</xsl:when>
       
   830 					<!-- non-nested pkgs here on out don't have room for inline label-->
       
   831 					<xsl:when test="parent::layer and count(exslt:node-set($levels)/level) &gt; 1">
       
   832 						<xsl:value-of select="$h0 + $padding + $pkgLabelSize"/>  <!-- padding plus room for title -->
       
   833 								<!--xsl:value-of select="$h0 + 2 * $groupDy"/>  <!-  title should go inline -->
       
   834 					</xsl:when>
       
   835 					<xsl:when test="$max-width - $min-width &lt; $inlineLabel">
       
   836 						<xsl:value-of select="$h0 + $padding"/> <!-- nested pkg too small to fit label: use normal height, but make wider (below) -->
       
   837 					</xsl:when>
       
   838 					<xsl:otherwise>
       
   839 						<xsl:value-of select="$h0 + $padding"/>  <!--  title should go inline (nested pkg) -->
       
   840 					</xsl:otherwise>
       
   841 				</xsl:choose>
       
   842 			</xsl:variable>		
       
   843 		<xsl:variable name="expand-width">
       
   844 			<!-- Set expand-width to indicate when the pkg should be expanded to add room for a title iff it's stays at the native height --> 
       
   845 			<xsl:choose>
       
   846 				<xsl:when test="not(exslt:node-set($content)/package or exslt:node-set($content)/collection)">0</xsl:when> <!-- no content, don't expand -->
       
   847 				<xsl:when test="exslt:node-set($content)/package">0</xsl:when> <!--  never expand with nested pkgs  -->
       
   848 				<xsl:when test="/SystemDefinition[@detail-type='fixed' and @detail='package']">0</xsl:when>				<!-- fixed detail.  -->
       
   849 				<xsl:when test="parent::package and ($min-width + $inlineLabel  &lt; $subpkgMinWidth)">
       
   850 						<xsl:value-of select="$subpkgMinWidth - $max-width"/> <!-- small nested pkg -->
       
   851 				</xsl:when> 
       
   852 				<xsl:when test="parent::package and ($max-width - $min-width &lt; $inlineLabel)"> 
       
   853 					<!-- nested pkg  w/o room for label. Expand to fit label -->
       
   854 						<xsl:value-of select="$min-width + $inlineLabel - $max-width"/>
       
   855 				</xsl:when>
       
   856 				<xsl:when test="parent::package and ($max-width  &lt; $subpkgMinWidth)">
       
   857 						<xsl:value-of select="$subpkgMinWidth - $max-width"/>
       
   858 				</xsl:when> 	<!-- small nested pkg,  -->
       
   859 				<xsl:when test="not(parent::package) and count(exslt:node-set($levels)/level) = 1 and ../package[@level=current()/@level and not(@span) and contains(normalize-space(@levels),' ')]">
       
   860 					<!-- this has one level, but at least one sibling at the same level has more than one, so the height will be expanded. No need to add space for title -->
       
   861 					<xsl:choose>
       
   862 						<xsl:when test="$max-width  &lt; $pkgMinWidth"> 	 <!-- small package -->
       
   863 							<xsl:value-of select="$pkgMinWidth - $max-width"/>
       
   864 						</xsl:when>
       
   865 						<xsl:otherwise><xsl:value-of select="0"/></xsl:otherwise>	
       
   866 					</xsl:choose>
       
   867 				</xsl:when>				
       
   868 				<xsl:when test="$max-width  &lt; $pkgMinWidth and  $inlineLabel + $min-width &gt; $pkgMinWidth and $h &lt; $mHeight*1.5"> 
       
   869 				<!-- small pkg, without enough room for a title. Make wide enough to fit the title -->
       
   870 						<xsl:value-of select="$min-width + $inlineLabel - $max-width"/>
       
   871 				</xsl:when>
       
   872 				<xsl:when test="$max-width  &lt; $pkgMinWidth">0</xsl:when>
       
   873 				<xsl:when test="parent::package and  ($max-width - $min-width &lt; $inlineLabel)"> 
       
   874 					<!-- need to make wider to have room for a title -->
       
   875 						<xsl:value-of select="$min-width + $inlineLabel - $max-width"/>
       
   876 				</xsl:when>
       
   877 				<xsl:when test="$h &lt; $mHeight + $pkgLabelSize">
       
   878 					<!-- if not nested and only 1 level tall,  make wider instead of taller-->
       
   879 					<!-- need to make wider to have room for a title -->
       
   880 						<xsl:value-of select="$inlineLabel"/>
       
   881 				</xsl:when>
       
   882 				<xsl:when test="parent::layer and not(@level) and ../@levels and ($max-width - $min-width &lt; $inlineLabel)"> 
       
   883 					<!-- need to make wider to have room for a title -->
       
   884 						<xsl:value-of select="$min-width + $inlineLabel - $max-width"/>
       
   885 				</xsl:when>
       
   886 				<xsl:otherwise>0</xsl:otherwise>
       
   887 			</xsl:choose>
       
   888 		</xsl:variable>
       
   889 		
       
   890 		
       
   891 		
       
   892 			<xsl:variable name="w">
       
   893 				<xsl:choose>
       
   894 					<xsl:when test="not(exslt:node-set($content)/package or exslt:node-set($content)/collection) and parent::package">
       
   895 						<!-- no content, shown as placeholder. Use nested package-detail width --> 
       
   896 						<xsl:value-of select="$subpkgFixedWidth"/>
       
   897 					</xsl:when>
       
   898 					<xsl:when test="not(exslt:node-set($content)/package or exslt:node-set($content)/collection)">
       
   899 						<!-- no content, shown as placeholder. Use package-detail width --> 
       
   900 						<xsl:value-of select="$pkgFixedWidth"/>
       
   901 					</xsl:when>
       
   902 					<xsl:when test="exslt:node-set($content)/package and exslt:node-set($content)/collection">
       
   903 						<!-- sum of all packages, plus space between them + sum of each set of collections in a row w/padding around those-->
       
   904 						<xsl:call-template name="sum-list">
       
   905 							<xsl:with-param name="list">
       
   906 								<xsl:value-of select="concat(sum(exslt:node-set($content)/package/@width) + $groupDx * (count(exslt:node-set($content)/package) - 1),' ')"/>
       
   907 								<xsl:apply-templates mode="effective-width" select="exslt:node-set($content)/collection[not(following-sibling::*[self::collection or self::package]) or name(following-sibling::*[self::collection or self::package])='package']">
       
   908 									<xsl:with-param name="levels" select="$levels0"/>
       
   909 								</xsl:apply-templates>
       
   910 							</xsl:with-param>
       
   911 						</xsl:call-template>
       
   912 					</xsl:when>
       
   913 					<xsl:when test="/SystemDefinition[@detail-type='fixed' and @detail='package'] and exslt:node-set($content)/package">
       
   914 						<!-- pkg detail, so don't take collections into account. Just show at width of nested pkgs + padding -->
       
   915 						<xsl:value-of select="sum(exslt:node-set($content)/package/@width) + $groupDx * (count(exslt:node-set($content)/package) - 1)"/>
       
   916 					</xsl:when>
       
   917 					<xsl:when test="/SystemDefinition[@detail-type='fixed' and @detail='package'] and (parent::layer or parent::systemModel)">
       
   918 						<!-- fixed detail. Use package-detail width --> 
       
   919 						<xsl:value-of select="$pkgFixedWidth"/>
       
   920 					</xsl:when>
       
   921 					<xsl:when test="/SystemDefinition[@detail-type='fixed' and @detail='package']">
       
   922 						<!-- fixed detail. Use nested package-detail width --> 
       
   923 						<xsl:value-of select="$subpkgFixedWidth"/>
       
   924 					</xsl:when>
       
   925 					<xsl:when test="parent::package">
       
   926 						<!-- small nested pkg, use min width of twice smallest possible collection -->
       
   927 						<xsl:value-of select="$max-width"/>
       
   928 					</xsl:when>
       
   929 					<xsl:when test="exslt:node-set($content)/package and exslt:node-set($content)/collection and not(exslt:node-set($content)/collection[name(following-sibling::*[1])='collection'])">
       
   930 						<!-- easy case, all in a line, no two collections next to each other -->
       
   931 							<xsl:value-of select="sum(exslt:node-set($content)/*[self::package or self::collection]/@width) + $groupDx * (count(exslt:node-set($content)/*[self::package or self::collection]) - 1)"/>
       
   932 					</xsl:when>
       
   933 					<xsl:when test="exslt:node-set($content)/package">
       
   934 						<!-- sum of all contained packages only-->
       
   935 							<xsl:value-of select="sum(exslt:node-set($content)/package/@width) + $groupDx * (count(exslt:node-set($content)/package) - 1)"/>
       
   936 					</xsl:when>
       
   937 					<xsl:otherwise>
       
   938 						<!-- use width of widest level -->
       
   939 						<xsl:value-of select="$max-width"/>
       
   940 					</xsl:otherwise>
       
   941 				</xsl:choose>
       
   942 			</xsl:variable>
       
   943 				<!-- this has to be done in a variable since xalan won't let the node-sets be generated inside an attribute -->
       
   944 				
       
   945 		<xsl:variable name="ext-w" select="count(ancestor::SystemDefinition[@levels='expand'])*$levelExpandName"/>
       
   946 			<xsl:attribute name="width">
       
   947 				<xsl:choose>
       
   948 					<xsl:when test="parent::package and $w + $expand-width &lt; $subpkgMinWidth">	<!-- small nested pkg, use width of  3 components -->
       
   949 						<xsl:value-of select="$subpkgMinWidth + $ext-w + pkgAuxWidth"/>
       
   950 					</xsl:when>
       
   951 					<xsl:when test="$w + $expand-width  &lt; $pkgMinWidth">	<!-- small pkg, use width of twice smallest possible collection -->
       
   952 						<xsl:value-of select="$pkgMinWidth + $ext-w + $pkgAuxWidth "/>
       
   953 					</xsl:when>
       
   954 					<xsl:otherwise><xsl:value-of select="$w + $expand-width + $ext-w + $pkgAuxWidth"/></xsl:otherwise>
       
   955 				</xsl:choose>
       
   956 			</xsl:attribute>
       
   957 			<xsl:attribute name="height"><xsl:value-of select="$h"/></xsl:attribute>
       
   958 			
       
   959 	
       
   960 			<meta rel="model-levels"><xsl:copy-of select="$levels"/></meta>
       
   961 		
       
   962 			<xsl:copy-of select="$content"/>
       
   963 		</xsl:copy>
       
   964 	</xsl:if>
       
   965 </xsl:template>
       
   966 
       
   967 <xsl:template match="collection" mode="sizing">
       
   968 	<xsl:variable name="content">
       
   969 		<xsl:apply-templates select="node()" mode="sizing"/>
       
   970 	</xsl:variable>
       
   971 	<!-- if there's no content, only show if forced to by placeholder-detail -->
       
   972 	<xsl:if test="/SystemDefinition[@placeholder-detail='component' or @placeholder-detail='collection'] 
       
   973 		or exslt:node-set($content)/component">  
       
   974 		<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   975 			<xsl:variable name="w" select="sum(exslt:node-set($content)/component/@width)"/>
       
   976 			<xsl:attribute name="width">	
       
   977 				<xsl:choose>
       
   978 					<!-- a collection might be a sibling to a pkg, so it will take up some space at pkag level of detail -->
       
   979 					<xsl:when test="$w &lt; $mMinWidth or /SystemDefinition[(@detail='collection' or @detail='package') and @detail-type='fixed']">
       
   980 						<xsl:value-of select="$mMinWidth"/>
       
   981 					</xsl:when>	
       
   982 					<xsl:otherwise><xsl:value-of select="$w"/></xsl:otherwise>
       
   983 				</xsl:choose>
       
   984 			</xsl:attribute>		
       
   985 			<xsl:attribute name="height"><xsl:value-of select="$mHeight"/></xsl:attribute>		
       
   986 			<xsl:copy-of select="$content"/>
       
   987 		</xsl:copy>
       
   988 	</xsl:if>
       
   989 </xsl:template>
       
   990 
       
   991 <xsl:template match="component" mode="sizing">
       
   992 	<xsl:copy><xsl:apply-templates mode="copy-attr" select="@*"/>
       
   993 		<xsl:attribute name="width"><xsl:value-of select="$cSize"/></xsl:attribute>
       
   994 		<xsl:attribute name="height"><xsl:value-of select="$cSize"/></xsl:attribute>
       
   995 		<xsl:apply-templates select="node()" mode="sizing"/>
       
   996 	</xsl:copy>
       
   997 </xsl:template>
       
   998 
       
   999 <xsl:template match="package/package/package" priority="9" mode="sizing"> <!-- ignore 3+ level depth packages -->
       
  1000 	<xsl:apply-templates mode="sizing"/>
       
  1001 </xsl:template>
       
  1002 
       
  1003 <!-- stuff for dealing with levels -->
       
  1004 
       
  1005 <xsl:template match="*" mode="levels" priority="-8"><level/>
       
  1006 	<!-- Should not be able to get here. Panic -->
       
  1007 <xsl:message terminate="yes">
       
  1008 <xsl:value-of select="concat(name(), ' ',@id,': ',@levels)"/> (<xsl:value-of select="*/@level | */*/@level"/>)
       
  1009 </xsl:message>
       
  1010 </xsl:template>
       
  1011 
       
  1012 
       
  1013 <xsl:template match="package[not(@levels)] |layer[not(@levels)]" mode="levels" priority="-1">
       
  1014 	<!-- no levels, so everything must be on same nameless level (barring exceptions below) -->
       
  1015 	<level/>
       
  1016 </xsl:template>
       
  1017 
       
  1018 
       
  1019 <xsl:template match="layer[@levels]/package/package" mode="levels" priority="1">
       
  1020 <!-- a nested package with levels defined in the layer  -->
       
  1021 	<xsl:call-template name="levels-list">
       
  1022 		<xsl:with-param name="levels" select="normalize-space(../../@levels)"/>
       
  1023 	</xsl:call-template>
       
  1024 	<xsl:if test="descendant::collection[not(contains(concat(' ',normalize-space(current()/../../@levels),' '),@level)) or not(@level)]">
       
  1025 		<!--<xsl:call-template name="Caller-Warning">
       
  1026 			<xsl:with-param name="text">collection without valid level in package <xsl:value-of select="@id"/></xsl:with-param>
       
  1027 		</xsl:call-template>-->	
       
  1028 		<level/>
       
  1029 	</xsl:if>
       
  1030 </xsl:template>
       
  1031 
       
  1032 
       
  1033 <xsl:template match="layer/package/package[@levels]" mode="levels" priority="1">
       
  1034 <!-- a nested package with levels defined in the layer  -->
       
  1035 	<xsl:call-template name="levels-list">
       
  1036 		<xsl:with-param name="levels" select="normalize-space(@levels)"/>
       
  1037 	</xsl:call-template>
       
  1038 	<xsl:if test="descendant::collection[not(contains(concat(' ',normalize-space(current()/@levels),' '),@level)) or not(@level)]">
       
  1039 		<!--<xsl:call-template name="Caller-Warning">
       
  1040 			<xsl:with-param name="text">collection without valid level in package <xsl:value-of select="@id"/></xsl:with-param>
       
  1041 		</xsl:call-template>-->	
       
  1042 		<level/>
       
  1043 	</xsl:if>
       
  1044 </xsl:template>
       
  1045 
       
  1046 <xsl:template match="layer/package[@levels]/package" mode="levels" priority="1">
       
  1047 	<!-- a package with levels and a nested pkg  -->
       
  1048 	<xsl:call-template name="levels-list">
       
  1049 		<xsl:with-param name="levels" select="normalize-space(../@levels)"/>
       
  1050 	</xsl:call-template>
       
  1051 	<xsl:if test="descendant::collection[not(contains(concat(' ',normalize-space(current()/../@levels),' '),@level)) or not(@level)]">
       
  1052 		<!--<xsl:call-template name="Caller-Warning">
       
  1053 			<xsl:with-param name="text">collection without valid level in package <xsl:value-of select="@id"/></xsl:with-param>
       
  1054 		</xsl:call-template>-->	
       
  1055 		<level/>
       
  1056 	</xsl:if>
       
  1057 </xsl:template>
       
  1058 
       
  1059 <xsl:template match="layer[@levels]/package[not(@levels|@level)]" mode="levels">
       
  1060 	<!-- pkg with levels defined in the layer, and spans whole set of layer levels-->
       
  1061 	<xsl:call-template name="levels-list">
       
  1062 		<xsl:with-param name="levels" select="normalize-space(../@levels)"/>
       
  1063 	</xsl:call-template>
       
  1064 	<xsl:if test="descendant::collection[not(contains(concat(' ',normalize-space(current()/../@levels),' '),@level)) or not(@level)]">
       
  1065 		<!--<xsl:call-template name="Caller-Warning">
       
  1066 			<xsl:with-param name="text">collection without valid level in package <xsl:value-of select="@id"/></xsl:with-param>
       
  1067 		</xsl:call-template>-->	
       
  1068 		<level/>
       
  1069 	</xsl:if>
       
  1070 </xsl:template>
       
  1071 
       
  1072 <xsl:template match="layer[@levels]/package[not(@levels) and @level]" mode="levels">
       
  1073 	<!-- pkg with levels defined in the layer, but at a range of levels -->
       
  1074 	<xsl:variable name="span" select="sum(@span) + 1 - count(@span)"/> <!-- easier than having a <choose> -->
       
  1075 	<xsl:variable name="list">
       
  1076 		<xsl:call-template name="levels-list">
       
  1077 			<xsl:with-param name="levels" select="normalize-space(../@levels)"/>
       
  1078 		</xsl:call-template>
       
  1079 	</xsl:variable>
       
  1080 	<xsl:variable name="match" select="exslt:node-set($list)/level[@name=current()/@level]"/> <!-- the ending level of the span -->
       
  1081 	
       
  1082 	<xsl:choose>
       
  1083 		<xsl:when test="not($match)">
       
  1084 			<!--<xsl:call-template name="Caller-Warning">
       
  1085 				<xsl:with-param name="text">collection without valid level in package <xsl:value-of select="@id"/></xsl:with-param>
       
  1086 			</xsl:call-template>-->	
       
  1087 			<xsl:copy-of select="exslt:node-set($list)/level[position() &gt; last() - $span + 1]"/> <!-- want last $span-1 levels from this list -->
       
  1088 			<level/> <!-- extra unnamed level -->
       
  1089 		</xsl:when>
       
  1090 		<xsl:otherwise>
       
  1091 			<xsl:copy-of select="$match | $match/preceding-sibling::level[position() &lt; $span]"/> <!-- previous $span - 1 siblings -->
       
  1092 		</xsl:otherwise>	
       
  1093 	</xsl:choose>
       
  1094 </xsl:template>
       
  1095 
       
  1096 <xsl:template match="package[not(@levels) and not(descendant::collection/@level)]" mode="levels" priority="1">
       
  1097 	<!-- no levels on the package, and none used by any collections => just one level in pkg -->
       
  1098 	<level/>
       
  1099 </xsl:template>
       
  1100 
       
  1101 <xsl:template match="layer/package[@levels]|SystemDefinition/package[@levels]" mode="levels">
       
  1102 	<!-- a package with levels  -->
       
  1103 	<xsl:call-template name="levels-list"/>
       
  1104 	<xsl:if test="descendant::collection[not(contains(concat(' ',normalize-space(current()/@levels),' '),@level)) or not(@level)]">
       
  1105 		<!--<xsl:call-template name="Caller-Warning">
       
  1106 			<xsl:with-param name="text">collection without valid level in package <xsl:value-of select="@id"/></xsl:with-param>
       
  1107 		</xsl:call-template>-->	
       
  1108 		<level/>
       
  1109 	</xsl:if>
       
  1110 </xsl:template>
       
  1111 
       
  1112 <xsl:template match="layer[@levels]" mode="levels">
       
  1113 	<xsl:call-template name="levels-list"/>
       
  1114 	<xsl:if test="package[not(contains(concat(' ',normalize-space(current()/@levels),' '),@level)) and @level]">
       
  1115 		<!--<xsl:call-template name="Caller-Warning">
       
  1116 			<xsl:with-param name="text">package without valid level in layer <xsl:value-of select="@id"/></xsl:with-param>
       
  1117 		</xsl:call-template>-->	
       
  1118 		<level/>
       
  1119 	</xsl:if>
       
  1120 </xsl:template>
       
  1121 
       
  1122 <xsl:template match="layer[not(@levels) and package/@level]" mode="levels">
       
  1123 	<xsl:call-template name="Caller-Warning">
       
  1124 		<xsl:with-param name="text">layer <xsl:value-of select="@id"/> has no levels, but contains package <xsl:value-of select="package[@level]/@id"/> with defined level</xsl:with-param>
       
  1125 	</xsl:call-template>
       
  1126 	<!-- this is an error case, well... more of a warning case. Easy to handle with one fake level -->
       
  1127 	<level/>
       
  1128 </xsl:template>
       
  1129 
       
  1130 <xsl:template name="levels-list"><xsl:param name="levels" select="normalize-space(@levels)"/>
       
  1131 	<xsl:choose>
       
  1132 		<xsl:when test="contains($levels,' ')">
       
  1133 			<level name="{substring-before($levels,' ')}"/>
       
  1134 			<xsl:call-template name="levels-list">
       
  1135 				<xsl:with-param name="levels" select="substring-after($levels,' ')"/>
       
  1136 			</xsl:call-template>
       
  1137 		</xsl:when>
       
  1138 		<xsl:otherwise><level name="{$levels}"/></xsl:otherwise>
       
  1139 	</xsl:choose>
       
  1140 </xsl:template>
       
  1141 
       
  1142 <!-- widths of the collections in the levels that are in $item -->  
       
  1143 <xsl:template name="levels-widths"><xsl:param name="levels"/><xsl:param name="items" select="collection"/>
       
  1144 	<xsl:for-each select="exslt:node-set($levels)/*">
       
  1145 		<xsl:copy><xsl:copy-of select="@*"/>
       
  1146 			<xsl:attribute name="width">
       
  1147 				<xsl:variable name="match" select="$items[@level=current()/@name or (not(@level)  and not(current()/@name)) ]"/>
       
  1148 				<xsl:choose>
       
  1149 					<xsl:when test="$match">
       
  1150 						<xsl:variable name="w"  select="sum($match/@width)"/>
       
  1151 						<xsl:value-of select="$w +  (count($match) - 1) * $groupDx"/>
       
  1152 					</xsl:when>
       
  1153 					<xsl:otherwise>0</xsl:otherwise>
       
  1154 				</xsl:choose>
       
  1155 			</xsl:attribute>
       
  1156 		</xsl:copy>
       
  1157 	</xsl:for-each>
       
  1158 </xsl:template>
       
  1159 
       
  1160 <!-- add 2d sizes for each level contained in $item -->  
       
  1161 <xsl:template name="levels-size"><xsl:param name="levels"/><xsl:param name="items" select="package"/>
       
  1162 	<xsl:apply-templates select="$items[1]" mode="levels-size">
       
  1163 		<xsl:with-param name="levels" select="$levels"/>
       
  1164 	</xsl:apply-templates>
       
  1165 </xsl:template>
       
  1166 
       
  1167 <xsl:template mode="levels-size-step" match="package">
       
  1168 	<xsl:param name="levels"/> <!-- the set of levels -->
       
  1169 	<xsl:variable name="pkg" select="."/>
       
  1170 	<xsl:variable name="named" select="$levels[@name=current()/@level] or not(@level)"/>
       
  1171 	<!-- it's this level, or it spans all by not having any level defined, or by being in the span range for level  or it's the unnamed error level-->
       
  1172 	<xsl:variable name="match" select="$levels[@name=$pkg/@level  or not($pkg/@level)  or ($pkg/@span and following-sibling::level[position() &lt; $pkg/@span][@name=$pkg/@level or (not(@name) and not($named))]) or (not($named) and not(@name))]"/>
       
  1173 
       
  1174 
       
  1175 	<xsl:variable name="max-width"> <!-- the width of the widest level this spans (ie the x-pos of this pkg) -->
       
  1176 		<xsl:for-each select="$match[@width]">
       
  1177 			<xsl:sort select="@width" order="descending" data-type="number"/>
       
  1178 			<xsl:if test="position()=1"><xsl:value-of select="@width"/></xsl:if>
       
  1179 		</xsl:for-each>
       
  1180 	</xsl:variable>
       
  1181 
       
  1182 
       
  1183 	
       
  1184 	<xsl:variable name="h" select="(sum($match/@height) + $groupDy * (count($match/@height) - 1))"/> <!--height of all levels spanned by this, may be negative if no match -->
       
  1185 
       
  1186 	<xsl:for-each select="$levels">
       
  1187 		<xsl:copy><xsl:copy-of select="@*[name()!='width' and name()!='height'  and name()!='min-height']"/>
       
  1188 			<xsl:choose>
       
  1189 				<xsl:when test="not($match[@name=current()/@name or (not(@name) and not(current()/@name))])">
       
  1190 					<!--  the package does not impact this level, just copy existing attributes -->
       
  1191 					<xsl:copy-of select="@width|@height|@min-height"/>
       
  1192 				</xsl:when>
       
  1193 				<xsl:otherwise>
       
  1194 					<xsl:attribute name="width">
       
  1195 						<!-- current level is added to by this pkg -->
       
  1196 						<xsl:choose>
       
  1197 							<xsl:when test="$max-width='' or $max-width=0">
       
  1198 								<!-- at the current level, but not adding to anything-->
       
  1199 								<xsl:value-of select="$pkg/@width"/>
       
  1200 							</xsl:when>
       
  1201 							<xsl:otherwise>
       
  1202 								<!--  at the current level, but adding after something -->
       
  1203 								<xsl:value-of select="$pkg/@width + $groupDx + $max-width"/>		
       
  1204 							</xsl:otherwise>
       
  1205 						</xsl:choose>
       
  1206 					</xsl:attribute>					
       
  1207 					<xsl:choose>
       
  1208 						<xsl:when test="count($match)=1 and (not(@height) or (@height &lt; $pkg/@height))">
       
  1209 							<!-- pkg too tall, make just this single level bigger -->
       
  1210 							<xsl:copy-of select="$pkg/@height"/>
       
  1211 							<xsl:attribute name="min-height"><xsl:value-of select="$pkg/@height"/></xsl:attribute> <!-- level cannot be smaller than this -->
       
  1212 						</xsl:when>
       
  1213 						<xsl:when test="count($match)=1">
       
  1214 							<!-- level is bigger then the pkg, so keep height as is -->
       
  1215 							<xsl:copy-of select="@height|@min-height"/>
       
  1216 						</xsl:when>
       
  1217 						<xsl:when test="not($pkg/@levels) and $pkg/meta[@rel='model-levels']/level[@name=current()/@name or (not(@name) and not(current()/@name))]">
       
  1218 							<!-- there is a collection at this level, so note that height -->
       
  1219 							<xsl:choose>
       
  1220 								<xsl:when test="not(@height) or @height &lt; $mHeight">
       
  1221 									<xsl:attribute name="height"><xsl:value-of select="$mHeight"/></xsl:attribute>
       
  1222 									<xsl:attribute name="min-height"><xsl:value-of select="$mHeight"/></xsl:attribute>
       
  1223 								</xsl:when>							
       
  1224 								<xsl:otherwise>
       
  1225 									<xsl:copy-of select="@height|@min-height"/>
       
  1226 								</xsl:otherwise>
       
  1227 							</xsl:choose>
       
  1228 						</xsl:when>		
       
  1229 						<xsl:otherwise><xsl:copy-of select="@height|@min-height"/></xsl:otherwise>			
       
  1230 					</xsl:choose>
       
  1231 				</xsl:otherwise>
       
  1232 			</xsl:choose>
       
  1233 			<xsl:copy-of select="*"/>
       
  1234 			<xsl:if test="@name=$pkg/@level or (not($named) and not(@name)) or not($pkg/@level) and not(following-sibling::level)">
       
  1235 				<xsl:variable name="base">
       
  1236 					<xsl:for-each select="$match[@width]">
       
  1237 						<xsl:sort select="@width" order="descending" data-type="number"/>
       
  1238 						<xsl:if test="position()=1"><xsl:value-of select="@width"/></xsl:if>
       
  1239 					</xsl:for-each>
       
  1240 				</xsl:variable>
       
  1241 				<xsl:variable name="x">
       
  1242 					<xsl:choose>
       
  1243 						<xsl:when test="$base=''">
       
  1244 							<xsl:value-of select="$groupDx *count(@width)"/>
       
  1245 						</xsl:when>
       
  1246 						<xsl:otherwise>
       
  1247 							<xsl:value-of select="$base +  $groupDx *count(@width)"/>		
       
  1248 						</xsl:otherwise>
       
  1249 					</xsl:choose>
       
  1250 				</xsl:variable>
       
  1251 				<step ref="{$pkg/@id}" x="{$x}"/>
       
  1252 			</xsl:if>
       
  1253 		</xsl:copy>
       
  1254 	</xsl:for-each>
       
  1255 </xsl:template>
       
  1256 
       
  1257 <xsl:template mode="levels-size" match="package"><xsl:param name="levels"/>
       
  1258 	<xsl:apply-templates select="following-sibling::package[1]" mode="levels-size">
       
  1259 		<xsl:with-param name="levels">
       
  1260 			<xsl:apply-templates mode="levels-size-step" select="current()">
       
  1261 				<xsl:with-param name="levels" select="exslt:node-set($levels)/*"/>
       
  1262 			</xsl:apply-templates>
       
  1263 		</xsl:with-param>
       
  1264 	</xsl:apply-templates>
       
  1265 </xsl:template>
       
  1266 
       
  1267 <xsl:template mode="levels-size" match="package[not(following-sibling::package)]"><xsl:param name="levels"/>
       
  1268 	<xsl:apply-templates mode="levels-size-step" select=".">
       
  1269 		<xsl:with-param name="levels" select="exslt:node-set($levels)/*"/>
       
  1270 	</xsl:apply-templates>
       
  1271 </xsl:template>
       
  1272 
       
  1273 
       
  1274 <!-- /levels -->
       
  1275 
       
  1276 <!-- fix attributes -->
       
  1277 <xsl:template mode="copy-attr" match="@*"><xsl:copy-of select="."/></xsl:template>
       
  1278 
       
  1279 <xsl:template mode="copy-attr" match="collection/@level" priority="2">
       
  1280 		<xsl:choose><!-- remove invalid level attribute -->
       
  1281 			<!-- easier to read and write as two entries rather than one long one -->
       
  1282 			<xsl:when test="ancestor::package[@levels] and contains(concat(' ',normalize-space(ancestor::package/@levels),' '),concat(' ',.,' '))">
       
  1283 				<xsl:copy-of select="."/>
       
  1284 			</xsl:when>
       
  1285 			<xsl:when test="not(ancestor::package[@levels]) and ancestor::layer[@levels] and contains(concat(' ',normalize-space(ancestor::layer/@levels),' '),concat(' ',.,' '))">
       
  1286 				<xsl:copy-of select="."/>
       
  1287 			</xsl:when>
       
  1288 			<xsl:otherwise>
       
  1289 				<xsl:call-template name="Caller-Warning"><xsl:with-param name="text">collection <xsl:value-of select="../@id"/> with invalid level "<xsl:value-of select="."/>"</xsl:with-param>
       
  1290 				</xsl:call-template>				
       
  1291 			</xsl:otherwise>
       
  1292 		</xsl:choose>
       
  1293 </xsl:template>
       
  1294 
       
  1295 <xsl:template mode="copy-attr" match="layer/package/@level" priority="2">
       
  1296 		<xsl:choose><!--set to empty invalid level attribute -->
       
  1297 			<!-- easier to read and write as two entries rather than one long one -->
       
  1298 			<xsl:when test="not(../../@levels)">
       
  1299 				<xsl:call-template name="Caller-Warning">
       
  1300 					<xsl:with-param name="text">package <xsl:value-of select="../@id"/> cannot have level "<xsl:value-of select="."/>" if none defined in layer <xsl:value-of select="../@id"/></xsl:with-param>
       
  1301 				</xsl:call-template>				
       
  1302 			</xsl:when>
       
  1303 			<xsl:when test="contains(concat(' ',normalize-space(../../@levels),' '),concat(' ',.,' '))">
       
  1304 				<xsl:copy-of select="."/>
       
  1305 			</xsl:when>
       
  1306 			<xsl:otherwise>
       
  1307 				<xsl:call-template name="Caller-Warning">
       
  1308 					<xsl:with-param name="text">package <xsl:value-of select="../@id"/> with invalid level "<xsl:value-of select="."/>"</xsl:with-param>
       
  1309 				</xsl:call-template>
       
  1310 				<xsl:attribute name="level">*</xsl:attribute>				
       
  1311 			</xsl:otherwise>
       
  1312 		</xsl:choose>
       
  1313 </xsl:template>
       
  1314 
       
  1315 <xsl:template mode="copy-attr" match="layer/@span[.=0]" priority="2"/> <!-- default value, easier to remove -->
       
  1316 
       
  1317 <xsl:template mode="copy-attr" match="package/@span[.=1]" priority="2"/> <!-- default value, easier to remove -->
       
  1318 
       
  1319 
       
  1320 <!-- remove empty items, unless specifically told to include -->
       
  1321 
       
  1322 <xsl:template match="component[not(unit) and @filtered and not(/SystemDefinition/@placeholder-detail='component')]" mode="sizing" priority="3"/>
       
  1323 <xsl:template match="collection[not(component) and @filtered and not(/SystemDefinition[@placeholder-detail='component' or @placeholder-detail='collection'])]" mode="sizing"/>
       
  1324 <xsl:template match="package[not(collection or package) and @filtered and not(/SystemDefinition[@placeholder-detail!='layer'])]" mode="sizing"/>
       
  1325 <xsl:template match="layer[not(package) and @filtered and not(/SystemDefinition[@placeholder-detail='layer'])]" mode="sizing"/>
       
  1326 
       
  1327 
       
  1328 
       
  1329 
       
  1330 <xsl:template match="layer-group" mode="right-border">
       
  1331 	<xsl:variable name="d"><xsl:apply-templates select="." mode="depth"/></xsl:variable>
       
  1332 	<xsl:value-of select="$d * $lgrpDx"/>
       
  1333 </xsl:template>
       
  1334 
       
  1335 <xsl:template match="layer-group" mode="depth">
       
  1336 	<xsl:variable name="d">
       
  1337 		<xsl:call-template name="max-from-list">
       
  1338 			<xsl:with-param name="list">
       
  1339 				<xsl:text>0 </xsl:text>
       
  1340 				<xsl:for-each select="layer-group">
       
  1341 					<xsl:apply-templates select="." mode="depth"/><xsl:text> </xsl:text>
       
  1342 				</xsl:for-each>
       
  1343 			</xsl:with-param>
       
  1344 		</xsl:call-template>
       
  1345 	</xsl:variable>
       
  1346 	<xsl:value-of select="$d + 1"/>
       
  1347 </xsl:template>
       
  1348 
       
  1349 
       
  1350 <xsl:template match="layer-group" mode="left-border">
       
  1351 	<xsl:variable name="child-border">
       
  1352 		<xsl:call-template name="max-from-list">
       
  1353 			<xsl:with-param name="list">
       
  1354 				<xsl:text>0 </xsl:text>
       
  1355 				<xsl:for-each select="layer-group">
       
  1356 					<xsl:apply-templates select="." mode="left-border"/><xsl:text> </xsl:text>
       
  1357 				</xsl:for-each>
       
  1358 			</xsl:with-param>
       
  1359 		</xsl:call-template>
       
  1360 	</xsl:variable>
       
  1361 	<xsl:choose>
       
  1362 		<xsl:when test="@label"><xsl:value-of select="$child-border + $lgrpLabelDx"/></xsl:when>
       
  1363 		<xsl:otherwise><xsl:value-of select="$child-border + 0.75 * $lgrpDx"/></xsl:otherwise>
       
  1364 	</xsl:choose>
       
  1365 </xsl:template>
       
  1366 
       
  1367 
       
  1368 <!-- ====== legend ============= -->
       
  1369 
       
  1370 <xsl:include href="legend-module.xsl"/>
       
  1371 <!-- end legend -->
       
  1372 
       
  1373 
       
  1374 <!-- ============ utilities ============ -->
       
  1375 
       
  1376 <xsl:template name="sum-list"><xsl:param name="list"/> <!--  space-separated and terminated -->
       
  1377 	<xsl:variable name="cur" select="substring-before($list,' ')"/>
       
  1378 	<xsl:variable name="next" select="substring-after($list,' ')"/>
       
  1379 	<xsl:variable name="add"><xsl:choose>
       
  1380 		<xsl:when test="$next=''">0</xsl:when>
       
  1381 		<xsl:otherwise><xsl:call-template name="sum-list">
       
  1382 			<xsl:with-param name="list" select="$next"/>
       
  1383 		</xsl:call-template></xsl:otherwise>
       
  1384 	</xsl:choose></xsl:variable>
       
  1385 	<xsl:value-of select="$cur + $add"/>
       
  1386 </xsl:template>
       
  1387 
       
  1388 
       
  1389 <xsl:template name="max-from-list"><xsl:param name="list"/>
       
  1390 	<xsl:variable name="cur" select="substring-before($list,' ')"/>
       
  1391 	<xsl:variable name="next" select="substring-after($list,' ')"/>
       
  1392 	<xsl:variable name="max"><xsl:choose>
       
  1393 		<xsl:when test="$next=''">0</xsl:when>
       
  1394 		<xsl:otherwise><xsl:call-template name="max-from-list">
       
  1395 			<xsl:with-param name="list" select="$next"/>
       
  1396 		</xsl:call-template></xsl:otherwise>
       
  1397 	</xsl:choose></xsl:variable>
       
  1398 	<xsl:choose>
       
  1399 		<xsl:when test="$cur &gt; $max"><xsl:value-of select="$cur"/></xsl:when>
       
  1400 		<xsl:otherwise><xsl:value-of select="$max"/></xsl:otherwise>
       
  1401 	</xsl:choose>
       
  1402 </xsl:template>
       
  1403 </xsl:stylesheet>