Методы мастерской и пульта
Что окно мастерской берёт у платформы и чем её зовёт, методы функции ui и функции пульта canvas: документ пульта, поверхность для окна, рисунки, виды, заготовки.
Введение
Документ — часть договора Обмен с ядром: источники данных мастерской, методы программы окна и описание пульта. Отображение для человека — Мастерская. Коды отказов — Коды ошибок.
1 Данные мастерской
Функции не описывают отрисовку: мастерская рисует свои виды сама, а данные берёт обычными запросами к функциям (Мастерская, раздел 8).
Таблица 1 — Данные мастерской
| Что показывает мастерская | Откуда берёт |
|---|---|
| граф процесса | process.open, process.list, process.kinds, process.node.template, process.node.candidates, process.validate, process.inspect; событие process.changed — список процессов читается заново, кто бы ни создал, импортировал или сохранил процесс |
| программа, её события и прогоны | process.program.list, process.objects, process.variable.list, process.ask.list, process.show.get, process.runs.list, process.snapshot; события program.changed, run.changed, node.changed, variable.changed, show.changed, ask.opened, ask.closed |
| пульт | canvas.snapshot (слоты и revision), canvas.get при правке; пульта ещё нет — команда canvas.ensure создаёт пустой |
| настройки | settings.schema, settings.get; раздел «Состояние» — core.status |
| модули | module.list; вкладка «Проверка» — ответ module.test |
| память узла-модуля в панели узла | module.state.list; «Очистить память» — команда module.state.clear |
| журнал и проблемы | observe.logs.query, observe.problems.list (поля проблемы — Форматы файлов, раздел 13) |
Действие человека — обычная команда хозяину (process.run.start, process.event.fire, canvas.save, settings.set, module.install …); список команд — в договоре хозяина. При знакомстве функция называет свои поверхности в поле surfaces — это нужно, чтобы видеть состав платформы; смысла этих имён ядро не разбирает.
2 Окно
Окно мастерской — программа Windows; она подключается к функции ui по адресу 127.0.0.1 (порт и токен сессии приходят в командной строке запуска, Мастерская, раздел 2). Как передаются сообщения и как выглядит обёртка — Обмен с ядром, разделы 2, 3. id запроса окна — window-<номер>.
Таблица 2 — Окно
| Метод | Кто отвечает | Параметры | Результат |
|---|---|---|---|
ui.window.hello |
функция ui, первое сообщение соединения |
token |
{ "status": "ready" } |
ui.window.font |
функция ui |
— | { "format": "truetype" \| "opentype" \| "woff" \| "woff2", "data": base64 } — файл ui.font.file, если ui.font.source = file; до 2 500 000 байт |
ui.window.defaults |
функция ui |
— | { "values": { ключ: умолчание } } — умолчания всех ui.* по схеме функции ui; окно рисует ими, пока функция настроек не ответила значениями |
ui.window.layout.get |
функция ui |
— | документ ogas.layout/1 из config/layout.json; до первой записи — { "format", "host": null, "windows": [], "panels": {} } (Форматы файлов, 7.1) |
ui.window.layout.set |
функция ui |
layout: { host, windows, panels }; без panels записывается пустой набор |
{}; раскладка, которая не сходится с Форматы файлов, 7.1, — document_invalid с названием поля |
ui.window.library.get |
функция ui |
— | документ ogas.library/1 из config/library.json; до первой записи — { "format", "bars": [{ "id": "programs", "name": "", "programs": [] }], "hidden": { "programs": [], "modules": [] } } (Форматы файлов, 7.3) |
ui.window.library.set |
функция ui |
library: { bars, hidden, views } |
{}; библиотека, которая не сходится с Форматы файлов, 7.3, — document_invalid с названием поля |
ui.window.face |
функция ui |
— | { "process_id": id \| null } — процесс, лицо программы которого попросил показать запуск, или null; имя отдаётся один раз: окно, открытое заново, показывает то, о чём его попросят тогда |
ui.window.path |
функция ui |
path — путь Windows |
{ path } — тот же файл, как его видит Linux (wslpath -u); куда WSL не достаёт — отказ ui_window_path_unknown |
ui.window.launch |
функция ui |
— | { target, arguments, icon } — чем ярлык Windows запускает платформу: запускатель ogas-start.exe (программа окна кладёт его на диск Windows), который передаёт wsl.exe без консоли слова с дистрибутивом и папкой установки, значок — программа окна; ярлык программы дописывает program --process <id> |
методы функций (process.*, settings.*, i18n.* …) |
хозяин метода через ядро | как у хозяина | как у хозяина |
core.status, core.health, core.space, core.event.subscribe, core.shutdown |
ядро через функцию ui |
как в Обмен с ядром, раздел 5 | как в Обмен с ядром, раздел 5 |
Остальные core.* и function.handshake окну закрыты — method_not_allowed. Неверный токен или первое сообщение не ui.window.hello — ui_window_unauthorized и закрытие соединения. События ядра функция ui пересылает окну уведомлением event в той же обёртке события (Обмен с ядром, раздел 7). Своего срока на ответ не ставят ни функция ui, ни программа окна: обе только передают вызов, а сколько ждать, решает страница (Устройство платформы, 3.7.1). Страница ждёт столько, сколько нужно хозяину метода, и своего срока не ставит: долгую работу хозяина — проверку модуля, установку окружения — срок окна прервал бы. Вызов без ответа не висит: он кончается отказом function_lost, когда хозяин отключился или не прошёл проверку работоспособности, и ui_window_disconnected, когда оборвалась связь окна с платформой.
Лицо программы открывает запуск (Мастерская, 6.6). Имя программы несёт функция ui:
ui.face.open—{ "process_id" }(команда): запомнить для окна процесс, лицо программы которого надо показать, и опубликоватьui.face.asked(Обмен с ядром, раздел 7). Ответ —{ process_id }. Пустое или отсутствующее имя —invalid_request. Есть ли такой процесс и включается ли его программа, функцияuiне проверяет: это говорит окну хозяин процесса. Команду вызывает глагол реестраprogram(Сборка, установка и обслуживание, 5.2); из двух просьб подряд окно берёт последнюю.
Окно при запуске спрашивает ui.window.face и, получив имя, показывает лицо сразу, до чтения процесса; затем открывает процесс и включает его программу командой хозяина (process.program.on). Уже открытому окну о просьбе говорит событие ui.face.asked.
3 Пульт
Хозяин workspace.json — функция canvas. Документ пульта — ogas.workspace/3, граф интерфейса: вместилища и элементы (Форматы файлов, раздел 7). Смысл сквозных объектов — у графа: их задают узлы и переменные process.json (Программа: граф и запуски, раздел 16). Пустой пульт допустим: объекты не раскладываются сами. Отказ за форму документа — canvas_invalid, сообщение называет элемент или вместилище и поле.
canvas.get—{ "process_id" }: документogas.workspace/3, разложенный: у каждой страницы лист, у того, что на ней, место. На диске ничего не меняется;canvas.save—{ "process_id", "document" }: дополняет документ — имя пульта; идентификатор вместилища и то, как оно показывает своё; идентификатор и вместилище элемента; размер и место того, что стоит на листе и записано без них, — проверяет его форму и записывает. Место, записанное в документе, хозяин не меняет и на шаг листа не переводит: то, что не лежит на своём листе целиком или меньше наименьшего размера своего вида, — отказ. Объект, которого в графе нет или который элементу не подходит, отказом не является — его пометит снимок. Поколение пульта ведёт хозяин: записанный документ получает следующее поколение после записанного на диске (первый —1), полеgenerationприсланного документа не учитывается. Ответ —{ process_id, generation }. Пульт на диске, который функция не может прочитать или который другого формата, не перезаписывается: отказdocument_invalid;canvas.ensure—{ "process_id" }: создать пустой пульт — одно окно без названия и без элементов; лист оно получает с первым, что в него положат, — если пульта нет (команда). Записав пульт,canvas.saveиcanvas.ensureпубликуютcanvas.changed(Обмен с ядром, раздел 7). Функция пульта слушаетprocess.changed: если граф записан сrenamed_objects, а пульт ещё называет объекты прежними id, она сама переписывает привязки элементов, вместилищ и самого пульта на новые id и публикуетcanvas.changed; сбой —function.work_failed(Форматы файлов, раздел 15);canvas.snapshot—{ "process_id" }: поверхность для окна, а не документ; файла не создаёт. Ответ —{ surface_id: "canvas.editor", revision, process_id, bindings, open_why, groups, elements, objects, grid, scale_min, theme, images, looks }:revision— поколение документа пульта; без документа — пустой пульт;bindings— привязки самого пульта (open) с нынешними id;open_why—object_goneилиobject_unfit, когда переменная открытого окна пропала или не текстовая, иначеnull;- вместилище —
id,nameилиnull,parentилиnull,holds,bindingsс нынешними id,screenилиnull,box— рамка внутри страницы{ place, size }, посчитанная вокруг того, что в нём лежит, илиnull,lookилиnull,look_why,layerилиnull,collapsed,placed— не убрано ли с листа само,out— не стоит ли на листе — убрано само или лежит в убранном (тогдаbox—null),why—object_goneилиobject_unfitдля привязки к переменной, которой нет или которая не того типа (такое вместилище показывается, как без привязки),image_gone, когда рисунка подложки в папке нет, иначеnull; - элемент —
element_id,kind,family— род,group— вместилище,bindingsс нынешними id объектов (привязкаopensназывает вместилище пульта и не помечается),labelилиnull,screen—{ place, size }у того, что стоит на листе, иначеnull,placedиout— как у вместилища: не стоящий на листе элемент не рисуется,layerилиnull,lookилиnull,look_why— почему элемент нарисован не тем видом, который назвал:look_gone,look_unfitилиlook_broken(работе элемента это не мешает),parameters— заданные человеком и умолчания вида,invalidиwhy:object_gone— объекта в графе нет,object_unfit— объект элементу не подходит,image_gone— рисунка, названного элементом, в папке нет, иначеnull. У украшенияfamily—decoration, аbindingsпусты; - отражение —
id,objects— строки с нынешними id объектов,sourceилиnull,groupилиnull,layerилиnull,gone— те из строк, объектов которых в графе нет; - объект — то, что отдал граф (
process.objects), иfits— виды элементов, которыми объект ставится на пульт, в порядке набора; первый — тот, что объект получает, когда человек вида не назвал; grid—{ step, margin, sheet, head }: шаг листа и отступ от края в единицах листа, размер листа для страницы без него и высота головы рамки;scale_min— предел уменьшения листа на экране в процентах. Это настройки функции пульта для процесса (Настройки, раздел 8): своих чисел листа окно не держит;theme— все ключи темы со значениями: заданными пультом, остальные — из настроек;images— рисунки папки пульта:[ { name, media_type, bytes, stamp } ],stampменяется, когда файл записан заново;looks— виды, которые можно дать элементам:[ { look_id, kind, name, size, own, sound, why, stamp } ]— сперва свои виды процесса (own: true; у вида, который не проходит проверку,sound: falseи причина словами вwhy), затем встроенные, у которыхname—null, а название лежит в словаре элемента;canvas.preview—{ "process_id", "document" }и необязательныйprocess(запрос): то, чем присланный документ станет при записи, без записи. Сprocess— графом, который человек правит, — пульт сверяется с ним, а не с записанным графом: объект, заведённый минуту назад, подходит, убранный — помечается. Ответ —{ document, surface }: документ, дополненный как приcanvas.save, и его поверхность, как уcanvas.snapshot. Отказы — как уcanvas.save. Окно спрашивает так после каждой правки пульта и показывает ответ: своих правил о пульте — что куда встанет, что подходит, что недопустимо — оно не держит;canvas.elements—{}(запрос): набор элементов —{ elements: [ { kind, family, bindings, parameters, one_of, size, min_size } ], theme, image_types }в порядке набора:one_of— привязки, из которых элемент называет хотя бы одну, каждая необязательна сама по себе: кнопка нажимает событие, открывает вместилище или и то и другое;states— состояния, для которых вид может иметь рисунок, первое — обязательное; пустой список — видов у элемента нет;quantity— показывает ли элемент количество, которое вид может нарисовать (Форматы файлов, 7.2);- привязка —
name,objects— виды объектов,types— типы переменной (пусто — любой),many,optional,with— рядом с какой привязкой и каким объектом она допустима; - параметр —
name,how(number|choice|list|text|image— имя рисунка пульта),choices,default,optional,range— наименьшее и наибольшее целое для числа илиnull; theme— ключи темы:[ { key, type, choices, min, max } ],type—color,stringилиinteger; названия ключей — тексты настроекsetting.canvas.theme_<ключ>.title;image_types— окончания имён файлов, которые пульт берёт рисунками;- названия и подсказки — в словарях элементов:
canvas.element.<вид>.name,.description,.binding.<имя>.titleи.help,.param.<имя>.titleи.help,.param.<имя>.choice.<значение>. canvas.images—{ "process_id" }(запрос): рисунки папки пульта —{ images: [ { name, media_type, bytes, stamp } ] }по именам; папки нет — список пуст;canvas.image—{ "process_id", "name" }(запрос): один рисунок для показа —{ name, media_type, bytes, stamp, data },data— содержимое файла в base64. Отказы:canvas_image_invalid— имя не является именем рисунка, файл крупнее настройкиcanvas.image_max_bytesили начинается не так, как файл своего вида;canvas_image_not_found— такого файла нет;canvas.image.put—{ "process_id", "name", "data" }(команда): положить рисунок в папку пульта под этим именем;data— содержимое файла в base64, одним сообщением. Проверяются имя, вид по окончанию имени, начало файла и размер (Форматы файлов, 7.2); отказ —canvas_image_invalid. Рисунок с тем же именем заменяется. Ответ —{ name, media_type, bytes, stamp }; публикуетсяcanvas.images.changed;canvas.image.remove—{ "process_id", "name" }(команда): убрать рисунок из папки. Назван ли он на пульте, функция не проверяет: это правка, которую человек ещё не записал, и знает о ней окно — оно не убирает рисунок, пока тот стоит на листе. Ответ —{ name }; публикуетсяcanvas.images.changed;canvas.look—{ "process_id", "look_id", "kind" }(запрос): вид для показа —{ look_id, kind, own, stamp, look, images }:look— документogas.look/1,images— названные им рисунки{ "<файл>": { media_type, data } }в base64.kind— вид элемента, который спрашивает: свой вид процесса с этим именем отдаётся каким есть, встроенный — только вид этого элемента. Отказы:canvas_look_not_found,canvas_look_invalid;canvas.look.put—{ "process_id", "files": [ { name, data } ] }(команда): принять свой вид целиком —look.jsonи названные им рисунки одним сообщением,dataв base64; нарисованный вид (paint) — одинlook.json. Имя вида берётся изlook_idдокумента. Вид проверяется до записи (Форматы файлов, 7.2): документ, рисунки, лишние файлы, общий размер; отказ —canvas_look_invalidс причиной в сообщении. Вид с тем же именем заменяется целиком. Ответ —{ look_id, kind, files, bytes }; публикуетсяcanvas.images.changed;canvas.look.remove—{ "process_id", "look_id" }(команда): убрать свой вид процесса; нарисован ли им элемент, знает окно, и оно такой вид не убирает. Ответ —{ look_id }; публикуетсяcanvas.images.changed;canvas.files.export—{ "process_id", "target" }(команда): скопировать папкуpulpit/процесса в папкуtargetвнутри папки данных — так пакет процесса получает рисунки и виды пульта (Форматы файлов, 10.1). Ссылки и недописанные файлы не копируются; папка без файлов не создаётся. Ответ —{ files, bytes }. Путь вне папки данных —path_outside_root;canvas.files.import—{ "process_id", "source" }(команда): сделать файлы папкиsourceфайлами пульта этого процесса; источника нет — ничего не делается. Ответ —{ files, bytes }; когда файлы пришли, публикуетсяcanvas.images.changed.canvas.piece.save—{ "process_id", "group_id" }и необязательныйname(команда): сохранить вместилище записанного пульта со всем, что в нём лежит, заготовкой интерфейса в библиотеке (Форматы файлов, 7.4). Что снимается со связей и видов, — там же. Имя заготовки даёт функция из названия; занятое имя не перезаписывается, а получает номер. Ответ —{ piece_id, name }. Вместилища в пульте нет —canvas_invalid;canvas.piece.list—{}(запрос): заготовки библиотеки по именам —{ pieces: [ { piece_id, name, holders, elements } ] },holdersиelements— сколько в ней вместилищ и элементов. Файл другого формата в список не входит;canvas.piece.get—{ "piece_id" }(запрос): заготовка целиком, документogas.piece/1. Ставит её окно, правкой пульта, которую записываетcanvas.save. Заготовки нет —canvas_piece_not_found;canvas.piece.import—{ "path" }(команда): принять в библиотеку заготовку, принесённую извне, — документogas.piece/1по пути от папки данных, например скачанный из витрины вdownloads/. Её вместилища и элементы проверяются правилами пульта, как если бы они были пультом; имя заготовки даёт функция из её названия, занятое получает номер. Ответ —{ piece_id, name }. Документ другого формата или нарушающий правила пульта —canvas_invalid, документа нет —document_not_found. Заготовка — данные, а не код: о доверии не спрашивается.canvas.piece.delete—{ "piece_id" }(команда): убрать заготовку из библиотеки; программы, куда её поставили, поставленное сохраняют. Ответ —{ piece_id, deleted: true }. Заготовки нет —canvas_piece_not_found.