' C4-PlantUML ' Colors ' ################################## !global $ELEMENT_FONT_COLOR = "#FFFFFF" !global $ARROW_COLOR = "#666666" !global $BOUNDARY_COLOR = "#444444" !global $LEGEND_FONT_COLOR = "#FFFFFF" !global $LEGEND_TITLE_COLOR = "#000000" !global $LEGEND_UNDEFINED_BG_COLOR = "#D5CFEE" !global $LEGEND_UNDEFINED_FONT_COLOR = "#8B77E4" !global $LEGEND_SHADOW_TEXT = "(shadow) " !global $LEGEND_NO_SHADOW_TEXT = "(no shadow) " !global $LEGEND_NO_FONT_BG_TEXT = "(no text, no back color) " !global $LEGEND_NO_FONT_TEXT = "(no text color) " !global $LEGEND_NO_BG_TEXT = "(no back color) " !global $LEGEND_NO_LINE_TEXT = "(no line color) " ' Styling ' ################################## !global $TECHN_FONT_SIZE = 12 skinparam defaultTextAlignment center skinparam wrapWidth 200 skinparam maxMessageSize 150 skinparam LegendBorderColor transparent skinparam LegendBackgroundColor transparent skinparam LegendFontColor $LEGEND_FONT_COLOR skinparam rectangle { StereotypeFontSize 12 shadowing false } skinparam database { StereotypeFontSize 12 shadowing false } skinparam queue { StereotypeFontSize 12 shadowing false } skinparam Arrow { Color $ARROW_COLOR FontColor $ARROW_COLOR FontSize 12 } skinparam rectangle<> { Shadowing false StereotypeFontSize 0 FontColor $BOUNDARY_COLOR BorderColor $BOUNDARY_COLOR BorderStyle dashed } ' Legend and Tags ' ################################## !global $tagDefaultLegend = "" !global $tagCustomLegend = "" ' rel specific !unquoted function $toStereos($tags) !if (%strlen($tags) == 0) !return '' !endif !$stereos = '' !$brPos = %strpos($tags, "+") !while ($brPos >= 0) !$tag = %substr($tags, 0, $brPos) !$stereos = $stereos + '<<' + $tag + '>>' %set_variable_value("$" + $tag + "_LineLegend", %true()) !$tags = %substr($tags, $brPos+1) !$brPos = %strpos($tags, "+") !endwhile !if (%strlen($tags)>0) !$stereos = $stereos + '<<' + $tags + '>>' %set_variable_value("$" + $tags + "_LineLegend", %true()) !endif !return $stereos !endfunction !unquoted function $toStereos($elementType, $tags) !if (%strlen($tags) == 0) !$stereos = '<<' + $elementType + '>>' %set_variable_value("$" + $elementType + "Legend", %true()) !return $stereos !endif !$stereos = '' !$brPos = %strpos($tags, "+") !while ($brPos >= 0) !$tag = %substr($tags, 0, $brPos) !$stereos = $stereos + '<<' + $tag + '>>' %set_variable_value("$" + $tag + "Legend", %true()) !$tags = %substr($tags, $brPos+1) !$brPos = %strpos($tags, "+") !endwhile !if (%strlen($tags)>0) !$stereos = $stereos + '<<' + $tags + '>>' %set_variable_value("$" + $tags + "Legend", %true()) !endif ' has to be last, otherwise PlantUML overwrites all tag specific skinparams !$stereos = $stereos + '<<' + $elementType + '>>' %set_variable_value("$" + $elementType + "Legend", %true()) !return $stereos !endfunction !function $elementTagSkinparams($element, $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) !$elementSkin = "skinparam " + $element +"<<" + $tagStereo + ">> {" + %newline() !if ($fontColor!="") !$elementSkin = $elementSkin + " StereotypeFontColor " + $fontColor + %newline() !$elementSkin = $elementSkin + " FontColor " + $fontColor + %newline() !endif !if ($bgColor!="") !$elementSkin = $elementSkin + " BackgroundColor " + $bgColor + %newline() !endif !if ($borderColor!="") !$elementSkin = $elementSkin + " BorderColor " + $borderColor+ %newline() !endif !if ($shadowing == "true") !$elementSkin = $elementSkin + " Shadowing<<" + $tagStereo + ">> " + "true" + %newline() !endif !if ($shadowing == "false") !$elementSkin = $elementSkin + " Shadowing<<" + $tagStereo + ">> " + "false" + %newline() !endif !$elementSkin = $elementSkin + "}" + %newline() !return $elementSkin !endfunction !unquoted procedure $defineSkinparams($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) !$tagSkin = $elementTagSkinparams("rectangle", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) !$tagSkin = $tagSkin + $elementTagSkinparams("database", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) !$tagSkin = $tagSkin + $elementTagSkinparams("queue", $tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) $tagSkin !endprocedure !unquoted procedure $defineRelSkinparams($tagStereo, $textColor, $lineColor) !$elementSkin = "skinparam Arrow<<" + $tagStereo + ">> {" + %newline() !$elementSkin = $elementSkin + " Color " !if ($lineColor!="") !$elementSkin = $elementSkin + $lineColor !endif !if ($textColor!="") !$elementSkin = $elementSkin + ";text:" + $textColor !endif !$elementSkin = $elementSkin + %newline() !$elementSkin = $elementSkin + "}" + %newline() $elementSkin !endprocedure !function $tagLegendEntry($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) !$tagEntry = "|" !if ($bgColor!="") !$bg = $bgColor !else !$bg = $LEGEND_UNDEFINED_BG_COLOR !endif ' named colors have to start with # too !if (%substr($bg, 0, 1) != "#") !$bg = "#" + $bg !endif !$tagEntry = $tagEntry + "<" + $bg +">" ' ..white rectangle !if ($borderColor!="") !$tagEntry = $tagEntry + " " !else !$tagEntry = $tagEntry + " " !endif !if ($fontColor!="") !$tagEntry = $tagEntry + "" !else !$tagEntry = $tagEntry + "" !endif !$tagEntry = $tagEntry + " " + $tagStereo + " " !if ($shadowing == "true") !$tagEntry = $tagEntry + $LEGEND_SHADOW_TEXT !endif !if ($shadowing == "false") !$tagEntry = $tagEntry + $LEGEND_NO_SHADOW_TEXT !endif !if ($fontColor == "" && $bgColor == "") !$tagEntry = $tagEntry + $LEGEND_NO_FONT_BG_TEXT !else !if ($fontColor == "") !$tagEntry = $tagEntry + $LEGEND_NO_FONT_TEXT !endif !if ($bgColor == "") !$tagEntry = $tagEntry + $LEGEND_NO_BG_TEXT !endif !endif !$tagEntry = $tagEntry + " " !$tagEntry = $tagEntry + "|" !return $tagEntry !endfunction !function $tagRelLegendEntry($tagStereo, $textColor, $lineColor) !$tagEntry = "|" !$bg = $LEGEND_UNDEFINED_BG_COLOR ' named colors have to start with # too !if (%substr($bg, 0, 1) != "#") !$bg = "#" + $bg !endif ' !$tagEntry = $tagEntry + "<" + $bg +">" ' ..white line !if ($lineColor!="") !$tagEntry = $tagEntry + " " !else ' !$tagEntry = $tagEntry + " " !$tagEntry = $tagEntry + " " !endif !if ($textColor!="") !$tagEntry = $tagEntry + "" !else !$tagEntry = $tagEntry + "" !endif !$tagEntry = $tagEntry + " " + $tagStereo + " " !if ($textColor == "") !$tagEntry = $tagEntry + $LEGEND_NO_FONT_TEXT !endif !if ($lineColor == "") !$tagEntry = $tagEntry + $LEGEND_NO_LINE_TEXT !endif !$tagEntry = $tagEntry + " " !$tagEntry = $tagEntry + "|" !return $tagEntry !endfunction !unquoted procedure $addTagToDynamicLegend($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="") '' ignore workaround tags with & ' !if (%strpos($tagStereo, "&")<0) !$tagEntry = $tagLegendEntry($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) %set_variable_value("$" + $tagStereo + "LegendEntry", $tagEntry) !$tagCustomLegend = $tagCustomLegend + $tagStereo + "\n" ' !endif !endprocedure !unquoted procedure $addRelTagToDynamicLegend($tagStereo, $textColor="", $lineColor="") '' ignore workaround tags with & ' !if (%strpos($tagStereo, "&")<0) !$tagEntry = $tagRelLegendEntry($tagStereo, $textColor, $lineColor) %set_variable_value("$" + $tagStereo + "_LineLegendEntry", $tagEntry) !$tagCustomLegend = $tagCustomLegend + $tagStereo + "_Line\n" ' !endif !endprocedure !procedure $showActiveLegendEntries($allDefined) !$brPos = %strpos($allDefined, "\n") !while ($brPos >= 0) !$tagStereo = %substr($allDefined, 0, $brPos) !$allDefined = %substr($allDefined, $brPos+2) !$brPos = %strpos($allDefined, "\n") !if (%variable_exists("$" + $tagStereo + "Legend")) %get_variable_value("$" + $tagStereo + "LegendEntry") !endif !endwhile !if (%strlen($allDefined)>0) !$tagStereo = $allDefined !if (%variable_exists("$" + $tagStereo + "Legend")) %get_variable_value("$" + $tagStereo + "LegendEntry") !endif !endif !endprocedure ' used by new defined tags !unquoted procedure AddTagSupport($tagStereo, $bgColor="", $fontColor="", $borderColor="", $shadowing="") $defineSkinparams($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) $addTagToDynamicLegend($tagStereo, $bgColor, $fontColor, $borderColor, $shadowing) !endprocedure ' used by new defined rel tags !unquoted procedure AddRelTagSupport($tagStereo, $textColor="", $lineColor="") $defineRelSkinparams($tagStereo, $textColor, $lineColor) $addRelTagToDynamicLegend($tagStereo, $textColor, $lineColor) !endprocedure ' update the style of existing elements like person, ... !unquoted procedure UpdateElementStyle($elementName, $bgColor="", $fontColor="", $borderColor="", $shadowing="") $defineSkinparams($elementName, $bgColor, $fontColor, $borderColor, $shadowing) !$tagEntry = $tagLegendEntry($elementName, $bgColor, $fontColor, $borderColor, $shadowing) %set_variable_value("$" + $elementName + "LegendEntry", $tagEntry) !endprocedure ' update the style of default relation, it has to set both properties (combined statement not working) !unquoted procedure UpdateRelStyle($textColor, $lineColor) !$elementSkin = "skinparam Arrow {" + %newline() !$elementSkin = $elementSkin + " Color " + $lineColor + %newline() !$elementSkin = $elementSkin + " FontColor " + $textColor + %newline() !$elementSkin = $elementSkin + "}" + %newline() $elementSkin !endprocedure ' tags/stereotypes have to be delimited with \n !unquoted procedure SetDefaultLegendEntries($tagStereoEntries) !$tagDefaultLegend = $tagStereoEntries !endprocedure ' Line breaks ' ################################## ' PlantUML supports no DETERMINISTIC/automatic line breaks of "PlantUML line" (C4 Relashionships) ' therefore Rel...() implements an automatic line break based on spaces (like in all other objects). ' If a $type contains \n then these are used (and no automatic space based line breaks are done) ' $REL_TECHN_MAX_CHAR_WIDTH defines the automatic line break position !global $REL_TECHN_MAX_CHAR_WIDTH = 35 !global $REL_DESCR_MAX_CHAR_WIDTH = 32 !unquoted function $breakDescr($descr, $widthStr) !$width = %intval($widthStr) !$multiLine = "" !if (%strpos($descr, "\n") >= 0) !else !while (%strlen($descr)>$width) !$brPos = $width !while ($brPos>0 && %substr($descr, $brPos, 1)!= ' ') !$brPos = $brPos - 1 !endwhile !if ($brPos < 1) !$brPos = %strpos($descr, " ") !else !endif !if ($brPos > 0) !$multiLine = $multiLine + %substr($descr, 0, $brPos) + "\n" !$descr = %substr($descr, $brPos + 1) !else !$multiLine = $multiLine+ $descr !$descr = "" !endif !endwhile !endif !if (%strlen($descr)>0) !$multiLine = $multiLine + $descr !endif !return $multiLine !endfunction ' $breakTechn() supports //...//; $breakNode() in C4_Deployment supports no //....// !unquoted function $breakTechn($techn, $widthStr) !$width = %intval($widthStr) !$multiLine = "" !if (%strpos($techn, "\n") >= 0) !while (%strpos($techn, "\n") >= 0) !$brPos = %strpos($techn, "\n") !$multiLine = $multiLine + %substr($techn, 0, $brPos) + '//\n//' !$techn = %substr($techn, $brPos+2) !endwhile !else !while (%strlen($techn)>$width) !$brPos = $width !while ($brPos>0 && %substr($techn, $brPos, 1)!= ' ') !$brPos = $brPos - 1 !endwhile !if ($brPos < 1) !$brPos = %strpos($techn, " ") !else !endif !if ($brPos > 0) !$multiLine = $multiLine + %substr($techn, 0, $brPos) + '//\n//' !$techn = %substr($techn, $brPos + 1) !else !$multiLine = $multiLine+ $techn !$techn = "" !endif !endwhile !endif !if (%strlen($techn)>0) !$multiLine = $multiLine + $techn !endif !return $multiLine !endfunction ' Element properties ' ################################## ' collect all defined properties as table rows !global $propTable = "" !global $propTableCaption = "" !global $propColCaption = "=" !unquoted function SetPropertyHeader($col1Name, $col2Name, $col3Name = "", $col4Name = "") !$propColCaption = "" !$propTableCaption = "|= " + $col1Name + " |= " + $col2Name + " |" !if ($col3Name != "") !$propTableCaption = $propTableCaption + "= " + $col3Name + " |" !endif !if ($col4Name != "") !$propTableCaption = $propTableCaption + "= " + $col4Name + " |" !endif !return "" !endfunction !unquoted function WithoutPropertyHeader() !$propTableCaption = "" !$propColCaption = "=" !return "" !endfunction !unquoted function AddProperty($col1, $col2, $col3 = "", $col4 = "") !if ($propTable == "") !if ($propTableCaption != "") !$propTable = $propTableCaption + "\n" !endif !else !$propTable = $propTable + "\n" !endif !$propTable = $propTable + "| " + $col1 + " |" + $propColCaption + " " + $col2 + " |" !if ($col3 != "") !$propTable = $propTable + " " + $col3 + " |" !endif !if ($col4 != "") !$propTable = $propTable + " " + $col4 + " |" !endif !return "" !endfunction !unquoted function $getProps($alignedNL = "\n") !if ($propTable != "") !$retTable = $alignedNL + $propTable !$propTable = "" !return $retTable !endif !return "" !endfunction !unquoted function $getProps_L() !return $getProps("\l") !endfunction !unquoted function $getProps_R() !return $getProps("\r") !endfunction SetPropertyHeader("Property","Value") ' Layout ' ################################## !procedure HIDE_STEREOTYPE() hide stereotype !endprocedure !procedure LAYOUT_AS_SKETCH() skinparam backgroundColor #EEEBDC skinparam handwritten true skinparam defaultFontName "Comic Sans MS" center footer Warning: Created for discussion, needs to be validated !endprocedure !procedure LAYOUT_TOP_DOWN() top to bottom direction !endprocedure !procedure LAYOUT_LEFT_RIGHT() left to right direction !endprocedure ' has to be last call in diagram !unquoted procedure SHOW_LEGEND($hideStereotype="true") !if ($hideStereotype=="true") hide stereotype !endif legend right |**Legend** | $showActiveLegendEntries($tagDefaultLegend) $showActiveLegendEntries($tagCustomLegend) endlegend !endprocedure ' Boundaries ' ################################## !function $getBoundary($label, $type) !if ($type == "") !return '==' + $label !endif !if (type != "") !return '==' + $label + '\n[' + $type + ']' !endif !endfunction !unquoted procedure Boundary($alias, $label, $type="", $tags="") rectangle "$getBoundary($label, $type)" $toStereos("boundary", $tags) as $alias !endprocedure ' Relationship ' ################################## !function $getRel($direction, $alias1, $alias2, $label, $techn, $descr, $sprite, $tags) !$rel = $alias1 + ' ' + $direction + ' ' + $alias2 !if ($tags != "") !$rel = $rel + ' ' + $toStereos($tags) !endif !$rel = $rel + ' : ' !if ($sprite != "") ' if it starts with & it's a OpenIconic, details see https://useiconic.com/open/ !if (%substr($sprite, 0, 1) != "&") !$rel = $rel + '<$'+$sprite+'> ' !else !$rel = $rel + '<'+$sprite+'> ' !endif !endif !$rel = $rel + '**' + $label + '**' !if ($techn != "") ' line break is not deterministic, calculate it !$rel = $rel + '\n//[' + $breakTechn($techn, $REL_TECHN_MAX_CHAR_WIDTH) + ']//' !endif !if ($descr != "") ' line break is not deterministic, calculate it !$rel = $rel + '\n\n' + $breakDescr($descr, $REL_DESCR_MAX_CHAR_WIDTH) !endif !return $rel !endfunction !unquoted procedure Rel_($alias1, $alias2, $label, $direction) $alias1 $direction $alias2 : **$label** !endprocedure !unquoted procedure Rel_($alias1, $alias2, $label, $techn, $direction) $alias1 $direction $alias2 : **$label**\n//[$techn]// !endprocedure !unquoted procedure Rel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_Back($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<--", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_Neighbor($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_Back_Neighbor($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_D($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-DOWN->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_Down($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-DOWN->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel_D($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-DOWN->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel_Down($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-DOWN->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_U($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-UP->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_Up($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-UP->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel_U($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-UP->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel_Up($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-UP->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_L($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-LEFT->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_Left($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-LEFT->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel_L($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-LEFT->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel_Left($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-LEFT->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_R($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-RIGHT->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure Rel_Right($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("-RIGHT->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel_R($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-RIGHT->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure !unquoted procedure BiRel_Right($from, $to, $label, $techn="", $descr="", $sprite="", $tags="") $getRel("<<-RIGHT->>", $from, $to, $label, $techn, $descr, $sprite, $tags) !endprocedure ' Layout Helpers ' ################################## !unquoted procedure Lay_D($from, $to) $from -[hidden]D- $to !endprocedure !unquoted procedure Lay_U($from, $to) $from -[hidden]U- $to !endprocedure !unquoted procedure Lay_R($from, $to) $from -[hidden]R- $to !endprocedure !unquoted procedure Lay_L($from, $to) $from -[hidden]L- $to !endprocedure