Таблиці стилів

Починаючи з Gaphor 2.0, діаграми можуть мати інший вигляд за допомогою таблиць стилів. Таблиці стилів використовують синтаксис каскадних таблиць стилів (CSS). CSS використовується для опису представлення документа, написаного мовою розмітки, і найчастіше використовується з HTML для веб-сторінок.

На [домашній сторінці W3C CSS] (https://www.w3.org/Style/CSS/Overview.en.html) CSS описано так:

Каскадні таблиці стилів (CSS) — це простий механізм додавання стилю (наприклад, шрифтів, кольорів, інтервалів) до веб-документів.

Однак його застосування виходить далеко за межі веб-документів. Gaphor використовує CSS для надання елементів стилів елементам на діаграмах. CSS дозволяє нам, користувачам Gaphor, змінювати візуальний вигляд наших діаграм. Стилі кольорів і ліній можна змінювати, щоб полегшити читання діаграм.

Оскільки ми маємо справу з діаграмою, а не з HTML-документом, деякі функції CSS були пропущені.

Стиль є частиною моделі, тому всі, хто працює над моделлю, матимуть однаковий стиль. Щоб редагувати стиль, натисніть кнопку сторінки інструментів у верхньому правому куті в gaphor:

Кнопка для доступу до коду стилю

Ось простий приклад того, як змінити колір фону класу:

class {
  background-color: beige;
}
фон бежевий

Або змінити колір компонента, лише якщо він вкладений у вузол:

node component {
  background-color: skyblue;
}
вкладений компонент

Сама діаграма також виражається як вузол CSS. Визначити «темний» стиль досить просто:

diagram {
  background-color: #343131;
}

* {
  color: white;
  text-color: white;
}
темний стиль

Тут ви вже бачите перший користувацький атрибут: text-color. Ця властивість дозволяє керувати кольором тексту, намальованого на елементі. color використовується для ліній (штрихів), які складають макет елемента діаграми.

Підтримувані селектори

Оскільки ми маємо справу з діаграмами та моделями, нам не потрібні всі функції CSS. Нижче ви знайдете короткий перелік усіх функцій CSS, які підтримує Gaphor.

*

Усі елементи на схемі, включаючи саму схему.

компонент вузла

Будь-який елемент компонента, який є нащадком вузла.

вузол > компонент

Елемент компонента, який є дочірнім елементом вузла.

.item

Each diagram item has a class «item» assigned. This makes it easy to differentiate them from e.g. name elements.

узагальнення[тема]

Елемент узагальнення з присутнім підметом.

клас[name=Foo]

Клас з назвою «Foo».

діаграма[name^=draft]

Діаграма з назвою, що починається на «чернетка».

діаграма[name$=чернетка]

Діаграма з назвою закінчується на «чернетка».

діаграма[назва*=чернетка]

Діаграма з назвою, що містить текст «чернетка».

діаграма[назва~=чорновий елемент]

Діаграма з назвою «чернетка» або «елемент».

діаграма[назва|=чернетка]

Діаграма з назвою «чернетка» або починається з «чернетка-«.

:focus

Фокусований елемент. Інші псевдокласи:

  • вибрані елементи :active

  • :hover для елемента під мишею

  • :drop, якщо елемент перетягується і може бути скинутий на цей елемент

  • :disabled, якщо елемент неактивний під час руху ручки

:порожній

Вузол, який не містить дочірніх вузлів на діаграмі.

:корінь

Посилається на саму діаграму.

Це стосується лише діаграми

:перша дитина

Вузол є першим елементом у групі однорідних елементів.

:has()

Елемент містить будь-який із наданих селекторів.

наприклад node:has(component): вузол, що містить елемент компонента.

:is()

Зіставте будь-який із запропонованих селекторів.

наприклад :is(node, subsystem) > component: вузол або підсистема.

:not()

Відмінити селектор.

наприклад :not([тема]): будь-який елемент, який не має «теми».

::після

Додайте додатковий вміст після тексту. Підтримується лише властивість content.

  • Офіційна специфікація селекторів атрибутів CSS3.

  • Gaphor надає селектор атрибутів |= для повноти. Хоча це, ймовірно, не дуже корисно в цьому контексті.

  • Зауважте, що Gaphor CSS не підтримує ідентифікатори для елементів діаграми, тому синтаксис CSS для ідентифікаторів (#some-id) не використовується. Також наразі не підтримується синтаксис класу (.some-class).

Властивості стилю

Gaphor підтримує підмножину властивостей CSS та деякі специфічні властивості Gaphor. Інтерпретатор таблиць стилів відносно простий. Всі ширини, висоти та розміри вимірюються у пікселях. Ви не можете використовувати складні оголошення стилів, такі як властивість font в HTML/CSS, яка може містити сімейство шрифтів, розмір, вагу.

Деякі властивості успадковуються від батьківського стилю. Батько часто є діаграмою. Коли ви встановлюєте color`` або font-familyнаdiagram`, вони поширюватимуться на елементи, які містяться на схемі.

Кольори

background-color

Приклади:

background-color: azure;

background-color: rgb(255, 255, 255);

background-color: hsl(130, 95%, 10%);

color

Колір, який використовується для ліній. (успадковано)

text-color

Колір для тексту. (успадковано)

Застаріло починаючи з версії 2.23.0: Використовуйте колір, якщо це можливо.

opacity

Коефіцієнт непрозорості кольору (0,0 - 1,0), застосований до всіх кольорів.

  • Колір може бути будь-яким CSS3 колірним кодом, як описано в документації CSS. Gaphor підтримує всі позначення кольорів: rgb(), rgba(), hsl(), hsla(), Hex-код (#ffffff) та назви кольорів.

Текст і шрифти

font-family

Одна назва шрифту (наприклад, sans, serif, courier). (успадковано)

font-size

Абсолютний розмір (наприклад, 14) або значення розміру (наприклад, small). (успадковано)

font-style

Або нормальний або курсив. (успадковано)

font-weight

Або нормальний або жирний. (успадковано)

text-align

Або ліворуч, центр, право. (успадковано)

text-decoration

Або немає або підкреслення.

vertical-align

Вертикальне вирівнювання тексту.

Або верх, середина або низ.

vertical-spacing

Установіть вертикальний інтервал для піктограм (акторів, початкового стану).

Приклад: vertical-spacing: 4.

white-space

Змініть поведінку переносу рядка для тексту. (успадковано)

  • font-family може бути лише однією назвою шрифту, а не списком (резервних) імен, як це використовується для HTML.

  • font-size може бути числом або абсолютними значеннями розміру CSS. Підтримуються лише значення «x-small», «small», «medium», «large» і «x-large».

Креслення та інтервали

border-radius

Радіус для прямокутників: border-radius: 4.

dash-style

Стиль для пунктирних ліній: dash-style: 7 5.

justify-content

Вирівнювання вмісту для коробок.

Або початок, кінець, центр або розтягнути.

line-style

Або нормальний, або недбалий [фактор].

line-width

Встановіть ширину ліній: line-width: 2. (успадковано)

min-height

Установіть мінімальну висоту для елемента: min-height: 50.

min-width

Установіть мінімальну ширину для елемента: min-width: 100.

max-width

Встановіть максимальну ширину (тільки для текстових полів): max-width: 100.

padding

Відступ у стилі CSS (верхній, правий, нижній, лівий).

Приклад: padding: 3 4.

  • padding визначається цілими числами в діапазоні від 1 до 4. Одиниці (px, pt, em) використовувати не потрібно. Усі значення вказані у піксельних відстанях.

  • dash-style — це список чисел (рядок, проміжок, лінія, прогалина, …)

  • line-style має ефект лише тоді, коли визначено на diagram. Коефіцієнт неохайності може бути встановлений в діапазоні від -2 до 2.

Псевдо елементи

Наразі підтримується лише псевдоелемент ::after.

content

Додатковий вміст, який буде показано після тексту.

Змінні

Починаючи з Gaphor 2.16.0, ви можете використовувати змінні CSS у своїх таблицях стилів.

Це дозволяє визначати часто використовувані значення більш загальним способом. Подумайте про такі речі, як стиль штрихів і кольори.

Функція var() має деякі обмеження:

  • Значення не можуть мати значення за умовчанням.

  • Змінні не можуть мати значення змінної.

Приклад:

diagram {
  --bg-color: whitesmoke;
  background-color: var(--bg-color);
}

diagram[diagramType=sd] {
  --bg-color: rgb(200, 200, 255);
}

Усі схеми мають білий фон. Діаграми послідовностей отримують блакитний фон.

Медіа запити

Gaphor підтримує темні та світлі режими, починаючи з версії 2.16.0. Темні та світлі колірні схеми використовуються виключно для редагування на екрані. Під час експорту зображень застосовується лише типова схема кольорів. Кольорові схеми можна визначити за допомогою запитів @media. Підтримується офіційний запит prefers-color-scheme = dark, а також більш зручний 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;
  }
}

Стилі діаграм

Для діаграми можна визначити лише декілька властивостей, а саме background-color та line-style. Стиль діаграми визначається окремо від стилів елементів діаграми. Таким чином, ви можете задати колір тла саме для діаграм. Стиль ліній може бути звичайними прямими лініями або більш грайливим «недбалим» стилем. Для недбалого стилю можна задати опціональний коефіцієнт хиткості, щоб встановити рівень хиткості лінії. 0.5 - значення за замовчуванням, 0.0 - пряма лінія. Значення має бути між -2.0 і 2.0. Значення від 0.0 до 0.5 дають тонкий ефект.

Елементи моделі CSS

Gaphor має багато модельних елементів. Як можна дізнатися, який предмет потрібно стилізувати?

Gaphor стилізує тільки ті елементи, які є в моделі, тому ви повинні чітко вказувати їхні імена. Наприклад: Component успадковує від Class в UML-моделі, але зміна кольору для Class не змінює його для Component.

Якщо ви наведете вказівник миші на кнопку панелі інструментів (нижня ліва частина), з’явиться спливаюче вікно з назвою елемента та його ярликом. Як правило, ви можете використовувати назву компонента, склеєну з назвою у таблиці стилів. До компонента можна звертатися як до component, до використовуваного регістру - як до usecase. Відповідність імен не залежить від регістру. За замовчуванням імена CSS пишуться у нижньому регістрі.

Однак, оскільки імена елементів CSS походять від імен, які використовуються в Gaphor, є кілька винятків.

Профіль

Група

Елемент

елемент CSS

*

*

назва елемента

назва елемента без пробілів

наприклад клас, випадок.

UML

Заняття

всі Асоціації

association

UML

Компоненти

Пристрій/вузол

node

UML

Дії

Вузол рішення/злиття

decisionnode

UML

Дії

Розгалуження/Вузол приєднання

forknode

UML

Дії

Свімлане

partition

UML

Взаємодії

Рефлексивне повідомлення

message

UML

Держави

Початковий псевдостан

pseudostate

UML

Держави

Історія Псевдодержава

pseudostate

UML

Профілі

Метаклас

class

Модель C4

Модель C4

Особа

c4person

Модель C4

Модель C4

Програмна система

c4container[type="Software System"]

Модель C4

Модель C4

Компонент

c4container[type="Component"]

Модель C4

Модель C4

Контейнер

c4container[type="Container"]

Модель C4

Модель C4

Контейнер: база даних

c4database

SysML

Блоки

ValueType

datatype

SysML

Блоки

Примітивний

datatype

SysML

Вимоги

Вивести вимогу

derivedreq

RAAML

FTA

будь-який І/АБО/… ворота

and, or, etc.

Ідеї

Ось кілька ідей, які виходять за межі зміни кольору чи шрифту. За допомогою наступних прикладів ми заглибимося в структуру моделі Gaphor, щоб відкрити користувачам більше інформації.

Щоб створити власний вираз, ви можете скористатися консоллю (Іконка меню → Інструменти → Консоль). Напишіть нам на Gitter, і ми будемо раді допомогти вам.

Пакет чернеток

Всі схеми в пакеті «Чернетки» повинні бути намальовані неакуратними лініями:

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 */
}
чернетковий стиль

Обгортання довгих атрибутів, операцій і стереотипних значень

Іноді значення атрибутів можуть бути довгими. За замовчуванням Gaphor не обгортає текст. Якщо ви хочете, ви можете додати цей невеликий фрагмент, щоб обернути текст для довгих атрибутів у класах. Звісно, ви також можете застосувати його до інших типів.

class * {
 white-space: normal;
}
довгий атрибут wrap

Беззв’язкові відносини

Всі елементи на діаграмі, які не підкріплені елементами моделі, повинні бути намальовані темно-червоним кольором. Це може бути використано для виявлення не дуже добре пов’язаних зв’язків, таких як Узагальнення, Реалізація та Залежність. Ці елементи будуть підкріплені елементом моделі лише після того, як ви з’єднаєте обидва кінці лінії. Це правило виключає прості елементи, такі як лінії та рамки, які ніколи не матимуть підкріплення у вигляді елемента моделі.

:not(:is(:root, line, box, ellipse, commentline))[subject=""] {
  color: firebrick;
}
безсполучникові відносини

Лінії Solid Control Flow

У Gaphor лінії Control Flow відповідають стилю SysML: пунктирні. Якщо ви бажаєте або маєте суворо дотримуватися офіційних специфікацій UML, ви можете просто зробити ці суцільні лінії.

controlflow {
  dash-style: 0;
}
керування потоком

Усі виділення нот

Усі коментарі, що починаються з фрази «todo», можуть бути виділені іншим кольором, призначеним для користувача. Це може бути використано для того, щоб нагадати собі, що вам потрібно виконати додаткову роботу, щоб завершити діаграму.

comment[body^="TODO"] {
  background-color: skyblue;
}
виділена нотатка про завдання

Підкресліть абстрактні класи та операції

Можливо, використаний курсивний шрифт недостатньо помітний, щоб розрізнити конкретні та абстрактні класи або операції. Щоб це виправити, ми перевіряємо, чи встановлено для елемента атрибут isAbstract:

:is(name, operation)[isabstract]::after {
  content: " {abstract}"
}
підкреслити абстрактні елементи

Таблиця стилів системи

/* 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;
}