SVG-виджеты и tcl/tk-9.0

Работая над проектом »SVG-виджеты для tckl/tk», я с нетерпением ждал выхода не только релиза Tcl/Tk-9.0, но и выхода интерпретатора tclexecomp с его поддержкой. Релиз Tcl/Tk-9.0 появился в сентябре 2024 года, когда работа над проектом приближалась к завершению. После выхода релиза Tcl/Tk-9.0.0, сразу же появилось желание протестировать свой проект с новым интерпретатором, но я решил дождаться появления и интерпретатора tclexecomp с поддержкой нового релиза Tcl/Tk.
Время шло, на Хабре была выложена финальная статья про SVG-виджеты, а tclexecomp на базе Tcl/Tk-9.0 так и не появлялся. В настоящее время уже вышел второй релиз, а именно Tcl/Tk-9.0.1. И тогда в памяти всплыл мудрый совет Ивана Владимировича Мичурина:

Мы не можем ждать милостей от природы, взять их у неё — наша задача

Поскольку для проекта svgwidgets требуются и сторонние пакеты (tkpath, treectrl, xml), то было решено воспользоваться проектом BAWT.
Сборка проекта BAWT не вызвала затруднений:

sh Build-Linux.sh --tclversion 9.0.1 intel 64 Setup/Tcl_Basic.bawt update

Дальше всё просто, сначала запускается интерпретатор wish9, а в нем — графическая консоль tkcon:

$./wish9.0
% puts $tcl_patchLevel
9.0.1
% package require tkcon
2.7
#Запускаем графическую оболочку
% tkcon::Init -package Tk

Первое, что было интересно понять, это что такое частичная поддержка SVG-изображений в Tcl/Tk-9.0. Отметим, что эта поддержка включена в ядро Tcl/Tk и не требует никаких дополнительных пакетов:

В Tcl/Tk-9 теперь можно создавать изображения image типа photo и из xml-кода, описывающего векторное изображение. Полученное изображение можно использовать, например, как иконку в кнопках (параметр -image), так и размещать как фон в главном окне (toplevel) и/или фреймах (frame) (параметр -backgroundimage / -bgimg). Размеры изображений можно легко менять. Более того, теперь можно этими изображениями замостить как окна, так и фреймы (параметр -tile 1):

e2bf98327afd4313794215b690c95b42.png

Ниже приведен код, создавший это изображение:

#Создаём главное окно
toplevel .test 
#Размер главного окна
wm geometry .test 915x530
#Заголовок окна
wm title .test "SVG-файлы в tcl/tk-9"
#Создаём изображение image из svg-файла
set img1 [image create photo -file tile_fleur.svg -format svg]
#Создаём фрейм желтого цвета с изображением 
frame .test.f1 -background cyan -backgroundimage $img1
#Создаём изображение image из svg-файла увеличенное в два раза
set img2 [image create photo -file tile_fleur.svg -format {svg -scale 2}]
#Создаём фрейм с задивкой cyan с увеличенным изображением
frame .test.f2 -bg yellow -bgimg $img2
#Создаём изображение image из svg-файла шириной в 100 пикселей
set img3 [image create photo -file tile_fleur.svg -format {svg -scaletowidth 100}]
#Создаём фрейм с задивкой yellow с изображением шириной в 100 пикселей
frame .test.f3 -bg yellow -bgimg $img3
#Создаём изображение image из svg-файла шириной в натуральную величину
set img4 [image create photo -file tile_fleur.svg -format svg]
#Создаём фрейм с задивкой cyan и мозтим (-tile 1) этим изображением
frame .test.f4 -bg cyan -bgimg $img4 -tile 1
#Для размещения используем менеджер grid
grid .test.f1 .test.f2 -sticky wnse -padx 1m -pady 1m
grid .test.f3 .test.f4 -sticky wnse -padx 1m -pady 1m
#Фреймы могут изменять размеры
grid columnconfigure .test all -weight 1
grid rowconfigure .test all -weight 1

Если мы хотим, чтобы размеры изображения менялись одновременно с изменением размеров окна или фрейма, то можно настроить событие для соответствующего виджета (в нашем случае для фрейма .tect.f2):

#Размер изображения по размерц фрейма
bind .test.f2   {eval [subst "$img2 configure -format {svg -scaletowidth [winfo width %W]}"]}

При этом надо учитывать, что изменение размеров svg-изображений в Tcl/Tk происходит пропорционально исходным пропорциям. Это несколько противоречит векторной графике, где размеры меняются независимо друг от друга.

Отвлекаясь от основной темы, хочется сказать, что в Tcl/Tk-9 добавлены две простые, но очень полезные команды. Первая из них file home позволяет получить путь к домашнему каталогу пользователя, а вторая file tempdir создает временный каталог. Обе команды очень удобны для обеспечения платформонезависимости приложений.

Для проверки как ведут себя в среде Tck/Tk-9 SVG-виджеты добавляем в переменную auto_path путь к каталогу с пакетами проекта svgwidgets:

%lappend auto_path <каталог с пакетами svgwidgets>

После этого запускаем тест скрипт_button_PACK.tcl:

d32edb0a69ca06c65ce3b553be09ee6b.png

SVG-виджеты успешно отображались на экране. Можно было приступать к разработке tclexecomp на базе Tcl/Tk-9. И тут случилось непредвиденное, я что-то набрал в поле ввода, а затем решил отредактировать текст. Нажал клавишу Backspace, и … интерпретатор рухнул. Сначала я не придал значения, но после повторных попыток выяснилось, что что аналогичный эффект происходит и при нажатии клавиш Left и Right. Я подумал, что это могут быть мои косяки, но решил проверить работу этих клавиш на родных виджетах text, entry и ttk: entry, в которых для редактирования текста используются эти клавиши. И тут выяснялось, что нажатие на эти клавиши приводит к краху интерпретатора wish9. Первым порывом было написать письмо разработчикам Tcl/Tk, но прежде я решил посмотреть, как идут дела у них с подготовкой очередного релиза. И здесь меня ждал приятный сюрприз. В файле изменений для Tk-9.0.2 присутствует такая запись:

Backspace crashes 9.0 interpreter on FreeBSD.

Это было то, с чем столкнулся я. Правда, здесь речь идёт о FreeBSD, а у меня Linux, но я решил проверить. Скачал текущую версию Tcl/Tk-9.0.2 и собрал интерпретатор wish9. Проверка показала работоспособность клавиш и больше проблем с клавиатурой я не наблюдал.

Я не стал ждать выхода версии интерпретатора tclexecomp для Tcl/Tk-9, а решил собрать его самостоятельно (тем более что я это делал в первый раз и мне было просто интересно), с включением в него всех необходимых пакетов для работы с SVG-виджетами. Забегая вперед, скажу, что собранный интерпретатор со всеми пакетами svgwidgets под именем tclexecomp64_902_Lin64 добавлен в проект TkSVGWidgets на GitHub-е в папку tclexecomp902. Всем, кто будет тестировать проект, необходимо его скачать заново с GitHub.

Одновременно я узнал, что для работы с SVG-графикой в проекте BAWT есть и пакет tko, который создан, в том числе, и на базе пакета tkpath. Холст, создаваемый командой этого пакета tko: path мало чем отличается от холста tkp: canvas. Самое существенное с моей точки зрения отличие заключается в том, что холст tko: path в отличии от холста tkp: canvas не поддерживает растровую графику Tk. Второе отличие, это то, что в tko параметры matrix перелаются в виде списка из шести чисел, а в tkp — в виде списка из трех подсписков по два числа каждый. Добавим, что пакет tko поддерживает несколько виджетов, в том числе и виджет tko: graph для формирования различных графиков. Есть и виджет с всплывающей подсказкой tkp: tip:

501a2afa69b6a9ce8a854c9886a58a36.png

Было решено обеспечить поддержку SVG-виджетов на обоих типах холстов, в зависимости от того какой из пакетов доступен tko или tkpath. Все эти изменения внесены в пакеты svgwidgets, svg2can и tkfe_svg.
Дополнительно на github-е в проекте TkSVGWidgets создан подкаталог examples/CryptoArmPKCS_Test, в котором выложен исходный код криптографической утилиты для работы с электронной подписью cryptoarmpkcs.
Для её запуска достаточно запустить интерпретатор tclexecomp64_902_Lin64 для скрипта mainguipkcs_svg.tcl из каталога examples/CryptoArmPKCS:

tclexecomp64_902_Lin64 examples/CryptoArmPKCS_Test/mainguipkcs_svg.tcl

А если у кого есть, например, криптографический токен PKCS11 «ruToken-ECP» и библиотека к нему для Linux, то можно и поиграться и токеном:

0283342c9966e0b7fb7f4ac889b36e36.png

В заключении отметим, что теперь в tclexecomp для создания виртуальной файловой системы используется пакет cookfs, что не только значительно повысило быстродействие приложений, но и дало возможность напрямую работать с файлами, хранящимися в ней, с использованием команды file, включая команды file delete, file copy. По умолчанию виртуальная файловая система приложения монтируется на /cvfs. Если в виртуальной файловой системе хранится выполняемый файл, то для его выполнения создаётся временный каталог (команда file tempdir), в него копируется выполняемый файл из /cvfs (команда file copy), устанавливаются требуемые полномочия (команда file attributes <имя файла> -permissions 0755) и можно выполнять его (например, exec <имя файла>).
В целом Tcl/Tk-9 оставил приятное впечатление.

© Habrahabr.ru