Кроссплатформенный фреймворк FireMonkey, Delphi

В этой статье я покажу, что из себя представляет фреймворк FireMonkey, на что он способен и в чем его основная идея. Подробно рассматривать технические отличия от VCL не буду, но некоторых вещей обязательно коснусь. Прошу не судить строго за статью, я постараюсь следить за ошибками в тексте и постараюсь донести свою мысль. Также, знаю, как сейчас относятся к Delphi, но тем не менее статья именно о нём. И первым делом, хотелось бы немного об этом поговорить. 

Несмотря на мнение большинства, язык развивается. Местами не так активно или не в том направлении, в котором некоторые ожидают, но мы регулярно видим обновления (~каждые 3 месяца).

Вот некоторые из последних и значимых обновлений:

Среда разработки

  • Поддержка LSP — Language Server Protocol

    • Это позволило создать плагин подсветки и анализа кода в VS Code

    • Новое API для плагинов IDE, работающих с кодом

  • Добавили HiDPI для среды. Обновили всю графику

    • Среда корректно может работать с HiDPI на разных мониторах с разным DPI

    • В среде можно тестировать HiDPI для созданных форм (вручную можно указать в дизайнере целевой DPI)

    • Некоторые компоненты VCL имеют возможность добавлять несколько вариантов растровой графики, которая будет выбираться в зависимости от масштабирования формы

  • Встроенный менеджер пакетов GetIt

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

    • Там же публикуются обновления среды (патчи)

  • Вынос вкладок с кодом или дизайнером в отдельные окна

  • SplitView редактора (этот и предыдущий пункт позволяют редактировать один и тот же файл параллельно)

  • Среда избавилась от WebView, который использовался для WelcomePage и справочной информации при работе с кодом, теперь используется движок на базе HTMLComponents

  • Обновление системы стилей VCL

    • VCL теперь может использовать разные «скины» для отдельных контролов

    • Стиль отображается не только в рантайм, но и в дизайн тайм

  • Затемнение кода, который сейчас не учитывается из-за условных директив

  • Подсветка блоков в редакторе, подсветка синтаксиса ассемблерных вкладок, подсветка ассемблера в отладочных окнах, направляющие в дизайнере

  • Цветовое разделение элементов в окне Сообщений, Дереве структуры кода, в поиске по методам и классам

  • Более отзывчивое и функциональное окно автозавершения кода и подсказок

  • Индикация внутри скроллбара (места ошибок, подсказок, варнингов, изменений и т.д.)

  • Стилизация IDE и режимы темный/светлый

  • Focus Mode — режим фокусировки на написании кода (по сути, просто «F11» для редактора кода)

Язык

var MyInt: integer := 1;
...
for var i := 0 to 10 do ...
var i := 1;
...
for var Item in List do
...
for var Control in Layout.Controls do 
...
var text := GetText();
...
var Proc := 
  procedure(i: integer)
  begin
    ...
  end;
Proc(123);
  • Директива inline для оптимизации вызовов методов

  • Классовые конструкторы/деструкторы

  • Конструкторы/деструкторы записей (Managed Records)

  • Поддержка инструкций AVX-512

  • Некоторые мелочи по типу записи числа в бинарном виде (%101110), или с разделителями тысячных (1_000_000)

  • Мультистроки (ссылка)

var Query := '''
  SELECT * FROM table
  WHERE field = :my_value
  ''';
  • Анонимные функции и захват переменных (захватываются адреса)

  • Дженерики (обобщенные типы)

  • TArray и конкатенация массивов

Это наиболее интересные, на мой взгляд, обновления за полтора года (и чуть раньше). Patch Notes на самом деле включает в себя списки фиксов (до нескольких сотен за раз), обновления RTL и т.д.

Ещё ссылки:
Изменения в D12
Изменения в остальных версиях

FireMonkey (FMX)

Данный фреймворк позволяет создавать графические приложения под следующие платформы: MS Windows (32/64bit), Linux (64bit), MacOS (64bit, ARM 64bit), Android (32/64bit), iOS (64bit, simulator ARM 64bit). А прежде чем начнем рассматривать FMX, давайте посмотрим на современную версию среды разработки Delphi.

RAD Studio Delphi 12

RAD Studio Delphi 12

Тут мы видим новый, кастомизируемый WelcomePage и в окне Create New пункт создания кроссплатформенного приложения — Multi-Device Application.
P.S. для WelcomePage мы можем создавать собственные представления и добавлять их на экран.

Шаблоны Multi-Device Application

Шаблоны Multi-Device Application

В этой статье будем использовать только пустое приложение — Blank Application. Выбираем его, после чего создается проект и открывается вкладка с первым модулем и дизайнером окна (всё как в VCL). 

40a7441b9a7864aa5388db193b54f596.png

Быстро пройдемся по окну среды:

  1. Выбор активной платформы и целевого устройства или эмулятора

  2. Текущий отображаемый стиль (платформа) в дизайнере и вариант окна (интерфейс можно отдельно настроить под разные устройства/размеры экранов)

  3. Управление проектом, тут мы можем выбрать или добавить платформу, указать конфигурацию сборки (Debug/Release), настроить пакеты и библиотеки (например, для Андроид) и использовать как навигацию по проекту.

  4. Дизайнер окна

Дальше всё как обычно: Инспектор объектов, Дерево объектов, Палитра компонентов. Но, в целом, отличий не так много от VCL.

Теперь, приступим. Возьмем два простых элемента: кнопку и слой/контейнер (layout). Layout — это абсолютно пустой контрол, который обычно используется для разметки.

1918079668e960afdae6ffba19791473.png

В Layout поместим другие элементы. Например, Label, Rectangle и Image. У Layout найдем свойство StyleName и зададим значение, например «my_button». А у кнопки найдём свойство StyleLookup и укажем то же значение. Увидим следующую картину:

59c49ebcd46aee81417942adc90a0ea2.png

Наша кнопка стала отображаться так, как мы настроили наш Layout. В окне структуры (слева вверху) мы видим, что кнопка внутри себя не содержит ничего, но выглядит точно так же, как наполненный Layout, а элементы подчиняются выравниванию относительно размеров кнопки. Если мы зададим компоненту Label в слое свойство StyleName = «text», то кнопка подхватит наличие этого элемента и будет отображать там свой текст. Помимо этого кнопка установит свои настройки текста (в данном случае выравнивание по центру) для Label

Сейчас, если запустить приложение, кнопка будет «некликабельная», т.к. все нажатия перехватывают помещенные в слой компоненты, но это можно исправить, установив им свойство HitTest в значение False.
Конечно, мы потеряли всю анимацию при наведении и при нажатии на кнопку, т.к. мы всеми этими действиями указали собственный стиль компонента, заменив стиль «по умолчанию». В будущем мы это исправим.

Вот таким простым способом мы можем менять представление любого компонента. Но, оставлять на форме «шаблон» не очень удобно, по этому, добавим на форму компонент TStyleBook. Двойным кликом его откроем. Теперь мы можем вырезать наш шаблон с формы и вставить в структуру слева:

Окно дизайнера стиля (StyleBook)

Окно дизайнера стиля (StyleBook)

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

StyleBook

Немного рассмотрим компонент StyleBook. Этот компонент имеет свой дизайнер.

9f674663d2b118781d1a3fa98abc29d7.png

  1. Структура стилей — основной способ навигации по списку стилей. В этой структуре отображается StyleName, а не Name элемента

  2. Целевая платформа стиля. Default — стиль по умолчанию для всех платформ.

  3. Вариант отображения фона

  4. Кнопка «Применить». Её нужно не забывать нажимать.

  5. Превью стиля (тут работают события мыши для стиля. Среда разработки подбирает контрол для превью по имени стиля)

В этом дизайнере мы можем настроить стиль нужного нам контрола почти так же, как в обычном дизайнере формы. Нам доступны все те же компоненты из палитры компонентов. Мы можем добавить также анимацию, эффекты и прочее. 

Анимация свойств

Анимация свойств

Я добавил две анимации TFloatAnimation, которые анимируют свойство Opacity у фона bg: TRectangle. В анимации указаны триггеры (могут быть: IsMouseOver, IsPressed, IsOpen, IsChecked, isVisible, …), на которые анимация будет срабатывать, само свойство и значения, в пределах которых будет изменяться свойство. Это значит, что при наведении мыши фон будет становиться чуть прозрачным, а при нажатии или отводе мыши возвращаться обратно.

Таким образом мы можем анимировать любые свойства контрола (Opacity, Margins, Paddings, Size, Position и т.д.). А помимо TFloatAnimation имеются следующие, готовые аниматоры:

7c7445a220a45855878a00fd6bf8e17d.png

TColorAnimation — анимация цвета интерполяцией
TGradientAnimation — анимирует цвета точек градиента (тоже интерполяцией)
TFloatAnimation — анимирует любое свойство с типом Single
TRectAnimation — комплексная анимация свойств с типом TRectF
TBitmapAnimation — анимация смены картинки
TBitmapListAnimation — покадровая анимация (как для Sprite)
TColorKeyAnimation/TFloatKeyAnimation — анимации с несколькими значениями по временным меткам
TPathAnimation — анимация, использующая в качестве значений PathData (как в SVG), т.е. позволяет описать траекторию изменения значения

6c501b326e52eb0335ca20e3dd785330.png

Помимо подобных анимаций, существуют TransitionEffect анимации, использующие шейдеры. Позволяют анимировать смену или изменение растрового изображения различными способами, либо добавить какой-то переходной эффект. Такими анимациями можно реализовать смену StyleBook. Например, если имеется два StyleBook для темной и для светлой темы.

Один из моих старых примеров смены стиля через TransitionEffect.

Одна из идей FMX состоит в том, что любой контрол является контейнером и позволяет размещать внутри себя другие контролы. В этом мы уже убедились выше, поместив картинку и текст внутрь прямоугольника. Это позволяет нам создавать всевозможные контролы не прибегая к созданию их отдельно кодом и устанавливая в среду разработки в составе отдельного пакета.

Мы можем создавать стили в том числе и для элементов списка TListBox и дерева TTreeView, можем назначать разным элементам разные стили и размеры, что значит, что они могут быть сколько угодно сложным. Стилизации поддается абсолютно всё (на самом деле, почти всё, но по этому поводу уже созданы issue для исправления), что позволяет нам кардинально менять вид нашего приложения.

Пример

Помощник в создании десериализации Json to Delphi в стиле MaterialDesign 3

Помощник в создании десериализации Json to Delphi в стиле MaterialDesign 3

Помощник в создании десериализации Json to Delphi в стиле WinUI 3 + Mica оформление окна

Помощник в создании десериализации Json to Delphi в стиле WinUI 3 + Mica оформление окна

Продолжение следует

© Habrahabr.ru