Control the appearance of a Clicky diagram with style sheets written in a CSS-like language.
A CCSS file consists of a series of rule sets, which are blocks of declarations that apply to one or more selectors. For example, this rule set contains one declaration, for the background property. It says that all elements should have a red background:
* {
background: rgb(100%,0,0);
}
Tell Clicky to use a CCSS file with its -s option:
clicky -s CCSSFILE ...
CCSS selectors determine which elements are affected by a rule block. The following basic selectors are available:
* | Matches any element |
CLASSNAME | Matches elements with class CLASSNAME CLASSNAME can contain glob match characters, like * or ?. |
port | Matches ports |
handler | Matches handlers |
Additional modifiers can follow these selectors. For elements, the modifiers are:
#NAME | Matches elements named NAME NAME can contain glob match characters, like * or ?. |
.anonymous | Matches anonymous elements |
.primitive | Matches non-compound elements (defined directly by the driver) |
.compound | Matches compound elements (defined by elementclass or { ... }) |
.passthrough | Matches compound elements defined by { input -> output } |
.live | Matches elements that are hooked up to a live driver |
[in=N] | Matches elements with N inputs [in>=N] and similar comparisons also work. |
[out=N] | Matches elements with N outputs |
[name*=X] | Matches elements whose names contain X as a substring |
[downstream=S] | Matches elements downstream of at least one element or port matching S S can be an element class name or an element name, possibly containing glob match characters. Use #S to match an element name only. You can also contain port numbers, as in [0]. The reachability calculations uses Click's flow codes. |
[downstream!=S] | Matches elements not downstream of any element or port matching S |
[upstream=S] | Matches elements upstream of at least one element or port matching S |
[upstream!=S] | Matches elements not upstream of any element or port matching S |
[reachable=S] | Matches elements reachable from at least one element or port matching S Reachable is the union of upstream and downstream. |
[reachable!=S] | Matches elements not reachable from any element or port matching S |
[HANDLER=VALUE] | Matches elements hooked up to a live driver that have a handler named HANDLER, whose value is VALUE |
[HANDLER!=VALUE] | Matches elements hooked up to a live driver that have a handler named HANDLER, whose value is not VALUE |
:hover | Matches elements under the pointer |
:active | Matches elements that have been clicked |
:pressed | Matches elements that are being pressed |
For ports, the modifiers are:
#NUM | Matches ports numbered NUM |
.input | Matches input ports |
.output | Matches output ports |
.push | Matches push ports |
.pull | Matches pull ports |
.agnostic | Matches agnostic ports |
.error | Matches erroneous ports (too many for the element class or push/pull error) |
For handlers, the modifiers are:
#HANDLER | Matches handlers named HANDLER HANDLER can contain glob match characters, like * or ?. |
.read | Matches read handlers |
.write | Matches write handlers |
.param | Matches read handlers that take parameters |
.calm | Matches "calm" handlers (marked by the driver as rarely changing) |
.expensive | Matches "expensive" handlers (marked by the driver as expensive to compute) |
.deprecated | Matches "deprecated" handlers (marked by the driver as deprecated) |
A complete selector consists of one or more basic selectors separated by spaces. An element selector followed by a port selector matches the ports on elements that match the element selector. Multiple element selectors match compound element container relationships. For instance:
Foo Idle | Matches Idle elements in compound elements named Foo. |
* * * * | Matches elements that are 4 deep in a compound element stack. |
Idle port.push | Matches push ports on Idle elements. |
A rule set is preceded by one or more complete selectors separated by commas, and applies to any of those selectors.
When searching for a declaration, Clicky combines all applicable rulesets, ordering them so that the best matches take precedence.
The following declarations determine how elements are displayed.
orientation | Element orientation: either vertical (the default) or horizontal, or either combined with reverse. |
padding | Padding around inside of element box. padding-left, padding-right, padding-top, padding-bottom are supported. |
margin | Margin outside the element box. The -left, -right, etc. versions are supported. |
min-width | Minimum element box width, including padding. |
min-height | Minimum element box height, including padding. |
min-length | Minimum element box dimension, including padding, in the direction of flow. For horizontal orientation this is the same as min-width, for vertical orientation the same as min-height. |
height-step | Increment for element heights. |
color | Foreground color. Example: color: red, color: rgba(255,0,0,0.4). |
text | Text to print in the element. Can contain % escapes, explained below. |
font | Font to use for printing element text. |
background-color | Background color. |
border-style | Border style, none, solid, inset, dashed, or dotted. |
border-color | Border color. |
border-width | Border width. |
border | Combination of border style, color, and width. |
shadow-style | Shadow style, none, drop, outline, or unscaled-outline. |
shadow-width | Shadow width. |
shadow-color | Shadow color. |
style | Element drawing style; either normal or queue. |
queue-stripe-style | Border style for queue stripes. |
queue-stripe-width | Line width for queue stripes. |
queue-stripe-color | Color for queue stripes. |
queue-stripe-spacing | Spacing between queue stripes. |
display | Element display style: none (do not display), open (display compound elements as including their contents), closed (display compound elements as primitives), expanded (display compound elements' contents but not the compound element itself), or passthrough (do not display, but display connections to or from the element as passing through it). |
port-split | How to split elements by ports. It can occasionally make a diagram look better if an element is split into two separate boxes, one for inputs and one for outputs. Values: none (default), inputs (only display inputs), outputs (only display outputs), both (display two boxes, one for inputs and one for outputs). |
flow-split | How to split elements by flow. Takes a flow code, such as ab/ab. Will split the element into multiple boxes, one each for each type of flow. Defaults to no split. |
The % escapes for text declarations are:
%n | Name of element |
%c | Element class name |
%f | Flat name of element (compound ancestor names turned into slashes) |
%C | Configuration string |
%#C | Configuration string surrounded by parentheses -- but if configuration is empty, then nothing |
%:NC | Nth configuration argument |
%:*C | Configuration argument corresponding to the port (port-text only) |
%{handlername} | Value of handler (live configurations only) |
%.30C | At most the first 30 characters of the configuration string (can be applied to any escape) |
The text parser also accepts HTML-style font changes, such as <small> and <b>.
These declarations determine how ports are displayed:
port-shape | Shape of ports, triangle or rectangle. |
port-length | Port length. This is the dimension parallel to the side on which the port is displayed. |
port-width | Port width. This is the dimension perpendicular to the side on which the port is displayed. |
port-font | Font for port explanation text. |
port-text | Text to display near the port. |
port-color | Port fill color. |
port-border-style | Style of port border. |
port-border-width | Port border width. |
port-border-color | Port border color. |
port-margin | Margin around ports. |
port-edge-padding | Extra padding to add to first and last ports. |
port-display | Whether to display inputs, outputs, both, or neither (none). |
These declarations determine how handlers are used:
autorefresh | Whether to autorefresh handler values: off (default), on (autorefresh), or a time count in seconds (autorefresh with that period). |
autorefresh-period | Autorefresh period. |
display | How to display handlers: displayed (default), none, collapse (show the handler name but inside an expander). |
allow-refresh | Whether to allow refresh: yes (default) or no. |
Clicky CSS also support CSS-style media and import at-rules. A media at-rule says that the enclosed declarations apply only to the specified media types. For example, this says that drop shadows should only occur on the screen (not in PDF output):
@media screen {
* {
shadow: drop rgba(50%, 50%, 45%, 50%) 3px;
}
}
Clicky understands two media types, print (PDF output) and screen (the UI).
An import at-rule includes rules from another CCSS file:
@import "filename.ccss";
Here is a simple Click configuration:
rr :: RoundRobinSched;
TimedSource(0.2) -> c1::Counter
-> r :: { input -> Queue(20) -> output }
-> Print(q1) -> [0]rr;
TimedSource(0.5) -> c2::Counter -> Queue(20) -> Print(q2) -> [1]rr;
rr -> TimedSink(0.1);
Here's how Clicky displays it with the default styles.
The following examples demonstrate how the display attribute affects elements.
expanded and closed are meaningful on compound elements only, and determine how compounds' contents are displayed. closed hides the contents, where expanded hides the compound, shifting the contents one level up to mingle with other elements.
#r { display: closed; }
#r { display: expanded; }
display: none causes the Print elements and all connections to and from those elements to vanish, leaving the diagram disconnected. display: passthrough hides the Print elements, but preserves their connections.
Print { display: none; }
Print { display: passthrough; }
Splitting elements is occasionally useful when backwards connection (such as through ICMPError), or high connectivity (common to IPRewriters), complicates a diagram. Display the problematic element multiple times with different port subsets and the diagram may simplify itself, for instance into subsets.
#rr { port-split: both; }
#rr { flow-split: ab/a; }
Use port classes to highlight or annotate particular ports.
#c1 port.output#0 {
port-text: "interesting";
}
#rr port#1 {
port-text: "boring";
}
#c2 port.input#0 {
port-color: red;
port-width: 10;
port-length: 18;
}
Turn elements upstream of [0]rr blue:
[upstream=[0]rr] {
background: rgb(200,200,255);
}
Turn elements in between a TimedSource and a Print green:
[downstream=TimedSource][upstream=Print] {
background: rgb(200,255,200);
}
Here are the default rules Clicky applies to diagrams as of 3/7/2009. Your CCSS files augment these rules.
port.input {
port-shape: triangle;
port-length: 11px;
port-width: 7px;
port-margin: 1px;
port-edge-padding: 2px;
}
port.output {
port-shape: rectangle;
port-length: 9px;
port-width: 5.5px;
port-margin: 1px;
port-edge-padding: 2px;
}
port.push, port.push.agnostic {
port-color: black;
}
port.pull, port.pull.agnostic {
port-color: white;
}
port.agnostic {
port-color: gray;
}
port.push, port.pull {
port-border: black 1px solid;
}
port.agnostic, port.push.agnostic, port.pull.agnostic {
port-border: black 1px inset;
}
port.push.error, port.push.agnostic.error {
port-color: red;
}
port.pull.error, port.pull.agnostic.error {
port-color: rgb(100%, 75%, 75%);
}
port.push.error, port.pull.error {
port-border: red 1px solid;
}
port.agnostic.error, port.push.agnostic.error, port.pull.agnostic.error {
port-border: red 1px inset;
}
* {
background: rgb(100%, 100%, 87%);
color: black;
border: 1px solid black;
padding: 8px 12px;
margin: 20px 14px;
shadow: drop rgba(50%, 50%, 45%, 50%) 3px;
orientation: vertical;
scale: 100%;
queue-stripe: 1px solid rgb(87%, 87%, 50%);
queue-stripe-spacing: 12px;
text: "%n\n<small>%c</small>";
display: open;
port-display: both;
port-font: 6;
@media print {
font: Times;
port-font: Times 6;
}
}
*.anonymous {
text: "%n";
}
* * {
background: rgb(98%, 98%, 81%);
}
* * * {
background: rgb(96%, 96%, 75%);
}
* * * * {
background: rgb(94%, 94%, 69%);
}
@media screen {
*:hover {
background: #fffff2;
}
*:active, *:active:hover {
background: #ffff94;
shadow: unscaled-outline rgba(90%, 20%, 95%, 50%) 3px;
}
*:pressed, *:active:pressed {
shadow: drop rgba(50%, 50%, 45%, 50%) 3px;
}
}
*Queue {
min-length: 49.6px;
style: queue;
}
fullness {
style: fullness;
length: length;
capacity: capacity;
color: rgba(0%, 0%, 100%, 20%);
autorefresh: length 0.1s;
}
activity {
style: activity;
handler: count;
decay: 5s;
max-value: 3;
type: rate;
autorefresh: 1s;
}