4.5.7.1.2. Расширение существующей темы

Существующая в платформе тема может быть изменена в проекте приложения. В измененной теме можно сделать следующее:

  • Изменить изображения для фирменного стиля.

  • Добавить изображения для использования в визуальных компонентах.

  • Создать новые стили и использовать их в атрибутах stylename визуальных компонентов. Для этого требуется знание CSS.

  • Изменить существующие в платформе стили компонентов.

  • Изменить общие параметры, такие как цвет фона, отступы, промежутки и т.д.

Тема описывается в файлах SCSS. Для изменения (расширения) темы в проекте необходимо создать специальную файловую структуру в модуле web. Это удобно сделать с помощью CUBA Studio: откройте секцию Project properties и нажмите ссылку Create theme extension. В диалоговом окне выберите тему, которую вы хотите расширить. В результате в проекте будет создана следующая структура каталогов (для расширения темы Halo):

themes/
  halo/
    branding/
      app-icon-login.png
      app-icon-menu.png
    favicon.ico
    halo-ext-defaults.scss
    halo-ext.scss
    styles.scss

Кроме того, скрипт сборки build.gradle будет дополнен задачей buildScssThemes, автоматически запускаемой при сборке модуля web. Опциональная задача deployThemes может быть использована для быстрого применения изменений в темах на работающем приложении.

Изменение фирменного стиля

Можно настроить некоторые параметры фирменного стиля (branding): пиктограммы и заголовки окна логина и главного окна, пиктограмму вебсайта favicon.ico.

Для использования собственных изображений, замените соответствующие файлы в каталоге modules/web/themes/halo/branding.

Чтобы задать заголовки главного окна, окна логина и текст приглашения окна логина, в CUBA Studio откройте Project propertiesEdit и нажмите кнопку Branding внизу страницы. Используйте соответствующие ссылки для задания заголовков окон и текста приглашения окна логина.

Данные параметры сохраняются в главном пакете сообщений модуля gui (то есть в файле modules/gui/<root_package>/gui/messages.properties и его вариантах для разных локалей). Использование пакетов сообщений дает возможность использовать разные файлы изображений для разных локалей пользователей. Пример содержимого файла messages.properties:

application.caption = MyApp
application.logoImage = branding/myapp-menu.png

loginWindow.caption = MyApp Login
loginWindow.welcomeLabel = Welcome to MyApp!
loginWindow.logoImage = branding/myapp-login.png

Путь к favicon.ico указывать не нужно, он должен обязательно находится в корне каталога с именем темы.

Добавление изображений

В расширенную тему можно также добавить файлы изображений для использования в свойствах icon действий и визуальных компонентов, например Button.

Например, чтобы добавить расширение темы Halo пиктограмму, достаточно в описанный выше каталог modules/web/themes/halo добавить файл изображения (желательно в некоторый подкаталог):

themes/
  halo/
    images/
      address-book.png

После этого можно использовать эту пиктограмму, указывая в свойстве icon путь к ней относительно каталога темы:

<action id="adresses"
        icon="images/address-book.png"/>

Вместо файлов изображений для пиктограмм можно использовать элементы шрифта Font Awesome. Для этого достаточно указать в свойстве icon имя нужной константы перечисления com.vaadin.server.FontAwesome с префиксом font-icon:, например:

<action id="adresses"
        icon="font-icon:BOOK"/>
Добавление изображений из других библиотек шрифтов

Для более тонкой настройки расширенной темы можно создать изображения, встроенные в шрифты, либо использовать готовые внешние библиотеки изображений.

Создайте в модуле web класс enum, реализующий интерфейс com.vaadin.server.FontIcon, в который поместите новые изображения:

import com.vaadin.server.FontIcon;
import com.vaadin.server.GenericFontIcon;

public enum IcoMoon implements FontIcon {

    HEADPHONES(0XE900),
    SPINNER(0XE905);

    public static final String FONT_FAMILY = "IcoMoon";
    private int codepoint;

    IcoMoon(int codepoint) {
        this.codepoint = codepoint;
    }

    @Override
    public String getFontFamily() {
        return FONT_FAMILY;
    }

    @Override
    public int getCodepoint() {
        return codepoint;
    }

    @Override
    public String getHtml() {
        return GenericFontIcon.getHtml(FONT_FAMILY, codepoint);
    }

    @Override
    public String getMIMEType() {
        throw new UnsupportedOperationException(FontIcon.class.getSimpleName()
                + " should not be used where a MIME type is needed.");
    }

    public static IcoMoon fromCodepoint(final int codepoint) {
        for (IcoMoon f : values()) {
            if (f.getCodepoint() == codepoint) {
                return f;
            }
        }
        throw new IllegalArgumentException("Codepoint " + codepoint
                + " not found in IcoMoon");
    }
}

Добавьте новые стили и файлы шрифта в расширение темы. Рекомендуется создать отдельную папку fonts в главном каталоге расширения темы, например, modules/web/themes/halo/com.company.demo/fonts. Поместите в неё стили и файлы шрифтов в своих собственных подпапках, например, fonts/icomoon. Файлы шрифта включают в себя набор следующих расширений: .eot, .svg, .ttf, .woff. Использованный в этом примере набор шрифтов icomoon из открытой библиотеки представлен в виде 4 файлов: icomoon.eot, icomoon.svg, icomoon.ttf, icomoon.woff, которые используются совместно.

Создайте файл стилей, в который включите @font-face и CSS класс со стилем для изображения. Ниже представлен пример файла icomoon.scss, где имя класса IcoMoon соответствует значению, возвращаемому методом FontIcon#getFontFamily:

@mixin icomoon-style {
    /* use !important to prevent issues with browser extensions that change fonts */
    font-family: 'icomoon' !important;
    speak: none;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    line-height: 1;

    /* Better Font Rendering =========== */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

@font-face {
    font-family: 'icomoon';
    src:url('icomoon.eot?hwgbks');
    src:url('icomoon.eot?hwgbks#iefix') format('embedded-opentype'),
        url('icomoon.ttf?hwgbks') format('truetype'),
        url('icomoon.woff?hwgbks') format('woff'),
        url('icomoon.svg?hwgbks#icomoon') format('svg');
    font-weight: normal;
    font-style: normal;
}

.IcoMoon {
    @Include icomoon-style;
}

Подключите файл стилей шрифта в halo-ext.scss или другой файл расширения данной темы:

@import "fonts/icomoon/icomoon";

Создайте новый класс App.java, расширяющий DefaultApp, в корневом пакете модуля web и зарегистрируйте его в web-spring.xml в качестве бина cuba_App, чтобы переопределить бин центрального класса инфраструктуры приложения, например:

<bean name="cuba_App" class="com.company.sample.web.App" scope="prototype"/>

Зарегистрируйте в App.java новый алиас для изображений:

import com.haulmont.cuba.web.DefaultApp;
import com.haulmont.cuba.web.gui.components.WebComponentsHelper;

public class App extends DefaultApp {
    static {
        WebComponentsHelper.registerFontIcon("ico-moon-icon", IcoMoon.class);
    }
}

Теперь вы можете использовать изображения по прямой ссылке на класс и элемент enum в XML-дескрипторе экрана:

<button caption="Headphones" icon="ico-moon-icon:HEADPHONES"/>

или в контроллере Java:

spinnerBtn.setIcon("ico-moon-icon:SPINNER");

В результате, новые изображения добавились к кнопкам:

add icons
Создание новых стилей

Рассмотрим пример установки желтого цвета фона для поля, отображающего название заказчика.

В XML-дескрипторе экрана определен компонент FieldGroup:

<fieldGroup id="fieldGroup" datasource="customerDs">
    <field id="name"/>
    <field id="address"/>
</fieldGroup>

Элементы field компонента FieldGroup не имеют атрибута stylename, поэтому необходимо задать имя стиля в контроллере:

@Named("fieldGroup.name")
private TextField nameField;

@Override
public void init(Map<String, Object> params) {
    nameField.setStyleName("name-field");
}

В файле halo-ext.scss добавьте определение нового стиля в mixin halo-ext:

@import "../halo/halo";

@mixin halo-ext {
  @include halo;

  .name-field {
    background-color: lightyellow;
  }
}

После пересборки проекта поля будут выглядеть следующим образом:

gui themes fieldgroup 1
Изменение существующих стилей компонентов

Для изменения параметров стиля существующих компонентов необходимо добавить соответствующий код CSS в mixin halo-ext файла halo-ext.scss. Например, для того, чтобы пункты главного меню отображались жирным шрифтом, содержимое файла halo-ext.scss должно быть следующим:

@import "../halo/halo";

@mixin halo-ext {
  @include halo;

  .v-menubar-menuitem-caption {
      font-weight: bold;
  }
}
Изменение общих параметров

Темы содержат переменные SCSS, которые управляют цветом фона, размерами компонентов, отступами и пр.

Рассмотрим пример расширения темы Halo, так как она основана на теме Valo фреймворка Vaadin, и предоставляет максимальные возможности адаптации.

Файл themes/halo/halo-ext-defaults.scss предназначен для размещения в нем переменных темы. Большинство переменных Halo соответствует описанным в документации по Valo, ниже приведены основные:

$v-background-color: #fafafa;        /* component background colour */
$v-app-background-color: #e7ebf2;    /* application background colour */
$v-panel-background-color: #fff;     /* panel background colour */
$v-focus-color: #3b5998;             /* focused element colour */
$v-error-indicator-color: #ed473b;   /* empty required fields colour */

$v-line-height: 1.35;                /* line height */
$v-font-size: 14px;                  /* font size */
$v-font-weight: 400;                 /* font weight */
$v-unit-size: 30px;                  /* base theme size, defines the height for buttons, fields and other elements */

$v-font-size--h1: 24px;              /* h1-style Label size */
$v-font-size--h2: 20px;              /* h2-style Label size */
$v-font-size--h3: 16px;              /* h3-style Label size */

/* margins for containers */
$v-layout-margin-top: 10px;
$v-layout-margin-left: 10px;
$v-layout-margin-right: 10px;
$v-layout-margin-bottom: 10px;

/* spacing between components in a container (if enabled) */
$v-layout-spacing-vertical: 10px;
$v-layout-spacing-horizontal: 10px;

/* basic table dimensions */
$v-table-row-height: 30px;
$v-table-header-font-size: 13px;
$v-table-cell-padding-horizontal: 7px;

/* input field focus style */
$v-focus-style: inset 0px 0px 5px 1px rgba($v-focus-color, 0.5);
/* required fields focus style */
$v-error-focus-style: inset 0px 0px 5px 1px rgba($v-error-indicator-color, 0.5);

/* animation for elements is enabled by default */
$v-animations-enabled: true;
/* popup window animation is disabled by default */
$v-window-animations-enabled: false;

/* inverse header is controlled by cuba.web.useInverseHeader property */
$v-support-inverse-menu: true;

/* show "required" indicators for components */
$v-show-required-indicators: false !default;

Пример содержимого файла halo-ext-defaults.scss для темы с темным фоном и немного уменьшенными отступами:

$v-background-color: #444D50;

$v-font-size--h1: 22px;
$v-font-size--h2: 18px;
$v-font-size--h3: 16px;

$v-layout-margin-top: 8px;
$v-layout-margin-left: 8px;
$v-layout-margin-right: 8px;
$v-layout-margin-bottom: 8px;

$v-layout-spacing-vertical: 8px;
$v-layout-spacing-horizontal: 8px;

$v-table-row-height: 25px;
$v-table-header-font-size: 13px;
$v-table-cell-padding-horizontal: 5px;

$v-support-inverse-menu: false;
Изменение заголовка приложения

Тема Halo поддерживает свойство приложения cuba.web.useInverseHeader, управляющее цветом заголовка приложения. По умолчанию это свойство установлено в true, что задает темный (инверсный) заголовок. В проекте можно не изменяя темы сделать заголовок светлым, установив данное свойство в false.