Hojas de estilo¶
Desde Gaphor 2.0, los diagramas pueden tener un aspecto diferente mediante hojas de estilo. Las hojas de estilo usan la sintaxis Cascading Style Sheets (CSS). CSS se usa para describir la presentación de un documento escrito en un lenguaje de marcado, y se usa más comúnmente con HTML para páginas web.
En la página principal de CSS del W3C, CSS se describe como:
Cascading Style Sheets (CSS) es un mecanismo sencillo para añadir estilo (por ejemplo, fuentes, colores, espaciado) a los documentos web.
Pero su aplicación va mucho más allá de los documentos web. Gaphor usa CSS para proporcionar elementos de estilo a los elementos de los diagramas. CSS nos permite, a los usuarios de Gaphor, cambiar el aspecto visual de nuestros diagramas. Se pueden cambiar el color y los estilos de línea para facilitar la lectura de los diagramas.
Dado que se trata de un diagrama y no de un documento HTML, se han omitido algunas características CSS.
El estilo es parte del modelo, por lo que todos los que trabajen en un modelo tendrán el mismo estilo. Para editar el estilo pulse el botón de la página de herramientas en la esquina superior derecha en gaphor:

He aquí un ejemplo sencillo de cómo cambiar el color de fondo de una clase:
class {
background-color: beige;
}
O cambiar el color de un componente, sólo cuando está anidado en un nodo:
node component {
background-color: skyblue;
}
El propio diagrama también se expresa como un nodo CSS. Es bastante fácil definir un estilo «oscuro»:
diagram {
background-color: #343131;
}
* {
color: white;
text-color: white;
}
Aquí ya se ve el primer atributo personalizado: text-color. Esta propiedad le permite controlar el color del texto dibujado en un elemento. El color se usa para las líneas (trazos) que hacen el diseño de un elemento de diagrama.
Selectores compatibles¶
Dado que estamos tratando con diagramas y modelos, no necesitamos todas las características de CSS. A continuación encontrarás un resumen de todas las características CSS soportadas por Gaphor.
|
Todos los elementos del diagrama, incluido el propio diagrama. |
|
Cualquier elemento componente descendiente de un nodo. |
|
Un elemento componente que es hijo de un nodo. |
|
Each diagram item has a class «item» assigned. This makes it easy to differentiate them from e.g. name elements. |
|
Un elemento de generalización con un sujeto presente. |
|
Una clase con el nombre «Foo». |
|
Un diagrama cuyo nombre empieza por «borrador». |
|
Un diagrama con nombre terminado en «borrador». |
|
Un diagrama con un nombre que contiene el texto «borrador». |
|
Un diagrama con el nombre «borrador» o «elemento». |
|
Un diagrama con nombre «borrador» o que empieza por «borrador-«. |
|
El elemento enfocado. Otras pseudo clases son:
|
|
Un nodo que no contiene nodos hijos en el diagrama. |
|
Refers to the diagram itself. Esto solo es aplicable para el diagrama |
|
A node is the first element among a group of sibling. |
|
El elemento contiene cualquiera de los selectores proporcionados. P. ej., |
|
Coincide con cualquiera de los selectores proporcionados. P. ej., |
|
Negar el selector. P. ej., |
|
Provide extra content after a text.
Only the |
La especificación oficial de CSS3 attribute selectors.
Gaphor proporciona el selector de atributos
|=en aras de la exhaustividad. Sin embargo, probablemente no sea muy útil en este contexto.Tenga en cuenta que Gaphor CSS no admite ID para elementos de diagrama, por lo que no se usa la sintaxis CSS para ID (
#some-id). Además, la sintaxis de clase (.some-class) no está soportada actualmente.
Propiedades de estilo¶
Gaphor soporta un subconjunto de propiedades CSS y algunas propiedades específicas de Gaphor. El intérprete de hojas de estilo es relativamente sencillo. Todas las anchuras, alturas y tamaños se miden en píxeles. No se pueden usar declaraciones de estilo complejas, como la propiedad font en HTML/CSS que puede contener familia de fuentes, tamaño, peso.
Some properties are inherited from the parent style. The parent often is a diagram.
When you set a color`` or a font-familyondiagram`, it will propagate down
to the items contained in the diagram.
Colores¶
|
Ejemplos:
|
|
Color used for lines. (inherited) |
|
Color for text. (inherited) Obsoleto desde la versión 2.23.0: Use color if possible. |
|
Factor de opacidad del color ( |
Un color puede ser cualquier código de color CSS3, como se describe en la documentación CSS. Gaphor soporta todas las notaciones de color:
rgb(),rgba(),hsl(),hsla(), código hexadecimal (#ffffff) y nombres de color.
Texto y tipografías¶
|
A single font name (e.g. |
|
An absolute size (e.g. |
|
Either |
|
Either |
|
Either |
|
Ya sea |
|
Alineación vertical del texto. Ya sea |
|
Establece el espaciado vertical para los elementos tipo icono (actores, estado inicial). Ejemplo: |
|
Change the line wrapping behavior for text. (inherited) |
font-familypuede ser solo un nombre de tipografía, no una lista de nombres (fallback), como se usa para HTML.font-sizepuede ser un número o valores CSS de tamaño absoluto. Solo se admiten los valoresx-small,small,medium,largeyx-large.
Trazado y espaciado¶
|
Radio para rectángulos: |
|
Estilo para líneas discontinuas: |
|
Alineación del contenido de las cajas. Ya sea |
|
Ya sea |
|
Set the width for lines: |
|
Establece la altura mínima de un elemento: |
|
Establece el ancho mínimo de un elemento: |
|
Set maximum width (text fields only): |
|
Estilo CSS de relleno (arriba, derecha, abajo, izquierda). Ejemplo: |
paddingestá definido por enteros en el rango de 1 a 4. No es necesario usar ninguna unidad (px, pt, em). Todos los valores están en distancia de píxel.dash-stylees una lista de números (línea, hueco, línea, hueco, …)line-stylesolo tiene efecto cuando se define en undiagram. Se puede proporcionar un factor de omisión en el rango de -2 a 2.
Pseudo elements¶
Currently, only the ::after pseudo element is supported.
|
Extra content to be shown after a text. |
Variables¶
Desde Gaphor 2.16.0 puede usar variables CSS en sus hojas de estilo.
Esto le permite definir valores de uso frecuente de forma más genérica. Piense en cosas como el estilo de guiones de línea y los colores.
La función var() tiene algunas limitaciones:
Los valores no pueden tener un valor predeterminado.
Las variables no pueden tener una variable como valor.
Ejemplo:
diagram {
--bg-color: whitesmoke;
background-color: var(--bg-color);
}
diagram[diagramType=sd] {
--bg-color: rgb(200, 200, 255);
}
Todos los diagramas tienen un fondo blanco. Los diagramas de secuencia tienen un fondo azulado.
Media queries¶
Gaphor soporta los modos oscuro y claro desde la versión 2.16.0. Los esquemas de color oscuro y claro se usan exclusivamente para la edición en pantalla. Al exportar imágenes, sólo se aplica el esquema de color predeterminado. Los esquemas de color se pueden definir con consultas @media. La consulta oficial prefers-color-scheme = dark está soportada, así como la más conveniente dark-mode.
/* The background you see in exported diagrams: */
diagram {
background-color: transparent;
}
/* Use a slightly grey background in the editor: */
@media light-mode {
diagram {
background-color: #e1e1e1;
}
}
/* And anthracite a slightly grey background in the editor: */
@media dark-mode {
diagram {
background-color: #393D47;
}
}
Estilos de diagrama¶
En un diagrama solo pueden definirse unas pocas propiedades, a saber, background-color y line-style. El estilo del diagrama se define por separado de los estilos de los elementos del diagrama. De esta manera es posible establecer el color de fondo para los diagramas específicamente. El estilo de línea puede ser las líneas rectas normales, o un estilo «omisión» más juguetón. Para el estilo «omisión» se puede proporcionar un factor opcional de bamboleo para establecer el nivel de bamboleo de la línea. 0.5 es el valor predeterminado, 0.0 es una línea recta. El valor debe estar comprendido entre -2,0 y 2,0. Los valores entre 0,0 y 0,5 producen un efecto sutil.
CSS model elements¶
Gaphor tiene muchos elementos de modelo. ¿Cómo se puede saber qué elemento debe ser estilizado?
Gaphor solo aplica estilo a los elementos que están en el modelo, por lo que debe ser explícito en sus nombres. Por ejemplo: Component hereda de Class en el modelo UML, pero cambiar un color para Class no lo cambia para Component.
Si pasa el ratón por encima de un botón de la caja de herramientas (sección inferior izquierda), aparecerá una ventana emergente con el nombre del elemento y un acceso directo. Como regla general, puede usar el nombre del componente, pegado como el nombre en la hoja de estilos. Un Componente puede ser direccionado como component, Caso de uso como usecase. La coincidencia de nombres es insensible a mayúsculas y minúsculas. Los nombres CSS se escriben en minúsculas por defecto.
Sin embargo, como los nombres de los elementos CSS se derivan de los nombres usados en Gaphor, hay algunas excepciones.
Perfil |
Grupo |
Elemento |
Elemento CSS |
|---|---|---|---|
* |
* |
nombre del elemento |
nombre del elemento sin espacios P. ej. |
UML |
Clases |
Todas las asociaciones |
|
UML |
Componentes |
Dispositivo/Nodo |
|
UML |
Acciones |
Nodo de decisión/fusión |
|
UML |
Acciones |
Nodo de bifurcación/unión |
|
UML |
Acciones |
Carril |
|
UML |
Interacciones |
mensaje reflexivo |
|
UML |
Estados |
Pseudoestado inicial |
|
UML |
Estados |
Pseudoestado de historia |
|
UML |
Perfiles |
Metaclase |
|
Modelo C4 |
Modelo C4 |
Persona |
|
Modelo C4 |
Modelo C4 |
Sistema informático |
|
Modelo C4 |
Modelo C4 |
Componente |
|
Modelo C4 |
Modelo C4 |
Contenedor |
|
Modelo C4 |
Modelo C4 |
Contenedor: Base de datos |
|
SysML |
Bloques |
ValorTipo |
|
SysML |
Bloques |
Primitivo |
|
SysML |
Requisitos |
Derivación de requisitos |
|
RAAML |
FTA |
cualquier puerta AND/OR/… |
|
Ideas¶
He aquí algunas ideas que van más allá de cambiar un color o un tipo de letra. Con los siguientes ejemplos profundizamos en la estructura del modelo de Gaphor para revelar más información a los usuarios.
To create your own expression you may want to use the Console ( → Tools → Console). Drop us a line on
Gitter and we would be happy to help you.
El paquete de borradores¶
Todos los diagramas del paquete «Borradores» deben dibujarse con líneas poco definidas:
diagram[owner.name=drafts] {
line-style: sloppy 0.3;
}
diagram[owner.name=drafts] * {
font-family: Purisa; /* Or use some other font that's installed on your system */
}
Wrap long attributes, operations, and stereotype values¶
Sometimes attribute values get a bit lengthy. By default, Gaphor will not wrap text. If you want to, you can add this little snippet to wrap text for lengthy attributes on classes. You can also apply this to other types, of course.
class * {
white-space: normal;
}
Relaciones inconexas¶
Todos los elementos de un diagrama que no estén respaldados por un elemento del modelo deben dibujarse en color rojo oscuro. Esto se puede usar para detectar relaciones no muy bien conectadas, como Generalización, Implementación y Dependencia. Estos elementos sólo estarán respaldados por un elemento del modelo una vez que conecte ambos extremos de la línea. Esta regla excluirá elementos simples, como líneas y cajas, que nunca tendrán un elemento modelo de respaldo.
:not(:is(:root, line, box, ellipse, commentline))[subject=""] {
color: firebrick;
}
Líneas sólidas de flujo de control¶
En Gaphor, las líneas de flujo de control siguen el estilo SysML: discontinuas. Si desea, o necesita seguir estrictamente las especificaciones oficiales UML, puede simplemente hacer esas líneas sólidas.
controlflow {
dash-style: 0;
}
Nota destacada¶
Todos los comentarios que empiecen por la frase «todo» pueden resaltarse con un color diferente específico para cada usuario. Esto puede usarse para avisarle de que tiene que hacer algún trabajo adicional para finalizar el diagrama.
comment[body^="TODO"] {
background-color: skyblue;
}
Emphesize abstract classes and operations¶
It may be that the italic font used is not distinguishable enough to differentiate between
concrete and abstract classes or operations.
To make this work we check if the isAbstract attribute is set on the element:
:is(name, operation)[isabstract]::after {
content: " {abstract}"
}
System Style Sheet¶
/* Gaphor diagram style sheet */
* {
--opaque-background-color: white;
background-color: transparent;
}
:not(diagramframe):drop {
color: #1a5fb4;
line-width: 3;
}
:disabled {
opacity: 0.5;
}
@media light-mode {
* {
--opaque-background-color: #fafafa;
}
}
@media dark-mode {
* {
--opaque-background-color: #242424;
color: white;
}
:drop {
color: #62a0ea;
}
}
:root {
color: black;
font-family: sans;
font-size: 14 ;
line-width: 2;
padding: 0;
}
diagramframe {
justify-content: start;
}
:is(:root, diagramframe) > pentagon {
line-width: 1;
background-color: var(--opaque-background-color);
}
:is(:root, diagramframe) > pentagon > diagramtype {
font-weight: bold;
padding: 4 0 4 4;
}
:is(:root, diagramframe) > pentagon > stereotypes {
padding: 4 0 4 4;
}
:is(:root, diagramframe) > pentagon > name {
padding: 4;
}
:has(.item) compartment:first-child {
justify-content: start;
}
/* Relationships */
commentline,
c4dependency,
dependency,
interfacerealization,
include,
extend,
packageimport,
lifetime,
satisfy,
derivereqt,
trace,
verify,
refine {
dash-style: 7 5;
}
dependency[on_folded_interface = true],
interfacerealization[on_folded_interface = true] {
dash-style: 0;
}
/* General */
comment {
text-align: left;
vertical-align: top;
padding: 4 16 4 4;
}
comment stereotypes {
text-align: center;
}
comment body {
padding: 0;
}
diagram > icon {
padding: 4;
border-radius: 4;
}
diagram > type {
font-weight: bold;
}
metadata {
justify-content: stretch;
text-align: left;
}
metadata cell {
padding: 4;
}
metadata heading {
font-weight: bold;
font-style: normal;
font-size: small;
}
pentagon {
padding: 4;
justify-content: start;
text-align: left;
}
/* UML */
controlflow {
dash-style: 9 3;
}
objectnode > icon {
padding: 4 12;
}
decisionnode > type {
font-size: small;
}
proxyport > icon,
activityparameternode,
executionspecification {
background-color: var(--opaque-background-color);
}
partition {
padding: 4 12 4 12;
justify-content: stretch;
}
package {
padding: 24 12 4 12;
}
interaction {
justify-content: start;
}
activity {
padding: 4 12;
border-radius: 20;
justify-content: start;
}
activityparameternode {
padding: 4 12;
min-width: 120;
text-align: center;
}
action,
valuespecificationaction {
padding: 4 12;
border-radius: 15;
}
callbehavioraction {
padding: 4 24 4 12;
border-radius: 15;
}
sendsignalaction {
padding: 4 24 4 12;
}
accepteventaction {
padding: 4 12 4 24;
}
usecase {
padding: 4;
}
swimlane {
min-width: 150;
padding: 4 12 4 12;
justify-content: start;
white-space: normal;
}
association > end {
font-size: x-small;
padding: 4;
}
/* SysML */
requirement {
justify-content: start;
}
requirement text {
white-space: normal;
}
directedrelationshippropertypath {
dash-style: 7 5;
}
/* Classifiers */
compartment:first-child {
padding: 12 4;
}
compartment + compartment {
padding: 4;
min-height: 8;
text-align: left;
justify-content: start;
white-space: nowrap;
}
artifact compartment:first-child,
component compartment:first-child {
padding: 12 24 12 4;
}
state compartment:first-child {
padding: 4;
}
:has(.item),
:has(compartment + compartment),
:has(regions) {
justify-content: start;
}
regions {
justify-content: stretch;
}
region {
padding: 4;
min-height: 100;
justify-content: start;
text-align: left;
}
region + region {
dash-style: 7 3;
}
and name,
xor name,
intermediateevent name,
dormantevent name,
basicevent name,
houseevent name,
topevent name,
inhibit name,
conditionalevent name,
zeroevent name,
or name,
not name,
transferin name,
transferout name,
undevelopedevent name,
seq name,
majorityvote name,
unsafecontrolaction name,
operationalsituation name,
controlaction name,
interfaceblock name,
block name,
property name,
requirement name,
c4person name,
c4database name,
c4container name,
package name,
enumeration name,
interface name,
class name,
datatype name,
component name,
statemachine name,
usecase name,
actor name,
artifact name,
node name {
font-weight: bold;
}
name[isabstract] {
font-style: italic;
}
from {
font-size: x-small;
}
activity > :is(name, stereotypes) {
text-align: left;
}
compartment heading {
padding: 0 0 4 0;
font-size: x-small;
font-style: italic;
text-align: center;
}
operation[isabstract] {
font-style: italic;
}
attribute[isstatic],
operation[isstatic] {
text-decoration: underline;
}
property:not([aggregation="composite"]) {
dash-style: 7 5;
}
/* Attached */
:has(icon)[connected_side] {
text-align: right;
vertical-align: top;
}
:has(icon)[connected_side="left"] {
text-align: left;
}
:has(icon)[connected_side="bottom"] {
vertical-align: bottom;
}
/* C4 model */
c4container, c4person {
padding: 4 4 4 4;
}
c4database {
padding: 20 4 4 4;
}
:is(c4container, c4database, c4person):has(.item) {
justify-content: end;
}
:is(c4container, c4database, c4person):has(.item) > :is(name, technology) {
text-align: left;
}
c4dependency name {
max-width: 150;
}
:is(c4container, c4database, c4dependency, c4person) technology {
font-size: x-small;
}
:is(c4container, c4database, c4person) description {
padding: 4 4 0 4;
}