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