В этой статье я покажу, что из себя представляет фреймворк 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
''';
Анонимные функции и захват переменных (захватываются адреса)
Дженерики (обобщенные типы)
С ними полезные вещи:
TValue - тип, схожий с Variant, но имеющий более удобные инструменты присваивания и получения значения (AsType<T>, Form<T>, ...)
Метод Default(T) - позволяет инициализировать переменную обобщенного типа значением "по умолчанию"
TArray<T> и конкатенация массивов
Это наиболее интересные, на мой взгляд, обновления за полтора года (и чуть раньше). 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.
Тут мы видим новый, кастомизируемый WelcomePage и в окне Create New пункт создания кроссплатформенного приложения - Multi-Device Application.
P.S. для WelcomePage мы можем создавать собственные представления и добавлять их на экран.
В этой статье будем использовать только пустое приложение - Blank Application. Выбираем его, после чего создается проект и открывается вкладка с первым модулем и дизайнером окна (всё как в VCL).
Быстро пройдемся по окну среды:
Выбор активной платформы и целевого устройства или эмулятора
Текущий отображаемый стиль (платформа) в дизайнере и вариант окна (интерфейс можно отдельно настроить под разные устройства/размеры экранов)
Управление проектом, тут мы можем выбрать или добавить платформу, указать конфигурацию сборки (Debug/Release), настроить пакеты и библиотеки (например, для Андроид) и использовать как навигацию по проекту.
Дизайнер окна
Дальше всё как обычно: Инспектор объектов, Дерево объектов, Палитра компонентов. Но, в целом, отличий не так много от VCL.
Теперь, приступим. Возьмем два простых элемента: кнопку и слой/контейнер (layout). Layout - это абсолютно пустой контрол, который обычно используется для разметки.
В Layout поместим другие элементы. Например, Label, Rectangle и Image. У Layout найдем свойство StyleName и зададим значение, например “my_button”. А у кнопки найдём свойство StyleLookup и укажем то же значение. Увидим следующую картину:
Наша кнопка стала отображаться так, как мы настроили наш Layout. В окне структуры (слева вверху) мы видим, что кнопка внутри себя не содержит ничего, но выглядит точно так же, как наполненный Layout, а элементы подчиняются выравниванию относительно размеров кнопки. Если мы зададим компоненту Label в слое свойство StyleName = “text”, то кнопка подхватит наличие этого элемента и будет отображать там свой текст. Помимо этого кнопка установит свои настройки текста (в данном случае выравнивание по центру) для Label.
Сейчас, если запустить приложение, кнопка будет “некликабельная”, т.к. все нажатия перехватывают помещенные в слой компоненты, но это можно исправить, установив им свойство HitTest в значение False.
Конечно, мы потеряли всю анимацию при наведении и при нажатии на кнопку, т.к. мы всеми этими действиями указали собственный стиль компонента, заменив стиль “по умолчанию”. В будущем мы это исправим.
Вот таким простым способом мы можем менять представление любого компонента. Но, оставлять на форме “шаблон” не очень удобно, по этому, добавим на форму компонент TStyleBook. Двойным кликом его откроем. Теперь мы можем вырезать наш шаблон с формы и вставить в структуру слева:
Добавленный компонент StyleBook нужно указать в одноименное свойство формы и наш стиль снова будет доступен кнопке, но уже из StyleBook.
StyleBook
Немного рассмотрим компонент StyleBook. Этот компонент имеет свой дизайнер.
Структура стилей - основной способ навигации по списку стилей. В этой структуре отображается StyleName, а не Name элемента
Целевая платформа стиля. Default - стиль по умолчанию для всех платформ.
Вариант отображения фона
Кнопка “Применить”. Её нужно не забывать нажимать.
Превью стиля (тут работают события мыши для стиля. Среда разработки подбирает контрол для превью по имени стиля)
В этом дизайнере мы можем настроить стиль нужного нам контрола почти так же, как в обычном дизайнере формы. Нам доступны все те же компоненты из палитры компонентов. Мы можем добавить также анимацию, эффекты и прочее.
Я добавил две анимации TFloatAnimation, которые анимируют свойство Opacity у фона bg: TRectangle. В анимации указаны триггеры (могут быть: IsMouseOver, IsPressed, IsOpen, IsChecked, isVisible, ...), на которые анимация будет срабатывать, само свойство и значения, в пределах которых будет изменяться свойство. Это значит, что при наведении мыши фон будет становиться чуть прозрачным, а при нажатии или отводе мыши возвращаться обратно.
Таким образом мы можем анимировать любые свойства контрола (Opacity, Margins, Paddings, Size, Position и т.д.). А помимо TFloatAnimation имеются следующие, готовые аниматоры:
TColorAnimation - анимация цвета интерполяцией
TGradientAnimation - анимирует цвета точек градиента (тоже интерполяцией)
TFloatAnimation - анимирует любое свойство с типом Single
TRectAnimation - комплексная анимация свойств с типом TRectF
TBitmapAnimation - анимация смены картинки
TBitmapListAnimation - покадровая анимация (как для Sprite)
TColorKeyAnimation/TFloatKeyAnimation - анимации с несколькими значениями по временным меткам
TPathAnimation - анимация, использующая в качестве значений PathData (как в SVG), т.е. позволяет описать траекторию изменения значения
Помимо подобных анимаций, существуют TransitionEffect анимации, использующие шейдеры. Позволяют анимировать смену или изменение растрового изображения различными способами, либо добавить какой-то переходной эффект. Такими анимациями можно реализовать смену StyleBook. Например, если имеется два StyleBook для темной и для светлой темы.
Один из моих старых примеров смены стиля через TransitionEffect.
Одна из идей FMX состоит в том, что любой контрол является контейнером и позволяет размещать внутри себя другие контролы. В этом мы уже убедились выше, поместив картинку и текст внутрь прямоугольника. Это позволяет нам создавать всевозможные контролы не прибегая к созданию их отдельно кодом и устанавливая в среду разработки в составе отдельного пакета.
Мы можем создавать стили в том числе и для элементов списка TListBox и дерева TTreeView, можем назначать разным элементам разные стили и размеры, что значит, что они могут быть сколько угодно сложным. Стилизации поддается абсолютно всё (на самом деле, почти всё, но по этому поводу уже созданы issue для исправления), что позволяет нам кардинально менять вид нашего приложения.
Пример
Продолжение следует.
UPD
Для тестов и своих проектов можно взять бесплатную коммьюнити версию, вышедшую на прошлой неделе тык