Узнайте, как выполнить автоматизацию общих задач разработки сценариев с помощью панели сценариев и панели ярлыков сценариев в InDesign.
Разработка сценариев в InDesign
Сценарии представляют собой удобный инструмент для выполнения различных задач. Сценарий может быть как простым (например, автоматизированная типовая задача), так и сложным (например, полностью новая функция). Возможно как создание собственных сценариев, так и запуск сценариев, созданных другими пользователями. Дополнительные сведения о сценариях см. в руководстве по разработке сценариев, в требованиях к сценариям, а также на других ресурсах для разработчиков на сайте.
Руководство содержит введение в написание сценариев и учебные пособия. В нем также представлен ряд полезных сценариев, например сценарий, который рисует направляющие вокруг выделенного объекта. Некоторые из этих сценариев по умолчанию отображаются в палитре «Сценарии».
Сценарии UXP
Сценарии в InDesign теперь поддерживаются Unified Extensibility Platform (UXP), так что для автоматизации задач можно использовать современный JavaScript (ES5 и большинство функций ES6). Получите более подробную информацию о Сценарии UXP.
Обзор палитр «Сценарии» и «Ярлык сценария»
InDesign содержит две палитры для работы со сценариями: Сценарии и Ярлык сценария.
С помощью палитры Сценарии можно выполнять сценарии, не выходя из программы InDesign. В палитре Сценарии отображаются сценарии, расположенные в подпапках Scripts папки приложения InDesign и в пользовательских папках Установки.
Выберите Windows >Утилиты > Сценарии, чтобы открыть Палитру сценариев.Чтобы сценарий появился в палитре Сценарии, после создания или получения его необходимо поместить в папку Scripts Panel.
Users/[имя_пользователя]/Library/Preferences/Adobe InDesign/[версия]/[язык]/Scripts/Scripts Panel |
|
Documents and Settings[имя пользователя]Application DataAdobeInDesign[версия][язык]ScriptsScripts Panel |
|
Windows Vista и Windows 7 |
Users[имя_пользователя]AppDataRoamingAdobeInDesign[версия][язык]ScriptsScripts Panel |
Для быстрого перехода к папке Scripts Panel щелкните сценарий в палитре Сценарии правой кнопкой мыши (Windows) или удерживая клавишу Control (macOS), а затем выберите пункт Показать в Проводнике (Windows) или Показать в программе Finder (macOS).
Палитра Ярлык сценария позволяет задавать ярлыки для элементов страницы: текстовых фреймов, фигур и др. Задание ярлыков для элементов страницы особенно полезно при написании сценариев, в которых необходима идентификация объектов. Выберите Windows > Утилиты > Ярлык сценария, чтобы открыть палитру Ярлык сценария.
Дополнительные сведения о добавлении, выполнении и редактировании сценариев см. в руководстве по разработке сценариев.
Образцы сценариев
Вы можете дважды щелкнуть сценарий в палитре Сценарии, чтобы выполнить его, либо выполнять сценарии с помощью функции Быстрое применение.
AddGuides. |
Добавление направляющих вокруг выбранного объекта или объектов. |
AddPoints. |
Добавление точек в контур выбранного объекта или объектов. |
Добавление QR-кода |
QR-код может быть размещен на графическом объекте или непосредственно в качестве элемента страницы. |
AdjustPageItems |
Перемещает содержимое четных/нечетных страниц на указанную величину; пытается вернуть объекты в правильное положение после изменения поля мастер-страницы и/или вставки страницы. |
AlignToPage. |
Выравнивание объектов в указанном местоположении на странице. |
AnimationEncyclopedia. |
Автоматическое создание кнопок с различными свойствами анимации. |
BreakFrame. |
Удаление выбранного текстового фрейма и его содержимого из материала. |
CornerEffects. |
Повторная прорисовка контура выбранного элемента или элементов с использованием различных типов углов. Типы углов могут быть применены к выбранным точкам контура. |
CreateCharacterStyles. |
Определение полного стиля символа на основе выбранного текста. |
CropMarks. |
Добавление меток обреза или меток приводки вокруг выбранного объекта или объектов. |
ExportAllStories. |
Экспорт всех материалов документа в несколько текстовых файлов. |
FindChangeByList. |
Выполнение нескольких операций по поиску и замене текста на основе файла с разделителями-табуляциями. |
ImageCatalog. |
Размещение всей графики в определенной папке макета «галереи». |
MakeGrid. |
Создание сетки путем разделения или дублирования выбранного объекта или объектов. |
Neon. |
Применение эффекта «наложения» к выбранному объекту или объектам. |
PathEffects. |
Изменение положения точек контура на выбранном объекте или объектах для добавления художественного эффекта. |
PlaceMultipagePDF. |
Помещение всех страниц файла PDF. |
SelectObjects. |
Выбор объектов на активном развороте по типу. |
SortParagraphs. |
Сортировка всех абзацев выбранного фрагмента в алфавитном порядке. |
SplitStory. |
Разделение текстовых фреймов в выбранном материале на отдельные несвязанные текстовые фреймы. |
TabUtilities. |
Применение табуляции и отступа к выбранному тексту. |
Для получения дополнительной информации об установке и использовании этих образцов сценариев см. раздел Автоматизация.
Сценарии, созданные сообществом
Теперь в InDesign можно найти еще больше сценариев, созданных сообществом InDesign.
- Unicode Injector, автор Крис Коппитерс (Kris Coppieters) — позволяет использовать сочетания клавиш для вставки в текст InDesign любого символа или последовательности символов Unicode. Дополнительные сведения см. в разделе Инструкции.
- Insert Typographer Quote, автор Штефан Ракете (Stefan Rakete) — позволяет использовать сочетания клавиш для обрамления выделенного текста кавычками разных видов. Дополнительные сведения см. в разделе Инструкции.
- Layer Cloner, автор Паоло Агостинетто (Paolo Agostinetto) — этот сценарий позволяет скопировать один слой вместе с элементами из одного документа в другой. Дополнительные сведения см. в разделе Инструкции.
- Get x-Height, автор Роланд Дрегер (Roland Dreger) — определение высоты строчных знаков абзаца текста. Дополнительные сведения см. в разделе Инструкции.
- Привязка поля к текстовому фрейму, автор Ариэль Уолден (Ariel Walden) — сценарий позволяет изменить поля во всем документе, чтобы они соответствовали полям выбранного текстового фрейма. Дополнительные сведения см. в разделе Инструкции.
- Конец связывания текста, автор Ариэль Уолден (Ariel Walden) — сценарий InDesign, который облегчает добавление разрывов между текстовыми фреймами. Дополнительные сведения см. в разделе Инструкции.
- InCopy Note Alert, автор Крис Коппитерс (Kris Coppieters) — сценарий запуска для Adobe® InDesign® и Adobe InCopy®, который предупреждает о наличии примечаний. Дополнительные сведения см. в разделе Инструкции.
- Copy Paste Coordinates, автор Крис Коппитерс (Kris Coppieters) — сценарий для копирования и вставки координат в элементы страницы. Дополнительные сведения см. в разделе Инструкции.
- Chain Grep, автор Грегор Фелленц (Gregor Fellenz) — позволяет привязывать запросы InDesign GREP к новым сценариям. Дополнительные сведения см. в разделе Инструкции.
- Clear Overrides, автор Грегор Фелленц (Gregor Fellenz) — позволяет сбросить изменения текста, таблиц и объектов InDesign. Дополнительные сведения см. в разделе Инструкции.
- Invert Selection, автор Луис Фелипе Корульон (Luis Felipe Corullón) — Сценарий для инвертирования выделения в документе InDesign. Дополнительные сведения см. в разделе Инструкции.
- Layer Cloner, автор Паоло Агостинетто (Paolo Agostinetto) — Этот сценарий позволяет скопировать слой вместе с элементами из одного документа в другой. Дополнительные сведения см. в разделе Инструкции.
- Конечные заметки до конца книжных заметок, автор Питер Карел (Peter Kahrel) — Преобразование сносок в конце документа в сноски в конце книги. Дополнительные сведения см. в разделе Инструкции.
- Перенумерация ссылок в концевых сносках, автор Питер Карел (Peter Kahrel) — Сценарий создает концевые сноски, ссылки на которые не обновляются автоматически при добавлении или удалении концевых сносок. Дополнительные сведения см. в разделе Инструкции.
- Масштабирование по размерам страницы, автор Олав Кверн (Olav Kvern) — Изменение размера текущего выделения, например изображения, до размера страницы. Дополнительные сведения см. в разделе Инструкции.
- Масштабирование страницы по размерам объекта, автор Олав Кверн (Olav Kvern) — Изменение размера страницы до размера текущего выделения, например изображения. Дополнительные сведения см. в разделе Инструкции.
Adobe поддерживает на GitHub репозиторий со сценариями сообщества с открытым исходным кодом. Дополнительные сведения о репозитории InDesign Community Script см. в файле ReadMe. Этот файл ReadMe содержит подробную информацию о том, как внести свой сценарий в репозиторий, а также ссылки на создателей сценариев.
Связанные материалы
Обращайтесь к нам
Чтобы разобраться во всех возможностях скриптинга, надо не один раз прочитать руководство JavaScript Tools Guide (оно на английском языке) и разобраться, как работают другие скрипты. Кроме того, на мой взгляд, скрипты из SDK несколько заморочены. К счастью, эта замороченность побудила одного из мировых гуру индизайна и скриптинга Питера Карела сделать более ясное руководство. И это ему удалось!
Мы ранее сообщали об этой публикации и теперь предлагаем всем интересующимся перевод этого документа.
Вначале при переводе диалоги скриптов переводились на русский. Но когда стало ясно, что работая так, не уложусь в отведенное себе время на перевод, отказался от практики перевода скриптов. Они только проверялись на верность функционирования.
М.И.
Написание скриптов. Пользовательский интерфейс
Перевод статьи http://www.kahrel.plus.com/indesign/scriptui.html
Введение
ScriptUI — это модуль семейства программ Adobe CS, начиная с версии CS3, с помощью которого можно добавлять в скрипты диалоги. Модуль входит в состав ExtendedScript Toolkit (ESTK), и сделанные в нём диалоги можно использовать в скриптах для всех приложений Creative Suite, далее CS.
Хотя этот документ посвящен организации диалогов в скриптах, выполняемых в программе InDesign, теоретически всё сказанное здесь применимо и к скриптам для других программ CS.
Руководство посвящено только ScriptUI, предполагается, что читатель имеет достаточно знаний о JavaScript.
Руководство полностью описывает среду создания диалогов, и его надо рассматривать как дополнение к основному документу по скриптописанию — JavaScript Tools Guide.
«Здравствуй, мир!»
Самый простейший скрипт выводит сообщение на экран. Вот как он выглядит:
var myWindow = new Window ("dialog"); var myMessage = myWindow.add ("statictext"); myMessage.text = "Здравствуй, мир! Hello, world! [ ОКНО dialog ]"; myWindow.show ( );
Вот что будет при его запуске:
Первая строка определяет новое окно типа dialog; вторая добавляет элемент интерфейса типа statictext; третья определяет содержимое окна; последняя выводит окно на экран.
Чтобы закрыть окно, надо щелкнуть мышкой на красной кнопке с крестиком. Позднее будут рассмотрены более изящные способы закрытия диалогов.
Особенности типов окна
В графическом интерфейсе пользователя модальным называется окно, которое блокирует работу пользователя с родительским приложением до тех пор, пока пользователь это окно не закроет. Модальными преимущественно реализованы диалоговые окна. В ScriptUI есть два типа окна: dialog (диалоговое) и palette (палитра). Вы уже знаете, в чем межу ними разница, т.к. названия диалог и палитра отражают, как работают в InDesign подобные окна. Окно dialog остается активным, пока вы с ним работаете, и пока оно открыто, вы ничего другого делать не можете. Пример — диалоги TextFrame Options или Paragraph Rules. Вы сможете продолжить работу в программе только после закрытия этих окон.
Окно типа palette отображается на экране, но не препятствует работе в программе InDesign. Пример такого окна — палитры Paragraphs или Characters. Такие диалоговые окна называются немодальными.
Визуально окна этих типов можно различить по признаку наличия кнопок ОК и Cancel: диалоговые окна их имеют, а палитры — нет. Хотя можно сделать и палитру с этими кнопками, и диалог без них (хотя вряд ли он будет где-то полезен). Приведенный выше скрипт как раз и создает окно типа dialog.
[Для полноты картины надо сказать, что в объектной модели есть и третий тип окна — window, но он ведет себя точно также как palette.]
Окно типа palette
Чтобы сделать окно типа palette, надо задать этот тип при создании окна, и определить используемый движок (engine) — строка #targetengine «session» в следующем скрипте.
#targetengine "session"; var myWindow = new Window ("palette"); var myMessage = myWindow.add ("statictext"); myMessage.text = "Здравствуй, мир! Hello, world! [ ОКНО palette ]"; myWindow.show ( );
Попробуйте оба скрипта, чтобы убедиться, что первый блокирует работу, пока не закроешь окно, а второй позволяет работать при открытом окне.
Налицо и некоторые несущественные различия в оформлении окон в части скругления углов и разного размера кнопок.
Добавление элементов интерфейса
Элемент интерфе́йса — примитив графического интерфейса пользователя, имеющий стандартный внешний вид и выполняющий стандартные действия. Он также может называться как контро́л (control) или элемент управления.
В ScriptUI определены следующие простейшие элементы интерфейса:
button — кнопка;
checkbox — флажок;
dropdownlist — раскрывающийся список (выпадающий список);
edittext — поле редактитрования (поле ввода);
iconbutton — кнопка с картинкой;
image — графическое изображение в формате PNG, картинка
item — элемент списка или выпадающего списка;
listbox — список;
radiobutton — радиокнопка;
statictext — сообщение, к которому нет доступа пользоваелю;
Более сложные:
flashplayer — флэш-проигрыватель;
progressbar — индикатор выполнения задачи на текущий момент;
scrollbar (полоса прокрутки);
slider — движок;
treeview (дерево для отбражения иерархии).
Элементы интерфейса-контейнеры:
Новое окно, созданное командой new Window(), по своей сути является контейнером, в который помещаются элементы интерфейса – кнопки, текст, поля ввода, списки, радиокнопки, чекбоксы и т.д. Но существуют и другие типы контейнеров в ScriptUI — это группа элементов (group), панель (panel) и панель с вкладками, называемая TabbedPanel. Вы можете как угодно вкладывать один контейнер в любой другой, например в главное окно добавить три панели, затем в первую панель добавить элемент Static Text и еще панель, во вторую панель можете добавить группу и панель с вкладками, и на каждой вкладке снова разместить панели с элементами, а в третьей – разместить прогрессбар и т.д. Все элементы интерфейса и контейнеры добавляются при помощи метода add().
Элементы интерфейса, добавленные в какой-нибудь контейнер, считаются дочерними по отношению к нему. И если вы решили скрыть какой-то контейнер, то исчезнут и элементы, расположенные в нем.
В первом скрипте была управляющая строка statictext. Этот элемент интерфейса позволяет добавить в окно какой-нибудь текст. Помещаемый текст задавался второй строкой:
myMessage.text = "Здравствуй, мир!";
но можно обойтись и одной строкой:
var myMessage = myWindow.add ("statictext", undefined, "Здравствуй, мир!")
т.е. задать текст как параметр метода add().
В этой строке оператор undefined используется как заместитель параметров, которые не будут рассмотрены в этом руководстве, а именно размер и положение текста в окне или другом контейнере (позднее мы вернемся к контейнерам внутри окна).
Первый рабочий пример
Перед тем как углубиться в детали всех других средств управления, сделаем простой скрипт, показывающий основные особенности окна ScriptUI. Изучая этот пример вы увидите, как обычно подходят к созданию окон, это похоже на процесс конструирования — сперва определяются основные моменты, затем выбираются те, что более управляемы, чтобы улучшить вид окна. Будет сделан скрипт, запрашивающий у пользователя данные.
Ввод текста выполняется при помощи элемента интерфейса edittext. Чтобы указать, что это поле для ввода данных, надо при помощи элемента интерфейса statictext добавить отдельно приглашение.
var myWindow = new Window ("dialog", "Форма"); myWindow.add ("statictext", undefined, "Имя:"); var myText = myWindow.add ("edittext"); myWindow.show ();
Обратите внимание, что окно теперь с заголовком «Форма». Заметьте также, что поле ввода стоит ниже приглашения («Имя:»), что не есть хорошо. Предположительно, что ориентация окна по умолчанию имеет тип column. Чтобы изменить этот тип, нужен соответствующий оператор в скрипте (вторая строка):
var myWindow = new Window ("dialog", "Форма"); myWindow.orientation = "row"; myWindow.add ("statictext", undefined, "Имя:"); var myText = myWindow.add ("edittext"); myWindow.show ();
Результат несколько лучше, но поле ввода очень маленькое. Кроме того, надо сделать так, чтобы по умолчанию были введены какие-то данные.
var myWindow = new Window ("dialog", "Форма"); myWindow.orientation = "row"; myWindow.add ("statictext", undefined, "Имя:"); var myText = myWindow.add ("edittext", undefined, "Петр"); myText.characters = 30; myWindow.show ();
Теперь можно для элемента интерфейса edittext определить длину строки вводимых данных, это делается указанием значения свойства characters этого оператора. Далее будут показаны другие способы управления длиной строки.
В этом диалоге, чтобы изменить имя, пользователь должен поместить курсор в текстовое поле. Если скрипт сам поместит курсор в это поле и выделит текст, то такое решение будет намного полезнее предыдущего. Это выполняется строкой myText.active = true
var myWindow = new Window ("dialog", "Форма"); myWindow.orientation = "row"; myWindow.add ("statictext", undefined, "Имя:"); var myText = myWindow.add ("edittext", undefined, "Петр"); myText.characters = 30; myText.active = true; myWindow.show ();
Теперь добавим кнопки, в нашем случае OK и Cancel. Это элементы интерфейса типа button:
var myWindow = new Window ("dialog", "Форма"); myWindow.orientation = "row"; myWindow.add ("statictext", undefined, "Имя:"); var myText = myWindow.add ("edittext", undefined, "Петр"); myText.characters = 30; myText.active = true; myWindow.add ("button", undefined, "OK"); myWindow.add ("button", undefined, "Cancel"); myWindow.show ();
Поскольку тип ориентации окна выбран row, то у нас и приглашение, и текстовая строка, и кнопки вытянуты в одну линию. Но это не лучший вариант.
Можно вернуться к стандартному свойству ориентации окна (myWindow.orientation) «column», но сгруппировать поле приглашения и поле ввода текста в одну группу (myInputGroup), а кнопки в другую группу (myButtonGroup):
var myWindow = new Window ("dialog", "Форма"); // В следующей строке создается группа myInputGroup var myInputGroup = myWindow.add ("group"); myInputGroup.add ("statictext", undefined, "Имя:"); var myText = myInputGroup.add ("edittext", undefined, "Петр"); myText.characters = 30; myText.active = true; // В следующей строке задается группа myButtonGroup var myButtonGroup = myWindow.add ("group"); myButtonGroup.add ("button", undefined, "OK"); myButtonGroup.add ("button", undefined, "Cancel"); myWindow.show ();
Для объединения полей или кнопок кроме элемента интерфейса group может использоваться элемент интерфейса, контейнер panel. Он отличается от группы тем, что элементы интерфейса будут окружены рамкой. Кроме того, стандартная ориентация объектов для group — это row, тогда как для panel — column.
Ниже группа кнопок будет заключена в рамку:
var myWindow = new Window ("dialog", "Форма"); var myInputGroup = myWindow.add ("group"); myInputGroup.add ("statictext", undefined, "Имя:"); var myText = myInputGroup.add ("edittext", undefined, "Петр"); myText.characters = 26; myText.active = true; var myButtonGroup = myWindow.add ("panel"); myButtonGroup.orientation ="row"; myButtonGroup.add ("button", undefined, "OK"); myButtonGroup.add ("button", undefined, "Cancel"); myWindow.show ();
Добавим в окно контейнер типа panel, чтобы заключить в общую рамку все поля:
var myWindow = new Window ("dialog", "Форма"); var myPnl = myWindow.add ("panel"); var myInputGroup = myPnl.add ("group"); myInputGroup.add ("statictext", undefined, "Имя:"); var myText = myInputGroup.add ("edittext", undefined, "Петр"); myText.characters = 20; myText.active = true; var myButtonGroup = myPnl.add ("group"); myButtonGroup.add ("button", undefined, "OK"); myButtonGroup.add ("button", undefined, "Cancel"); myWindow.show ();
Обратите внимание, что в группах теперь не определен явно тип ориентации. В данном случае он не нужен: ведь в окне всего два объекта, и стандартная ориентация для панели — колонка, а для группы — строка.
{Но явным указанием ориентации в панели и группе можно получить такие результаты:
Панели — это хорошие инструменты скриптинга в создании окон. При правильном использовании создаваемые окна легко настраиваются. Например, если надо, чтобы кнопки были справа одна над другой, то всё, что надо сделать — это поместить в скрипт два оператора ориентации.
var myWindow = new Window ("dialog", "Форма"); myWindow.orientation = "row"; var myInputGroup = myWindow.add ("group"); myInputGroup.add ("statictext", undefined, "Имя:"); var myText = myInputGroup.add ("edittext", undefined, "Петр"); myText.characters = 20; myText.active = true; var myButtonGroup = myWindow.add ("group"); myButtonGroup.orientation = "column"; myButtonGroup.add ("button", undefined, "OK"); myButtonGroup.add ("button", undefined, "Cancel"); myWindow.show ();
Для выравнивания групп по вертикали надо добавить строку
myWindow.alignChildren = "top".
(При помощи свойства alignChildren происходит выравнивание дочерних элементов)
var myWindow = new Window ("dialog", "Форма"); myWindow.alignChildren = "top"; myWindow.orientation = "row"; var myInputGroup = myWindow.add ("group"); myInputGroup.add ("statictext", undefined, "Имя:"); var myText = myInputGroup.add ("edittext", undefined, "Петр"); myText.characters = 20; myText.active = true; var myButtonGroup = myWindow.add ("group"); myButtonGroup.orientation = "column"; myButtonGroup.add ("button", undefined, "OK"); myButtonGroup.add ("button", undefined, "Cancel"); myWindow.show ();
Предположим, что окно нас устраивает, и вернемся к вопросу, как в скрипте сохранить введенный пользователем текст. В нашем примере есть два события — пользователь щелкает на кнопке ОК (это эквивалентно нажатию на клавишу Enter) или щелкает на кнопке Cancel (это эквивалентно нажатию на клавишу Esc).
Скрипт работает так: если нажата кнопка ОК, строка myWindow.show () возвращает 1, в другом случае будет возвращена 2.
Эту проверка в скрипте реализуется так:
if (myWindow.show () == 1) var myName = myText.text; else exit ();
т.е. веденный текст берется из myText.text.
И полностью скрипт может выглядеть так:
var myName = myInput (); // rest of the script function myInput () { var myWindow = new Window ("dialog", "Форма"); var myInputGroup = myWindow.add ("group"); myInputGroup.add ("statictext", undefined, "Имя:"); var myText = myInputGroup.add ("edittext", undefined, "Петр"); myText.characters = 20; myText.active = true; var myButtonGroup = myWindow.add ("group"); myButtonGroup.add ("button", undefined, "OK"); myButtonGroup.add ("button", undefined, "Cancel"); if (myWindow.show () == 1) return myText.text; else exit (); }
Форматирование фрейма окна
Существуют некоторые особенности, определяющие вид палитр и диалогов.
Можно решить убрать кнопку закрытия окна:
myWindow = new Window ("dialog", "Example", undefined, {closeButton: false}) myWindow.add ("statictext", undefined, "closebutton: false"); myWindow.show ();
Можно сделать фрейм без бордюра:
myWindow = new Window ("dialog", "Example", undefined, {borderless: true}) myWindow.add ("statictext", undefined, "borderless: true"); myWindow.show ();
Такие безбордюрные фреймы минималистичны, по сути это просто серые панели. Их вид можно улучшить, нарисовав вокруг них контур (добавив панель):
myWindow = new Window ("dialog", undefined, undefined, {borderless: true}); myWindow.margins = [0,0,0,0]; myPanel = myWindow.add ("panel"); myPanel.add ("statictext", undefined, "borderless but framed. Окно без бордюра, но оконтурено"); myWindow.show ();
На этом основы построения окон завершены, вернемся к деталям организации содержимого окон.
Элементы интерфейса
Элемент интерфейса statictext
Упомянут для полноты освещения. О нем нечего сказать к тому, что было сказано раньше.
Элемент интерфейса edittext
Был рассмотрен ранее. Он используется для получения данных от пользователя. По умолчанию вводится одна строка, и есть полезное свойство multiline, позволяющее вводить несколько строк.
var myWindow = new Window ("dialog", "Multiline"); var myText = myWindow.add ("edittext", [0, 0, 150, 70], "", {multiline: true}); myText.active = true; myWindow.show ();
Второй параметр элемента управления edittext — размер окна [Xлв Yлв Ширина Высота]
При вводе чисел (перевод строки Crtl+Enter) при переполнении окна становится активной полоса прокрутки.
У этого элемента есть еще одно интересное свойство: noecho, по умолчанию установленное в False. Если его установить в true:
var myText = myWindow.add ("edittext", [0, 0, 150, 70], "", {noecho: true});
то вводимый текст в поле ввода не будет отображаться. Это может потребоваться если скрипт запрашивает пароль.
Для ввода данных есть только один инструмент — описанный ранее edittext. Не предусмотрено средств для ввода чисел, единиц измерения и пр. Если требуется указывать единицы измерения, это надо делать самим.
Пример: живая прокрутка
Можно захотеть иметь скрипт для отображения текста, но стандартная функция display() имеет ограничения и не приспособлена для работы с большими текстами. Однако нетрудно написать свой метод создания окна с прокруткой.
Дополнительно преимущество состоит в том, что можно копировать текст из окна и вставлять в окно.
// создадим пример массива array = []; for (i = 0; i < 150; i++) array.push ("Строка " + String (i)); alert_scroll ("Пример", array); function alert_scroll (title, input) // string, string/array { // если входной параметр -- массив, преобразуем его в строку if (input instanceof Array) input = input.join ("r"); var w = new Window ("dialog", title); var list = w.add ("edittext", undefined, input, {multiline: true, scrolling: true}); // Список не должен быть больше максимально возможной высоты окна list.maximumSize.height = w.maximumSize.height - 750; // эта строка определяет высоту прокручиваемого окна list.minimumSize.width = 150; w.add ("button", undefined, "Закрыть", {name: "ok"}); w.show (); }
Эта функция имеет один недостаток — при работе с большими массивами заметно время их обработки.
Элемент интерфейса button
Нажимаемые кнопки
Можно использовать различные типы кнопок. Ранее были рассмотрены стандартные нажимаемые кнопки ОК и Cancel, часто используемые в окнах
var w = new Window ("dialog"); w.add ("button", undefined, "OK"); w.add ("button", undefined, "Cancel"); w.show ();
По умолчанию щелчок на клавише ОК эквивалентен нажатию на клавишу Enter, а щелчок на Cancel — на клавишу ESC. И такая работа скрипта будет, если названия этих кнопок именно такие.
Действия при нажатии на кнопку
Если требуется выполнить какие-либо действия, отличные от ОК и Cancel, то их надо самому запрограммировать. Это выполняется при помощи функции onClick — отклика на событие.
Пример:
var w = new Window ("dialog"); var e = w.add ("edittext", undefined, "Abcdefg"); var convert_button = w.add ("button", undefined, "Convert to upper case"); w.add ("button", undefined, "OK"); convert_button.onClick = function () {e.text = e.text.toUpperCase()} w.show ();
После щелчка на кнопке ‘Переключить в верхний регистр’ буквы станут прописными. Это простой пример, но функции, вызываемые событием onClick могут быть любой сложности. (Есть несколько других откликов на события /в оригинале callback/, с которыми мы познакомимся позднее.
Кнопки-пиктограммы (icon buttons)
Кроме стандартных нажимаемых кнопок можно использовать пиктограммы как кнопки. На них отображается не текст, такой как ОК, а изображение. Картинка может быть в формате PNG, IDRC или JPEG.
Вот как выглядит запись такой кнопки в программе:
w.add ("iconbutton", undefined, <strong>File </strong>(myFile));
Это добавляет кнопку (как pushbutton, т.е. стартовую кнопку) на кнопочной панели, а не текст (например, первая кнопка на следующем рисунке кнопочной панели).
Кнопки могут быть добавлены как инструментальные кнопки (в оригинале toolbuttons), т.е. отображается только картинка, но не сама кнопка ( вторая кнопка на рисунке ). Кнопки могут работать как тумблеры (см. третью и четвертую кнопки на рис.), т.е. иметь два состояния «вкл/выкл», так, третья кнопка отжата, а четвертая — нажата.
Вот код, реализующий работу этих кнопок:
var w = new Window ("dialog","РАЗНЫЕ КНОПКИ"); w.orientation = "row"; var f = File ("/с/tmp/icon.jpg"); w.add ("iconbutton", undefined, f ); // 1 w.add ("iconbutton", undefined, f, {style: "toolbutton"}); // 2 var t1 = w.add ("iconbutton", undefined, f, {style: "toolbutton", toggle: true}); // c var t2 = w.add ("iconbutton", undefined, f, {style: "toolbutton", toggle: true}); // d t2.value = true; w.show ();
В интерфейсе индизайна примеры кнопок-тумблеров можно найти на панелях Text и GREP окна Find/Change, там эти кнопки определяют — надо или нет включать в пространство поиска сноски, мастер-страницы и пр. По умолчанию эти тумблеры выключены, и это состояние управляется свойством value, как показано в последнем примере. Это свойство проверяется, если надо узнать состояние переключателя: if (t1.value == true).
Свойства style и toggle имеют смысл только когда определены для кнопок-пиктограмм, для обычных кнопок эти свойства не работают.
Хорошая практика предполагать в скрипте, что файл пиктограммы может быть не найден, и иметь решение на этот случай:
var w = new Window ("dialog"); var f = File ("/d/test/icon.idrc"); try {var b = w.add ("iconbutton", undefined, f )} catch (_) {var b = w.add ("button", undefined, "@")} w.show ();
Если указанного файла не найдено, на экран выводится такое окно:
Элемент интерфейса checkbox (флажок)
Вот примеры окон с несколькими флажками. Во время отображения окна пользователь может поставить птичку в любом из квадратиков, это установит свойство value этого флажка в состояние true:
var myWindow = new Window ("dialog"); var check1 = myWindow.add ("checkbox", undefined, "Предпочтителен черный"); var check2 = myWindow.add ("checkbox", undefined, "Предпочтителен черный и белый"); check1.value = true; myWindow.show ();
По умолчанию свойство value установлено в false.
Здесь очевидна еще одна стандартная установка: в рамках контейнера все объекты выравниваются по центру. Это можно изменить установкой свойства alignChildren. Обратите также внимание, что описания флажков помещены очень близко к квадратику — чтобы отодвинуть текст, надо добавить неразрывный пробел (u00A0):
var w = new Window ("dialog"); w.alignChildren = "left"; var check1 = w.add ("checkbox", undefined, "u00A0Предпочтителен черный"); var check2 = w.add ("checkbox", undefined, "u00A0Предпочтителен черный и белый"); check1.value = true; w.show ();
А так можно проверить, установлен ли первый флажок:
if (check1.value == true) return whatever
Элемент интерфейса radiobutton (радиокнопка)
Радиокнопки схожи с флажками, но если можно установить все флажки, то с радиокнопками так не выйдет — в блоке может быть выбрана только одна кнопка.
Вот пример окна с несколькими радиокнопками:
var w = new Window ("dialog"); w.alignChildren = "left"; var radio1 = w.add ("radiobutton", undefined, "Предпочтителен черный"); var radio2 = w.add ("radiobutton", undefined, "Предпочтителен черный и белый"); radio1.value = true; w.show ();
Чтобы узнать, какая из радиокнопок в группе нажата, надо перебирать все кнопки, пока не будет найдена активная.
В случае группы из двух кнопок всё намного проще:
if (radio1.value == true) // выбрана первая радиокнопка else // выбрана вторая радиокнопка
Но если в группе несколько кнопок, то метод поиска перебором — это громоздкое решение.
Лучше поместить кнопки в массив, что позволит легко найти нажатую:
var w = new Window ("dialog"); w.alignChildren = "left" var formats = []; formats[0] = w.add ("radiobutton", undefined, "InDesign"); formats[1] = w.add ("radiobutton", undefined, "PDF"); formats[2] = w.add ("radiobutton", undefined, "IDML"); formats[3] = w.add ("radiobutton", undefined, "Text"); w.add ("button", undefined, "OK"); // по умолчанию выбрана первая кнопка formats[0].value = true; if (w.show () == 1) alert ("Выбрано: " + selected_rbutton (formats)); function selected_rbutton (rbuttons) { for (var i = 0; i < rbuttons.length; i++) if (rbuttons[i].value == true) return i; }
Важно установить блок радиокнопок в исходное состояние, т.е. программа возвращает результат выбора. Если начальной установки нет, и выбор не сделан, программа вернет значение undefined.
Для возврата текстовой строки, а не индекса используйте возвращенное число как индекс обращения к массиву. Например, в последнем примере вывод сообщения о выборе можно сделать так:
alert ("Выбрано: " + ["indd", "pdf", "idml", "txt"][selected_rbutton (formats)]);
т.е. выводится выбранное расширение файла.
Если у вас несколько блоков радиокнопок, они должны быть размещены в отдельных группах.
Вот, например, как в скрипте batch/convert/export documents
сделано два блока радиокнопок:
Радиокнопки для From: и To: размещены в отдельных группах.
Элемент интерфейса listbox (список)
Это список текстовых строк. Он может заполняться в момент создания окна или позже. Для заполнения списка в момент создания окна объекты списка помещаются в массив. Вот пример:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["one", "two", "three"]); w.show ();
Для создания списка позже, или добавления объектов в существующий список используйте показанный ниже метод:
var w = new Window ("dialog"); var myList = w.add ("listbox"); myList.add ("item", "one"); myList.add ("item", "two"); myList.add ("item", "three"); w.show ();
Объект в списке выбирается щелчком на нем. По умолчанию можно выбрать только один объект. Для возможности выбора нескольких объектов поступайте так:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["one", "owo", "three"], {multiselect: true}); w.show ();
Когда свойством
разрешен выбор нескольких строк, объекты выбираются стандартно: Ctrl+клик добавляет один объект, Shift+клик добавляет диапазон.
Чтобы после запуска скрипта одна из строк, например, первая, уже была выбрана, надо, чтобы было определено свойство selection этого списка:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["one", "two", "three"], {multiselect: true}); myList.selection = 0; w.show ();
Для выбора в таком списке более одной позиции при запуске скрипта надо записать в массив индексы выбираемых объектов:
myList.selection = [0,2];
для выбора подряд идущих объектов в этом массива должны быть перечислены индексы всех выбираемых объектов:
myList.selection = [0,1,2];
эта строка выберет первые три объекта списка.
Определение, какой из элементов списка выбран
Чтобы определить, какая строка выбрана в списке с возможностью выбора одной строки, проверяется свойство selection выбранной строки:
mySelection = myList.selection;
Чтобы уяснить, что делается в этом учебном скрипте, воспользуемся другим примером отклика на событие, он называется onChange и отвечает на изменения в управлении окном. Добавим отклик в скрипт, проверяющий список:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["один", "два", "три"]); myList.onChange = function () { $.writeln (myList.selection) } w.show ();
Запустим скрипт, выберем два, и программа выведет на экран слово два. Это выглядит как текст, но если проверить результат выбора таким образом:
if (myList.selection == "два")
то результат будет false.
Причина в том, myList.selection возвращает не текст, а объект типа ListItem.
Изменим скрипт так:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["one", "two", "three"]); myList.onChange = function (){$.writeln (myList.selection.constructor.name)} w.show ();
Теперь на экран будет выведено значение ListItem. Для получения содержимого этого объекта ListItem получите его свойство text:
if (myList.selection.text == "two")
Другое полезное свойство этого объекта — это index, который определяет положение строки в списке:
if (myList.selection.index == 2)
Определение, какие из элементов списка выбраны
Выбор нескольких объектов в списке отличается от предыдущего случая тем, что это массив объектов списка. Изменим предыдущий скрипт:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["one", "two", "three"], {multiselect: true}); myList.onChange = function (){$.writeln (myList.selection.constructor.name)} w.show ();
Запустим его, и на экран будет выведен массив. Массив элементов списка обрабатывается, как любой массив в JavaScript. Следующий скрипт напечатает содержимое выбранного списка:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["one", "two", "three"], {multiselect: true}); var b = w.add ("button", undefined, "Print list"); b.onClick = function () { for (var i = 0; i < myList.selection.length; i++) $.writeln (myList.selection[i].text) } w.show ();
Обработка списков
Списки — это массивы объектов типа ListItem. Они обрабатываются несколько иначе, нежели обычные массивы. Следующий скрипт обрабатывает список просто печатью атрибута текста каждого элемента:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["one", "two", "three"]); var b = w.add ("button", undefined, "Print"); b.onClick = function () { for (var i = 0; i < myList.items.length; i++) $.writeln (myList.items[i].text); } w.show ();
Поиск объекта в списке
Для этого используется метод find:
var myItem = myList.find ("two");
Метод возвращает объект типа ListItem, если объект найден, и null, если объекта в списке нет.
Вставка объектов в список
Ранее мы видели, что объекты могут быть добавлены в существующий список методом .add (“list”). Это всегда добавляет объекты в конец списка. Для помещения объекта в определенное место, включите индекс назначения. Например, чтобы добавить объект в начало списка, воспользуйтесь такой строкой:
myList.add ("item", "zero", 0);
Чтобы избежать дублирования записей в массиве, можно использовать метод find, чтобы проверить, есть ли уже такой объект в массиве:
(myList.find (myNewItem) != null) myList.add ("item", myNewItem);
При добавлении объекта в массив окно обновляется автоматически, как показано ниже:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, ["one", "two", "three"]); var b = w.add ("button", undefined, "Add"); b.onClick = function () {myList.add ("item", "zero", 0)} w.show ();
Упорядочение списков
Вот пример обработки списка — вставка объекта в список и сортировка обновленного списка по алфавиту. Программа активирует приглашение, поэтому можно ввести букву незамедлительно. Заметьте, что функция управления окном необязательно должна быть определена в том блоке, что определяет окно (т.е. между операторами new Window и w.show()).
var w = new Window ("dialog"); var myList = w.add ("listbox", [0, 0, 50, 150], ["A", "K", "X"]); var input = w.add ("edittext"); input.active = true; var b = w.add ("button", undefined, "Insert", {name: "ok"}); b.onClick = function () {insert_item (myList, input.text); input.text = ""} w.show ();
function insert_item (list_obj, new_item) { if (list_obj.find (new_item) == null) { var stop = list_obj.items.length; var i = 0; while (i < stop && new_item > list_obj.items[i].text) i++; list_obj.add ("item", new_item, i); } }//fnc
Интерфейс скрипта несколько неуклюжий, и кнопка ОК названа Insert — нажатие на клавишу Enter запускает функцию отклика на событие onClick. Далее мы покажем, как обрабатывать такие ситуации более элегантно, определив обработчик событий (event handler), а не использовать кнопку для этой цели.
Перемещение объектов списка
Для перемещения объектов в пространстве списка нужно иметь две кнопки: одна для перемещения выбранного объекта вверх, и другая — для перемещения вниз. Также нужна функция перестановки рядом стоящих объектов:
var w = new Window ("dialog", "Rearrange"); var list = w.add ("listbox", undefined, ["one", "two", "three", "four", "five"]); list.selection = 1; var up = w.add ("button", undefined, "Up"); var down = w.add ("button", undefined, "Down"); up.onClick = function () { var n = list.selection.index; if (n > 0) { swap (list.items [n-1], list.items [n]); list.selection = n-1; } } down.onClick = function () { var n = list.selection.index; if (n < list.items.length-1) { swap (list.items [n], list.items [n+1]); list.selection = n+1; } } function swap (x, y) { var temp = x.text; x.text = y.text; y.text = temp; } w.show ();
На самом деле объекты списка остаются на месте, меняются местами их свойства text, это делается функцией swap().
Удаление объектов из списка
Используйте метод .remove(), чтобы удалить объект из списка. Например, чтобы удалить третий объект из списка:
myList.remove (myList.items[2]);
Для удаления объекта, указав его имя, используйте этот метод так:
myList.remove (myList.find ("two"));
Добавление иллюстраций в список
Объекты списка могут включать иллюстрации, вот пример:
var descriptions = ["Footnotes", "Masters", "Locked stories"]; var imgs = ["footnotes.idrc", "masters.idrc", "locked_stories.idrc"]; var w = new Window ("dialog"); var myList = w.add ("listbox"); for (var i = 0; i < descriptions.length; i++) { myList.add ("item", descriptions[i]); myList.items[i].image = File ("~/Desktop/"+imgs[i]) } w.show ();
Первые две строки создают массивы имен иллюстраций и текстовые названия иллюстраций. Затем цикл for добавляет имена объектов, а затем сами иллюстрации. (Аналогично кнопкам-пиктограммам, изображения могут быть в PNG, IDRC или JPG формате).
Списки в несколько колонок
Такие списки позволяют создавать таблицы, отражающие структуру, с общими заголовками. Вот пример:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, "", {numberOfColumns: 3, showHeaders: true, columnTitles: ["English", "French", "Dutch"]}); with (myList.add ("item", "One")) { subItems[0].text = "Un"; subItems[1].text = "Een"; } with (myList.add ("item", "Two")) { subItems[0].text = "Deux"; subItems[1].text = "Twee"; } with (myList.add ("item", "Three")) { subItems[0].text = "Trois"; subItems[1].text = "Drie"; } w.show ();
Ширины колонок определяются автоматически, но можно задать ширину вручную, определив значение свойства columnWidths.
Обратите внимание, при добавлении списка использовались свойства showHeaders и columnTitles, которыми были добавлены названия колонок.
Текст, не поместившийся в колонку установленного пользователем размера, будет обрезан, и эта потеря текста будет отмечена многоточием:
var w = new Window ("dialog"); var myList = w.add ("listbox", undefined, "", {numberOfColumns: 3, showHeaders: true, columnTitles: ["English", "French", "Dutch"], columnWidths: [30,30,100]});
Иллюстрации могут добавляться в любую из строк любой из колонок:
with (myList.add ("item", "One")) { subItems[0].text = "Un"; subItems[0].image = myFile_1; subItems[1].text = "Een"; subItems[1].image = myFile_2; }
Элемент интерфейса dropdownlist (выпадающий список)
Выпадающие списки по многим аспектам схожи со списками (listbox), основное различие в том, что вы видите только одну строку списка, если он свернут, а в развернутом списке можно выбрать только одну строку. Если бы можно было выбирать несколько строк, то это было бы то же самое, что описанный ранее список с возможностью выбора нескольких объектов.
Вот пример выпадающего списка:
var w = new Window ("dialog"); var myDropDown = w.add ("dropdownlist", undefined, ["one", "two", "three"]); myDropDown.selection = 1; w.show ();
Чтобы узнать, какая стока выбрана, воспользуйтесь свойством text:
myChoice = myDropDown.selection.text;
Можно также узнать индекс выбранной строки
myChoice = myDropDown.selection.index;
Так же как со списками, в выпадающий список можно помещать изображения:
myDropDown.items[0].image = myImage
Элемент интерфейса treeview (древовидная структура)
Treeview это древовидная структура, похожая на дерево папок, которое мы видим в менеджере файлов. Вот пример:
var w = new Window ("dialog"); var myTree = w.add ("treeview", [0, 0, 100, 150]); var myDigits = myTree.add ("node", "Digits"); myDigits.add ("item", "one"); myDigits.add ("item", "two"); myDigits.add ("item", "three"); var myNames = myTree.add ("node", "Names"); myNames.add ("item", "Winnie"); myNames.add ("item", "Piglet"); myNames.add ("item", "Tigger"); myDigits.expanded = true; myNames.expanded = true; w.show ();
По умолчанию все вложенные списки свернуты (в таких списках их часто называют узлами). Чтобы развернуть любой из них, дважды щелкните по названию, или один раз по плюсику, предваряющему название списка.
Чтобы развернуть содержимое узла при открытии окна, надо свойству expanded разворачиваемого узла назначить значение true, в нашем примере есть узлы myDigits и myNames, строки myDigits.expanded = true и myNames.expanded = true инициируют развертывание этих узлов при открытии окна w.
Насколько мне известно, невозможно при развертывании такого окна указать, какая из строк выбрана.
Можно вкладывать узел в узел, создавая таким образом многоуровневые древовидные структуры. Вот пример:
var w = new Window ("dialog"); var myTree = w.add ("treeview", [0, 0, 120, 170]); var myDigits = myTree.add ("node", "Digits"); myDigits.add ("item", "one"); myTwo = myDigits.add ("node", "two"); myTwo.add ("item", "twee"); myTwo.add ("item", "deux"); myTwo.add ("item", "dwa"); myDigits.add ("item", "three"); var myNames = myTree.add ("node", "Names"); myNames.add ("item", "Winnie"); myNames.add ("item", "Piglet"); myNames.add ("item", "Tigger"); myDigits.expanded = true; w.show ();
Пример использования элемента интерфейса treeview можно найти в скрипте Габе Харба (Gabe Harbs), демонстрирующего иерархию создания стилей абзаца и скрипте Питера Карела для работы GREP-операторами.
Элемент интерфейса tabbedpanel (панель с вкладками)
Это еще один вариант контейнера данных в пользовательском интерфейсе (работает в скриптах, начиная с версии CS4). Панель вкладок определяется посредством идентификатора tabbedpanel, а вкладка — посредством tab. Вы знакомы с этим средством, т.к. InDesign использует его во многих диалогах. И следующий скрипт частично воспроизводит один из таких диалогов с использованием вкладок, а именно экспорт XML-данных. Пользователь не может управлять оформлением этих вкладок.
var w = new Window ("dialog", "Export XML", undefined, {closeButton: false}); w.alignChildren = "right"; var tpanel = w.add ("tabbedpanel"); tpanel.alignChildren = ["fill", "fill"]; tpanel.preferredSize = [350,300]; var general = tpanel.add ("tab", undefined, "General"); general.alignChildren = "fill"; var g_options = general.add ("panel", undefined, "Options"); g_options.alignChildren = "left"; g_options.dtd_decl = g_options.add ("checkbox", undefined, "Include DTD Declaration"); g_options.view_XML = g_options.add ("checkbox", undefined, "View XML Using: "); g_options.export_sel = g_options.add ("checkbox", undefined, "Export From Selected Element"); g_options.export_untagged = g_options.add ("checkbox", undefined, "Export Untagged Tables as CALS XML"); g_options.remap = g_options.add ("checkbox", undefined, "Remap Break, Whitespace, and Special Characters"); g_options.xslt = g_options.add ("checkbox", undefined, "Apply XSLT: "); g_options.add ("statictext", undefined, "Encoding: "); var images = tpanel.add ("tab", undefined, "Images"); images.alignChildren = "fill"; var img_options = images.add ("panel", undefined, "Image Options"); var buttons = w.add ("group"); buttons.add ("button", undefined, "Export", {name: "ok"}); buttons.add ("button", undefined, "Cancel"); w.show ();
{на нашем сайте мы рассматривали скрипт по работе с вкладками}
Элемент интерфейса progressbar (индикатор выполнения задания)
Этот элемент управления используется для вывода на экран одной или нескольких линий, отображающих ход исполнения задания. В основе простая идея — длительность линии и время исполнения скрипта связаны между собой. Пока не было лучшего примера использования этого инструмента, кроме скрипта Марка Аутрета (Marc Autret)
Вот код этого скрипта:
#targetengine "session" var ProgressBar = function(/*str*/title) { var w = new Window('palette', ' '+title, {x:0, y:0, width:340, height:60}), pb = w.add('progressbar', {x:20, y:12, width:300, height:12}, 0, 100), st = w.add('statictext', {x:10, y:36, width:320, height:20}, ''); st.justify = 'center'; w.center(); this.reset = function(msg,maxValue) { st.text = msg; pb.value = 0; pb.maxvalue = maxValue||0; pb.visible = !!maxValue; w.show(); }; this.hit = function() {++pb.value;}; this.hide = function() {w.hide();}; this.close = function() {w.close();}; }; //------------------------------------------------ // SAMPLE CODE //------------------------------------------------ function main() { var pBar = new ProgressBar("Script Title"); var i; // Routine #1 pBar.reset("Processing Routine #1...", 100); for( i=0 ; i < 100; ++i, pBar.hit() ) { $.sleep(10); } // Routine #2 var i; pBar.reset("Processing Routine #2...", 10); for( i=0 ; i < 10; ++i, pBar.hit() ) { $.sleep(300); } pBar.close(); } main();
Размер и положение
Координаты окна могут быть установлены, можно определить размер и положение любого элемента окна. Но не требуется часто точно определять эти значения, т.к. встроенный инструмент создания окна работает очень хорошо, и измерение размеров требуется очень редко.
Как позиционировать окно и элементы окна, хорошо объяснено в документе Tools Guide (см. раздел Window Layout, имеющееся во всех редакциях этого документа), поэтому тут не будем останавливаться на этом. Скажем только об одной или двух непредвиденных проблемах, которых следует остерегаться.
Свойство maximumWidth дает неверные результаты при работе в системе с двумя экранами. Допустим, у вас есть два 24-дюймовых монитора с разрешением 1920х1200, имеющих общий экран. Свойство окна maximumSize.height вернет корректное значение 1150 (1200 минус 50 точек на бордюр, например), но свойство maximumSize.width вернет 3790, будто бы у меня экран такой ширины, тогда как ожидалось, что будет возвращено число порядка 1900. Таким образом, свойство width рассматривает пространство обеих экранов как один. Это создаст трудности в верном позиционировании окон на экранах. Чтобы обойти эту особенность, надо использовать оператор $.screens. Он возвращает массив объектов, отображающих координаты. Обратите внимание, что этот оператор — часть ESTK, а не ScriptUI.
Следующий скрипт отображает координаты всех экранов:
for (var i = 0; i < $.screens.length; i++) { $.writeln ("Screen " + i); $.writeln ("top: " + $.screens[i].top); $.writeln ("left: " + $.screens[i].left); $.writeln ("bottom: " + $.screens[i].bottom); $.writeln ("right: " + $.screens[i].right); }
Screen 0
top: 0
left: 0
bottom: 1200
right: 1920
Screen 1
top: 0
left: 1920
bottom: 1200
right: 3840
Обратите внимание, что значения, возвращаемые строкой $.screens, не совпадают со значениями свойства maximumSize.
Подводя итог, можно сказать, что в двухэкранных системах нельзя пользоваться оператором maximumSize.width.
Шрифты
Стандартный размер шрифта обычно очень мал, и хочется сделать его чуть крупнее. Используемый шрифт обычно Tahoma или что-то похожее на неё. Самый простой способ управления размером — определить его при указании гарнитуры:
var w = new Window ("dialog"); button1 = w.add ("button", undefined, "Default"); button2 = w.add ("button", undefined, "Bigger"); button2.graphics.font = "Tahoma:18"; w.show ();
Обратите внимание, что в таком способе можно только определить название шрифта и размер, и ничего более. Если надо определить еще и начертание, то для этого предусмотрено другое решение:
var w = new Window ("dialog"); button1 = w.add ("button", undefined, "Default"); button2 = w.add ("button", undefined, "Big and bold"); button2.graphics.font = ScriptUI.newFont ("Tahoma", "Bold", 18); w.show ();
Если не важно, какая гарнитура используется в окне, а важны только размер букв и начертание, то можно указать для использования в текущем окне стандартный системный шрифт, определив его начертание и размер букв:
button2.graphics.font = ScriptUI.newFont (ScriptUI.applicationFonts.palette.name, "Bold", 18);
К сожалению, невозможно за один раз определить шрифты для всех окон, групп или панелей, для каждого варианта это надо делать отдельно. Вот такая функция упростит решение этой задачи:
function set_font (control, font) { for (var i = 0; i < control.children.length; i++) { if ("GroupPanel".indexOf (control.children[i].constructor.name) > -1) set_font (control.children[i], font); else control.children[i].graphics.font = font; } }
Используйте её для определения параметров шрифта всех объектов окна:
var w = new Window ("dialog"); var group1 = w.add ("group"); var button1 = group1.add ("button", undefined, "B1"); var button2 = group1.add ("button", undefined, "B2"); var group2 = w.add ("group"); var button1 = group2.add ("button", undefined, "B3"); var button2 = group2.add ("button", undefined, "B4"); set_font (w, "Tahoma:18"); w.show();
Или шрифта отдельной группы:
set_font (group1, "Tahoma:18");
Замечание: в Windows невозможно управлять размером шрифта в заголовке окна.
Цвета
Цвета, как и шрифты, — это часть управления графикой ScriptUI. Но если шрифтами управлять легко, то о цвете, кистях и других особенностях графики этого не скажешь. И не особо помогает почти полное отсутствие каких-либо толковых примеров как использовать эти графические элементы. InDesign/ESTK имеет два скрипта, где есть примеры, как устанавливать цвета переднего плана и фона, и это всё, что есть о цвете.
В приводимых ниже примерах показано, как управлять шрифтом, его размером и начертанием, а также цветами переднего и заднего планов. Цвет определен как матрица из трех чисел в диапазоне от 0 до 1 (т.е. это RGB-цвета), и дополнительно числом в диапазоне от 0 до 1 можно определять прозрачность (0 — полностью прозрачен, 1 — абсолютно непозрачен, но эта опция в Windows не работает).
Пример ниже скомпонован из тех двух скриптов из комплекта поставки, ColorSelector.jsx и ColorPicker.jsx.
var w = new Window ("dialog"); var s = w.add ("statictext", undefined, "Static"); var e = w.add ("edittext", undefined, "Edit"); var b = w.add ("button", undefined, "Button"); // The window's backround w.graphics.backgroundColor = w.graphics.newBrush (w.graphics.BrushType.SOLID_COLOR, [0.5, 0.0, 0.0, .2], 1); // Font for the first item, statictext s.graphics.font = ScriptUI.newFont ("Helvetica", "Bold", 30); s.graphics.foregroundColor = s.graphics.newPen (w.graphics.PenType.SOLID_COLOR, [0.7, 0.7, 0.7, 1], 1); // Font and colours for the second item, edittext e.graphics.font = ScriptUI.newFont ("Letter Gothic Std", "Bold", 30); e.graphics.foregroundColor = e.graphics.newPen (e.graphics.PenType.SOLID_COLOR, [1, 0, 0, 1], 1); e.graphics.backgroundColor = e.graphics.newBrush (e.graphics.BrushType.SOLID_COLOR, [0.5, 0.5, 0.5, 1], 1); // Font for the tird control, a button. Can't set colours b.graphics.font = ScriptUI.newFont ("Minion Pro", "Italic", 30); w.show ();
Похоже, есть проблемы в назначении цвета кнопкам, это обсуждалось на форуме Adobe , где Дирк Бекер предложил вариант решения этой проблемы.
Линии
Есть два способа нарисовать линию. Можно использовать графический объект ScriptUI, это весьма замороченный инструмент, но с его помощью можно делать узкие панели, имитирующие вертикальные и горизонтальные линии. Можно проводить линии, начиная с определенной точки, как в этом примере:
var w = new Window ("dialog"); w.add ("panel", [0,0,200,3]); w.add ("panel", [0,20,200,23]); w.add ("panel", [100,0,103,50]); w.show();
Первая линия [0,0,200,3] длиной 200 пикселей и толщиной 3 пикселя. {Вторая линия выглядит точно так же как первая, но только расположена ниже. Это обусловлено тем, что формат координат линии такой: [X1, Y1, X2, Y2].} Третья линия вертикальная, длиной 50 пикселей и толщиной 3 пикселя. {В описании линии заданы координаты точек начала и конца линии, но за счет того, что по умолчанию все объекты окна выравниваются по центру, эта линия размещена по центру окна. Если задать линию с координатами [10, 0, 13, 50], то на экране она будет размещена точно так же, как линия из кода программы с координатами [100, 0, 103, 50].}
Узкие панели используются для создания вертикальных линий, пустых панелей.
Неудобство описания линий указанием абсолютных значений координат её начальной и конечной точек состоит в том, что при изменении окна всегда приходится работать с линиями, и это может быть очень кропотливым занятием. Чтобы избежать этого, вы можете использовать менеджер макетов программы ScriptUI, — это самый оптимальный метод — используйте атрибут выравнивания fill, тогда размеры линий будут выравниваться со смежными панелями. Сделав это однажды, вы получите гибкую систему. Вот схематический пример такого подхода:
var w = new Window ("dialog"); w.alignChildren = ["fill","fill"]; var g1 = w.add ("group"); g1.alignChildren = ["fill","fill"]; var p1 = g1.add ("panel"); p1.preferredSize = [100, 50]; // Чтобы понять разницу, используйте [100,100] для второго варианта окна g1.separator = g1.add ("panel"); // Помещаем на экран вертикальную линию // Это ширина линии: g1.separator.minimumSize.width = g1.separator.maximumSize.width = 3; var p2 = g1.add ("panel"); p2.preferredSize = [100, 50]; w.separator = w.add ("panel"); // Помещаем на экран горизонтальную линию // Для программы этот параметр высота, но по сути это ширина линии! w.separator.minimumSize.height = w.separator.maximumSize.height = 3; var g2 = w.add ("group"); g2.alignChildren = ["fill","fill"]; var p3 = g2.add ("panel"); p3.preferredSize = [100, 50]; // Чтобы понять разницу, используйте [200,50] для второго варианта окна g2.separator = g2.add ("panel"); // Помещаем на экран вертикальную линию g2.separator.minimumSize.width = g2.separator.maximumSize.width = 3; var p4 = g2.add ("panel"); p4.preferredSize = [100, 50]; w.show ();
Поскольку для окна и двух групп используется выравнивание fill, при изменении объектов в группе длина линий тоже изменяется. Чтобы увидеть это, измените строку p1.preferredSize = [100, 50] на p1.preferredSize = [100, 100], а строку p3.preferredSize = [100, 50] на p3.preferredSize = [200, 50], чтобы получить другой вариант оформления окна:
(Замечание: замороченный на первый взгляд оператор w.separator.minimumSize.height = w.separator.maximumSize.height необходим, т.к. объекты в ScriptUI не имеют отдельной ширины и высоты, которые могли бы быть заданы. Поэтому мы говорим, что линии должны быть не менее и не более 3 пикселей, т.е. точно 3 пикселя.)
Callbacks (отклики на события)
Отклики на события — это встроенные методы, отслеживающие события в диалогах: нажатие кнопки, выбор строки в списке, завершение редактирования, и т.д. В руководстве Tools Guide для версии CS5 перечень откликов приведен на страницах 83 и 147. Видимо, наиболее часто используется отклик onClick, демонстрирующийся в следующем скрипте:
var w = new Window ("dialog"); var b1 = w.add ("button", undefined, "Show this"); var b2 = w.add ("button", undefined, "Show that"); b1.onClick = function () {$.writeln (this.text + " clicked.")} b2.onClick = function () {$.writeln (this.text + " clicked.")} w.show ();
Выше показаны окно и консоль после нажатия обеих кнопок. Нажатие на кнопку выводит на консоль её имя.
Код функции отклика на примере нажатия кнопки b1 — это просто {alert(this.text+ » clicked. «} может быть сколь угодно сложным. Принцип обработки других откликов точно такой же.
Другой часто использующийся отклик — это onChange, применяемый в нескольких типах элементов управления. Вот пример, отслеживающий ввод текста в редактируемое поле:
var w = new Window ("dialog"); var e1 = w.add ("edittext"); var e2 = w.add ("edittext"); e1.active = true; e1.characters = e2.characters = 20; e1.onChange = function () {e2.text = e1.text} w.show ();
Скрипт отображает два пустых текстовых поля. После набора текста в первом окне и нажатия клавиши перевода строки или клавиши табуляции этот текст будет скопирован во второе поле.
Обратите внимание, что этот оклик не активизируется раньше, чем вы завершите ввод текста.
Для отслеживания событий со время ввода текста надо использовать обработчики событий (см. ниже).
Работа со списками также может отслеживаться. Вот скрипт, отображающий трехстрочный список с выбранной первой строкой. Выбор любой строки в списке будет отображен на консоли.
var w = new Window ("dialog"); var list = w.add ("listbox", undefined, ["ОДИН", "ДВА", "ТРИ"]); list.selection = 0; list.onChange = function () {$.writeln (this.selection.text + " ВЫБРАНО.")} w.show ();
Вот вывод на консоль после щелчка на строке ТРИ.
Event handlers (обработчики событий)
Обработчики событий сходны с откликами на события в том, что они отслеживают события в диалогах. Но они более гибки, хотя эта гибкость оборачивается некоторой сложностью. Обработчики событий обсуждаются на странице 149 руководства Tools Guide для версии CS5. Два примера иллюстрируют обработчики: первый отслеживает работу с мышью, второй — с клавиатурой.
Отслеживание операций с мышью
Вот как контролируются состояния действий с мышью и некоторые состояния программного окружения:
var w = new Window ("dialog"); var b = w.add ("button", undefined, "Qwerty"); b.addEventListener ("mousedown", function (k) {whatsup (k)}); function whatsup (p) { if (p.button == 0) {$.writeln ("Нажата левая кнопка.")} if (p.button == 2) {$.writeln ("Нажата правая кнопка.")} if (p.altKey) {$.writeln ("При щелчке мышкой нажата клавиша Alt.")} $.writeln ("X: " + p.clientX); $.writeln ("Y: " + p.clientY); } w.show ();
Здесь mousedown означает «по щелчку» и может трактоваться как отклик onClick с дополнительными возможностями (похожие типы событий — это mouseup /отклик на отпускание кнопки мыши/ и mouseover /отклик на случай, когда курсор проходит над объектом/).
Эти выводимые на консоль свойства — какая кнопка мыши нажата, нажата ли хоть одна из управляющих клавиш — просто отображение сделанного выбора, полный список выводимых свойств этого обработчика событий изложены на странице 153 упомянутого ранее руководства.
В нашем примере значения clientX и clientY отображают координаты курсора в пространстве кнопки, это можно использовать для определения — в правой или левой половине кнопки был щелчок.
Мониторинг клавиатуры
Для отслеживания работы с клавиатурой определим перехватчик события (event listener) при помощи события keydown. Вот скрипт, демонстрирующий некоторые свойства этого события работы с клавиатурой:
var w = new Window ("dialog"); var edit = w.add ("edittext"); edit.active = true; edit.characters = 30; w.addEventListener ("keydown", function (kd) {pressed (kd)}); function pressed (k) { $.writeln (k.keyName); $.writeln (k.keyIdentifier); $.writeln (k.shiftKey ? "Shift pressed" : "Shift not pressed"); $.writeln (k.altKey ? "Alt pressed" : "Alt not pressed"); $.writeln (k.ctrlKey ? "Ctrl pressed" : "Ctrl not pressed"); } w.show ();
У каждой клавиши есть имя (А, D, Space, Shift, …) и код (шестнадцатеричное значение в формате U+0000 или имя, если это одна из управляющих клавиш), если клавиша нажата одновременно с управляющей клавишей, то выводится информация об этом.
Следующий скрипт отображает список, в котором можно перемещаться с помощью клавиш _ стрелка_вверх/стрелка вниз или PgUp/PgDn. При нажатии на клавишу PgUp выбирается первая строка списка, при нажатии PgDn — последняя.
Следующий скрипт отображает список, в котором можно перемещаться с помощью клавиш _ стрелка_вверх/стрелка вниз или PgUp/PgDn.
При нажатии на клавишу PgUp выбирается первая строка списка, при нажатии PgDn — последняя.
var w = new Window ("dialog"); var list = w.add ("listbox", undefined, ["one", "two", "three", "four"]); list.selection = 0; w.addEventListener ("keydown", function (k) {move_highlight (k.keyName)}); function move_highlight (key) { function go_down () { if (list.selection.index < list.items.length-1) list.selection = list.selection.index+1; else list.selection = 0; } // go_down function go_up () { if (list.selection.index == 0) list.selection = list.items.length-1; else list.selection = list.selection.index-1; } // go_up switch (key) { case "Up": go_up (); break; case "PageUp": list.selection = 0; break; case "PageDown": list.selection = list.items.length-1; break; case "Down": go_down (); break; } } w.show ();
Ресурсы
Фактически настоящим всеобъемлющим информационным ресурсом о ScriptUI является глава в руководстве Tools Guide, которое есть в комплекте файлов ESTK, его можно найти в меню справочника (Help).
Объектную модель ESTK можно просматривать с помощью вьюера. В замечательной коллекции информационных ресурсов Jongware есть информация об объектных моделях разных версий индизайна.
Другой источник информации — коллекция скриптов в составе ESTK, ищите его на своей машине.
Также есть много блогов и форумов, посвященных скриптингу.
Блоги
Marc Autret’s Indiscript: http://www.indiscripts.com/
Marijan Tompa’s InDesign Snippets: http://indisnip.wordpress.com/
Форумы по отдельным темам
http://forums.adobe.com/community/indesign/indesign_scripting
Изменение цвета кнопок
http://forums.adobe.com/message/2335096#2335096)
Изменение размера окна
http://forums.adobe.com/message/2280793#2280793
http://forums.adobe.com/message/2741942#2741942
Кнопки-пиктограммы
http://forums.adobe.com/message/2326630#2326630
http://forums.adobe.com/message/2899148#2899148
Панели с прокруткой
http://forums.adobe.com/message/2899148#2899148
индикатор выполнения задания
http://forums.adobe.com/message/3152162#3152162
Два интерактивных компоновщика диалоговых окон
Совершенно иной тип ресурсов можно найти на сайтах http://www.scriptui.com/ и http://www.scriptuibuilder.com/ . Эти программы помут вам создать диалоговые окна, но не дадут знаний об инструментах ScriptUI, если вы, конечно, не займетесь вскрытием кода этих программ.
Перевод:
Михаил Иванюшин
ivanyushin#yandex.ru
2010
2 — 2002
Кому и зачем?
Среда разработки
Базовые понятия
Объектные ссылки
Классы объектов
Наследование свойств
Переменные
Операторы
Команды и методы
Условные выражения
Структуры управления
Координатная сетка
Переходим к практике
Отступление для читателей, не знакомых
с программированием
Идея создания настоящего материала возникла летом, во время
подготовки обзорной статьи «Лед тронулся, или Приключения InDesign в России»
(КомпьюАрт №7’2001). Тогда авторам было мало что сказать по существу вопроса.
Сейчас же ситуация изменилась. Полгода мы проработали в InDesign и добились,
на наш взгляд, выдающегося результата — ВЕСЬ «КомпьюАрт» верстается в этом замечательном
издательском пакете. Номер, который у вас сейчас в руках, уже третий, полностью
подготовленный в среде InDesign1. Нам очень
интересно и комфортно работать в нем — во многом благодаря постоянному ощущению
свободы и всесильности, возникающему на всех стадиях издательского процесса.
Важной составляющей этой свободы является возможность гибкого программирования
собственных задач и высвобождения собственного Времени для достойных дел. Ребята
из Adobe Systems проделали отличную работу и хорошо постарались ради существования
этой возможности.
Кому и зачем?
Дефинируем предмет рассмотрения. Скрипт — серия команд, указывающая InDesign,
какие действия ему следует выполнять в определенный момент времени при соблюдении
или несоблюдении соответствующих условий. Эти действия могут быть как одиночными
и влиять исключительно на один, выбранный в данный момент объект, так и входить
в состав чрезвычайно сложной структуры, влияющей на многие объекты и публикации.
Таким образом, скриптинг2 — увлекательный
и творческий процесс, позволяющий решать посредством несложного программирования
абсолютно любую задачу, выполнимую в InDesign штатными средствами (работа с инструментами,
меню, палитрами, диалогами).
Входящие в состав скрипта процедуры и операторы могут касаться как InDesign
непосредственно, так и затрагивать внешние приложения: текстовые редакторы,
электронные таблицы, СУБД, ГИС- и CAD-системы. Более того, скриптинг в среде
InDesign может служить не только целям автоматизации часто повторяющихся операций,
но и являться продвинутым дизайнерским инструментом. Например, задачи случайного
выбора гарнитуры и цвета символа в строке текста, равномерного изменения кегля
от начала до конца строки в каждом символе, в конце концов просто свободного
распределения литер на полосе (распространенный дизайнерский прием) — все это
без применения скриптинга кажется тяжеловесным и трудновыполнимым.
Скриптинг доступен не только профессиональным разработчикам программного обеспечения.
Более того, он для них не предназначен. Верстальщику — «версталово», а программисту —
«программерово». Для профессиональных разработчиков существует SDK — Software
Development Kit for InDesign, который Adobe Systems предоставляет в свободном
доступе. Скриптинг же доступен каждому пользователю InDesign.
Широкое распространение InDesign и появление достаточного количества пользователей,
способных программировать свои задачи и добиваться максимальной эффективности
своей работы, способны взорвать и кардинально изменить сложившееся за 10 лет
эпохи Десктопа представление о профессии верстальщика. К глубокому сожалению
авторов, авторитет зубров-метранпажей3 и их
традиционно высокое в негласной иерархии типографских работников место остались
в прошлом. Ныне в основном превалирует отношение к верстальщику, как к низкоквалифицированной
рабочей силе, что-то вроде «посадимдевочкузалитьтекстнаполосы». Надо отметить,
что некоторые горе-«верстальщики» сильно способствуют этому. Но речь не о них.
Владение скриптингом может и должно стать основным аргументом верстальщика при
трудоустройстве. Ведь экономия времени, необходимого для выполнения рутинных
задач, в разы — серьезное повышение эффективности допечатного процесса, суть —
прямое конкурентное преимущество предприятия. А какое наслаждение запустить
скрипт собственного изготовления и наблюдать за тем, как публикация верстается
«сама»! Скриптинг — как процесс, безусловно, творческий — способен одухотворить
деятельность верстальщика, придать ей шарм и избавить от ощущения «одного и того
же». Наконец, полномасштабное владение скриптингом и знание общей типографской
культуры могут служить серьезным источником дополнительного дохода. Ни один
программист (если он никогда не занимался версткой) не в состоянии элементарно
сформулировать задачу по автоматизации издательского процесса, не говоря уже
о ее реализации и отладке. Разумеется, речь здесь идет не о глобальных плагинах
и дополнениях, над которыми работают целые коллективы специалистов, а о маленьких
скриптиках, учитывающих особенности и потребности конкретного издательского
процесса, но дающих в итоге огромную экономию временных ресурсов.
Надеемся, что необходимость и полезность освоения скриптинга в InDesign очевидна
всем. Итак, приступим!
Среда разработки
До единого аппаратно-платформенного стандарта в DTP-индустрии очень далеко,
и с программной средой разработки, отлаживания и исполнения скриптов для InDesign
ситуация обстоит так же, как и во всей отрасли. Для PC пишем на Visual Basic,
для InDesign под Mac OS — на AppleScript. К сожалению, конструкции скриптов
для InDesign под этими программными средами отличаются семантикой, но логика
работы одна и та же. Авторы не имеют возможности тестировать и отлаживать скрипты
под Macintosh, поэтому, не желая отбирать хлеб у наших коллег, приверженцев
платформы Apple, мы лишь кратко остановимся на сути скриптинга под Mac OS, а в дальнейшем
будем рассматривать в качестве программной среды Visual Basic (VB). К тому же
предварительный анализ семантических конструкций обеих программных сред позволяет
надеяться на появление в недалеком будущем скрипт-конверторов VB « AppleScript.
Итак, для успешного скриптинга в InDesign на платформе Apple нам необходимо
наличие в системе интерпретатора AppleScript, который входит в стандартную поставку
любой из Mac OS, и одного из доступных редакторов (AppleScript editor, Scripter,
Script Debugger, etc.)
Для скриптинга в InDesign на платформе Windows необходимо установить Microsoft
Visual Basic либо использовать любое приложение, содержащее Visual Basic for
Applications (VBA). Такие пакеты, как MS Office, AutoCAD, Corel, Visio и др.,
содержат в составе поставки VBA. InDesign, к сожалению, пока не комплектуется
VBA, но вполне успешно его поддерживает. На сайте Adobe Systems, в форуме, посвященном
скриптингу в InDesign, появлялась неофициальная информация о том, что InDesign
2.0 будет снабжен необходимыми компонентами VBA для работы со скриптами непосредственно
в пакете4, но эти ожидания пока не оправдались.
Базовые понятия
В этой части материала, которую имеющие минимальный опыт программирования на
VB читатели вполне могут пропустить, дадим начальные сведения о конструкциях
Visual Basic и принципах скриптинга в InDesign.
В процессе обычной работы в среде InDesign мы работаем с фреймами и их содержимым,
применяем к ним цвета и стили, масштабируем, перемещаем и форматируем; открываем
публикации, перемещаемся по полосам и разворотам, размещаем элементы на них,
то есть всегда имеем дело с неким объектом.
При исполнении скрипта происходит то же самое, с той лишь разницей, что активной
стороной, влияющей на процесс, являемся не мы, как субъект взаимодействия с
пакетом, а скрипт, серия команд. С точки зрения InDesign не происходит ничего
незаурядного. Пакету отдается команда совершить действие А над объектом X. Если
это действие допустимо, оно выполняется.
Суть скриптинга заключается в объектной модели — описании всех доступных InDesign’у
объектов: публикаций, разворотов, полос и фреймов. При этом каждому типу присущи
свои специфические свойства, и каждый объект может быть однозначно идентифицирован.
Таким образом, скриптинг в InDesign является типичным случаем объектно-ориентированного
программирования. Схожие по тому или иному признаку объекты объединяются в классы
(classes), обладают свойствами (properties), манипуляции над объектами осуществляются
посредством методов (methods) в Windows или команд (commands) на Macintosh.
Объектные ссылки
Объекты в InDesign расположены иерархически, то есть фреймы принадлежат полосам,
полосы принадлежат публикации, которая, в свою очередь, принадлежит InDesign.
Для того чтобы подать команду какому-либо объекту, необходимо ее
направить по иерархической цепочке — указать «точный адрес» объекта. Адресация
объектов в VB идет от старшего объекта к младшему, в AppleScript — наоборот,
но четкая последовательность обращений к каждой иерархической ступени обязательна:
«Documents.Item(1).Spreads.Item(1). TextFrames.Item(1)» — Visual Basic; «the first text frame of the first spread of the first document» — AppleScript.
Вышеприведенные конструкции являются объектными ссылками (object reference)
и позволяют реализовывать принцип однозначности идентификации объекта. Таким
образом у каждого объекта существует уникальная объектная ссылка.
Классы объектов
Объекты со схожими свойствами объединяются в классы. Так, все типы фреймов —
прямоугольники, полигоны, овалы и фреймы свободной формы — принадлежат классу
объектов PageItems и обладают свойствами, общими для всех других типов объектов
этого класса. Например, свойство Geometric location является общим для всех
объектов класса PageItems.
Наследование свойств
Типы объектов класса наследуют ряд свойств этого класса. Прямоугольник наследует
свойство fill от класса PageItems, как и все прочие типы фреймов. Вместе с тем,
объекты могут обладать свойствами, которыми не обладают объекты другого типа
данного класса. У текстового фрейма есть свойство TextContents, которым фреймы
другого типа не обладают.
Типы данных
Поддерживаются данные пяти типов:
- Boolean (логический тип данных true or false);
- Integer (целое);
- Double (вещественные числа);
- String (строка символов, заключается в двойные кавычки);
- Array (массив данных любого типа).
Отдельно стоит описание данных как Variant, но об этом позднее.
Переменные
Переменные являются контейнерами для данных и могут содержать число, строку
текста или объект. У каждой переменной обязательно должно быть уникальное имя,
по которому мы к ней обращаемся. Присвоение значений переменным и последующее
их использование позволяет сделать скрипт универсальным и не зависящим от конкретной
ситуации, как это было бы при непосредственном использовании данных.
В AppleScript присвоение значений осуществляется с помощью оператора set:
set myNumber to 10 set myString to “Hello, World!” В Visual Basic при помощи оператора равенства (=): myNumber = 10 myString = “Hello, World!”
Операторы
Используются для выполнения вычислений над переменными и данными. Оператор возвращает
какое-либо значение, которое зависит от типа данных, над которыми
производятся вычисления. Это может быть как числовая величина (MyWidth/2),
так и логическое значение (в случае использования оператора сравнения MyWidth
> MyHeight).
Команды и методы
Команды в AppleScript и методы в VB по сути являются «глаголами», сообщающими
системе, что именно необходимо сделать с тем или иным объектом.
Так, в VB для создания нового объекта используется метод Add, для привязки
переменной к объекту — метод Set и оператор равенства (=) для изменения свойств
объекта.
В AppleScript команда make создает новый объект, set изменяет его свойства,
а get позволяет получить от объекта информацию о его свойствах.
Условные выражения
Условные выражения дают возможность скрипту в процессе исполнения анализировать
ситуацию и принимать то или иное решение в зависимости от выполнения условия.
Данные выражения всегда начинаются с оператора if. Следующий скрипт создает
новую публикацию, запрашивает InDesign о количестве текстовых материалов в ней
и, не обнаружив таковых, выводит сообщение5.
Private Sub Form_Load() Dim myInDesign As InDesign.Application Dim myPub As InDesign.Document Dim myStories As InDesign.Stories Set myInDesign = CreateObject (“InDesign. _ Application”) myNumberOfStories = myStories.Count If myNumberOfStories = 0 then MsgBox “В данном документе _ не содержится текстовых блоков” End If End Sub
Структуры управления
Предположим, что нам необходимо выполнить какое-либо действие несколько
раз подряд. Записать последовательно несколько строк, описывающих это действие?
А если существует необходимость в выполнении ста итераций? Для этих целей и
существуют структуры управления.
Следущие конструкции исполняют последовательности операторов скрипта (тело цикла)
заданное количество раз.
AppleScript: repeat with counter from 1 to 20 -- тело цикла end repeat Visual Basic: For counter = 1 to 20 rem тело цикла Next counter
Несколько более сложная конструкция управляющей структуры, которая выполняет
тело цикла до тех пор, пока ограничивающее условие истинно.
AppleScript repeat while myToDoCondition = true -- тело цикла end repeat Visual Basic Do While myToDoCondition = true rem тело цикла loop
Координатная сетка
Как и все современные пакеты верстки, InDesign использует стандартную 2D геометрию
для точного позиционирования объекта на полосе. Горизонтальный компонент координатной
пары (точки) обозначается как x, вертикальный — y. Эти координаты отображаются
в палитре Transform, при выборе объекта инструментом «указатель». Геометрический
ноль полосы в InDesign находится в левом верхнем углу полосы. Таким образом,
положительное направление по оси X — слева направо, а по оси Y — сверху вниз.
Важно помнить про последовательность записи координат объектов: сначала x, затем
y! InDesign ждет от нас именно такую запись. Следующий скрипт создает новую
публикацию, в ней новый объект, а затем перемещает его на 10 мм вправо и на
40 мм вниз.
AppleScript tell application “InDesign 1.5” set mySelection to selection move mySelection to {“10mm”, “40mm”} end tell Visual Basic Dim myInDesign as InDesign.Application Dim myPub as InDesign.Document Set myInDesign = CreateObject(“InDesign._ Application”) Set myPub = myInDesign.ActiveDocument myPub.Selection.Move Array(“10mm”,”40mm”)
Однако обратите внимание: при различных запросах InDesign выдает разные значения
координат. Координаты геометрической границы объекта и его видимой границы есть
различные массивы данных, включающие в себя по четыре значения: для верха (y),
левого края(x), низа (y) и правого края (x).
Переходим к практике
Специфика журнальной публикации не позволяет в полной мере развернуть все особенности
конструкций скриптинга и снабдить их подробными примерами, как это могло бы
быть в отдельном издании-учебнике. Но мы и не ставили перед собой подобную задачу.
В дальнейшем мы продолжим конспективное изложение основ скриптинга и его диалектов
на VB и AppleScript, главный же смысл серии публикаций, посвященных скриптингу,
мы видим в решении с его помощью конкретных издательских задач.
Подробное руководство по скриптингу доступно для свободного скачивания с сайта
Adobe Systems: http://www.adobe.com/products/indesign/pdfs/idsnscripting.pdf
Мы осваивали тонкости скриптинга в InDesign именно по этому руководству, в котором
подробно и с примерами описывается каждая семантическая конструкция диалектов
VB и AppleScript. Результатом наших экспериментов является появление и внедрение
в производственный процесс издательства «КомпьютерПресс» нескольких очень полезных,
на наш взгляд, облегчающих жизнь и экономящих время и верстальщикам и корректорам
издательства. Один из этих скриптов, текст которого приведен на следующей полосе,
мы предлагаем сегодня вашему вниманию. Наберите, протестируйте, отладьте, скомпилируйте
из него исполняемый файл и распространите его среди своих коллег. Их благодарность
не будет знать границ!
Верстка любого материала начинается с размещения текста на полосе и с его предобработки,
которая, как правило, происходит при помощи операций поиска и замены. Утомительное
занятие! Настоящий скрипт как раз и занимается предобработкой помещенного текста:
расставляет символы неразрывного пробела после каждого односимвольного слова,
удаляет двойные пробелы, заменяет там, где необходимо, дефис на тире и меняет
западные типографские кавычки (“лапки”) на принятые в отечественной типографике
(«елочки»).
Логика скрипта основана на анализе текущего символа и двух предыдущих. Для визуализации
процесса скрипт снабжен прогресс-индикатором, который вам необходимо
нарисовать в любом редакторе форм и включить в проект в виде файла zam.frm.
Скрипт, безусловно, можно оттачивать, модифицировать и усложнять. Можно добавить
процедуру предварительного выбора вариантов при помощи CheckBox: что включать
в список замен, а что нет. Можно добавить замену иксов между цифрами на знак
умножения (2×2 ® 2×2). Можно многое и не только с этим скриптом. Надеемся,
что настоящая публикация подвигнет вас к экспериментам, уважаемый коллега. Обязуемся
публиковать любой присланный нам законченный и работающий скрипт.
zlotnikov@compress.ru;
michnykin@mail.ru
КомпьюАрт 2’2002
Ivan @
15 / 11 / 2020 @
Blog /
InDesign / Вёрстка / Памятки
(InDesign / скрипты / скрипты в InDesign)
Время чтения: ~ 1 мин.
Обычные скрипты в InDesign устанавливаются в папку Scripts.
Startup-скрипты (как, например, скрипт, о котором шла речь ранее) надо установить в папку Startup Scripts — если ее нет, ее надо создать рядом с папкой Scripts Panel в папке Scripts.
А если вы хотите научиться круто работать в InDesign, вы можете записаться к нам на курс вёрстки для архитекторов.
Может быть интересно:
- Поменять картинки местами в InDesign
- Урок — Cлучайный поворот текста в InDesign
- Программы для вёрстки, кроме InDesign
- 5 причин наконец-то начать верстать в InDesign
- Поля ввода в InDesign (и прочих программах Adobe CC)
Копировать и отразить направляющие в InDesign
Поменять картинки местами в InDesign
▲
Подпишитесь на нас в социальных сетях!
◩ Instagram
▦ VK
▧ Facebook
▩ YouTube!
▨ Telegram!
Подпишитесь на обновления
* нажимая на кнопку «Подписаться», вы даете согласие на обработку своих персональных данных
В предыдущих статьях (в 2004 г. — «Скрипты под Illustrator: долой рутину!», № 7, с. 92; «Визитки на конвейере», № 8, с. 80; «Мал золотник, да дорог», № 10, с. 88; 2005 г. — «Календарь на автопилоте», № 6, с. 72) мы на примерах из практики разбирались со скриптингом под Illustrator. Теперь на очереди InDesign — количество операций, ждущих своей автоматизации, при вёрстке не меньше, чем в векторном пакете.
Скриптинг как средство быстрого выполнения большого объёма рутинной работы — вещь незаменимая. Разумеется, в дизайнерских программах, например, Photoshop и Illustrator CS, она не может проявить себя в полной мере: дизайн — процесс творческий, рутины в нём не так уж много. Зато верстальный пакет, такой как InDesign, — прекрасный кандидат для применения скриптов. Большие объёмы текста и иллюстраций, многочисленные графические элементы оформления, связи с внешними источниками — всё это диктует автоматизацию задач именно при сборке публикаций. Можно смело утверждать, что поддержка скриптинга — одно из главных преимуществ InDesign перед QuarkXPress, сыгравшее немаловажную роль при переходе верстальщиков в лагерь Adobe.
Документацию по скриптам для InDesign см. http://partners.adobe.com/public/developer/ indesign/devcenter.html и http://www.adobe.com/products/indesign/pdfs/ indesign_cs_scripting_guide.pdf. По полноте описания объектов последний документ несколько уступает описанию Illustrator. Это осложнит написание первого скрипта, но свойства и методы работы описаны очень подробно. На базовом уровне функциональность скриптинга в InDesign вполне адекватна Illustrator — тот же объектно-ориентированный подход, полный набор операций со своей спецификой, та же гибкость, позволяющая оперировать элементами публикации и текстом. Чтобы не возвращаться к основам скриптинга в продуктах Adobe, сошлюсь на Publish № 7, 2004, с. 92. Но скриптинг в InDesign продвинулся далеко за рамки базовых возможностей автоматизации дизайнерских приложений.
Во-первых, значительно расширены интерфейсные возможности. В Illustrator нельзя создать пользовательские окна диалога, и выход из положения — использовать ограниченные возможности JavaScript. А в InDesign создаются диалоговые окна любой сложности (даже с подгруппами элементов). В них присутствуют разные типы кнопок (в т. ч. радио), всплывающие списки и прочие элементы «красивой» жизни, упрощающие дизайнеру управление скриптом. Но диалоговыми окнами целесообразно пользоваться только в сложных скриптах, требующих массы параметров. В большинстве же задач достаточно стандартного окна запроса, знакомого по JavaScript и подробно описанного в той же статье. Упрощается сам скрипт, повышается его читабельность.
Во-вторых, в InDesign адекватно решаемым задачам развит механизм автоматического переноса публикации на другую платформу — например, для размещения в Сети (через XML), в т. ч. с сохранением интерактивности (за счёт поддержки событий типа mouseIn и mouseOver). Это реализация концепции Create once, ready everywhere — однажды созданный документ без проблем адаптируется к любому виду.
Как и для Illustrator, для InDesign можно писать скрипты на любом из трёх языков — Visual Basic (для почитателей продукции Microsoft), AppleScript (Mac OS) и платформенно-независимом универсальном JavaScript, хорошо известном веб-мастерам. Для двух первых в InDesign есть дополнительное удобство: для любого объекта выбирается желаемое действие из списка операций. При ориентации же на JavaScript вам придётся основательно изучить справочное руководство. Если никогда не занимались программированием, ознакомьтесь с основами скриптинга в упомянутой выше статье. Хотя в ней рассматривается механизм Illustrator, неспециалист легко разберётся в базовых понятиях, что облегчит миграцию на InDesign.
Взаимные связи между типами объектов хорошо согласуются с отношениями в Illustrator, но имеют специфику. Объект высшего уровня — сам InDesign, в нём может быть открыто одновременно несколько документов, один из которых — активный (activeDocument). Затем градация идёт по объектам, расположенным непосредственно на страницах (или разворотах) и отдельно — на монтажном столе (pasteboard). Многие объекты InDesign существуют в двух ипостасях: связанные с текущим документом (набор образцов цвета, стили абзацев, отдельных символов и печати, шрифты) и имеющие более высокий уровень — приложения, не зависящие от конкретного документа. К последним относятся настройки отображения публикации на экране, язык и др. Интересно, что с внешними источниками можно работать, как с Image (если растровый объект) либо EPS и PDF.
Механизм скриптинга позволяет обращаться к любому месту в публикации, причём не только в текстовом контейнере, но и в таблице, к графическим элементам, направляющим. Это снимает ограничения на управление некоторыми объектами, существующие в Illustrator CS. Разработчики уделяют скриптингу именно под InDesign много внимания, отсюда меньше недочётов по сравнению с векторным редактором. А вот подключить библиотечные файлы, как в Illustrator, к сожалению, нельзя.
Цель статьи — не научить скриптингу, а заинтересовать написанием собственных скриптов. Лучший способ — рассмотреть несколько типовых задач верстальщика. Выберем относительно несложные — на них вы прочувствуете, как это делается, а позже, освоившись с механизмом скриптинга под InDesign, вам будет легче перейти к сложным вопросам.
Удаление неиспользуемых цветов, стилей символов и абзацев
В принципе, такую очистку перед передачей публикации на вывод делать необязательно, но это свидетельствует о высокой культуре рабочего процесса и в цеховом сообществе считается хорошим тоном. Попутно очистим публикацию от пустых текстовых фреймов и содержащих только пробел либо абзац.
Разумеется, в конце работы скрипт должен выдавать отчёт о внесённых изменениях. В первоначальный момент их нет (CS — сокращение от characterStyles, PS — paragraphStyles, TF — textFrames):
deletedCS=0; deletedPS=0; deletedSwatches=0; deletedTF = 0;
Для сокращения размера скрипта будем использовать ссылку на родительский объект для всех участвующих элементов — на открытый документ:
aD = app.activeDocument;
К неиспользуемым цветам в скриптовой модели InDesign можно добраться через специальный объект unusedSwatches. Таким образом, нам достаточно сначала проверить, присутствуют ли такие цвета в публикации (свойство length «количество» > 0), и если да, то по очереди их удалять и заодно вести учёт:
uSw = aD.unusedSwatches; if (uSw.length > 0) { for (i=0; i
С цветами разобрались. Искать неиспользуемые стили текста будем иначе: для таких элементов в InDesign нет метода, подобного рассмотренному выше. Используем возможности поиска стилей, существующие в окне поиска/замены (Find/Change), — в скриптовой модели для этого есть специальный объект findPreferences. Все стили публикации можно узнать через aD.characterStyles; по очереди будем их перебирать и параллельно искать отформатированный ими текст. Если поиск ничего не дал, значит, стиль в публикации не используется, и его нужно удалить. Для отчётности ведём подсчёт удалённых стилей.
for (i=1; i
Строчка app.findPreferences = null необходима для сброса предыдущих параметров поиска, иначе могут остаться значения в тех полях, которые в новом поиске не используются. Аналогично действуем, удаляя неиспользуемые стили абзацев:
for (i=1; i
С первой частью скрипта разобрались. Что касается второй (поиск пустых текстовых контейнеров), то воспользуемся методом «contents», позволяющим работать с содержимым textFrames. Если контейнер пуст и не имеет цвета (это проверять обязательно, поскольку часто цветные текстовые фреймы используются в дизайнерских целях), он удаляется; заблокированный придётся предварительно разблокировать.
tF = aD.textFrames; for (i=0; i
Вместо конструкции if ((tF[i].contents == «»)||(tF[i].contents == » «)) и т. д. с длинным перечислением условий проверки воспользуемся упрощённым способом — через оператор switch / case, а служебный символ «r» обозначает символ абзаца.
В конце выводим отчёт о работе:
alert (‘Deleted:n’ + deletedCS+ » unused CharacterStylesn» +deletedPS+ » unused paragraphStylesn»+deletedSwatches+ » unused swatchesn» +deletedTF+ » deleted empty text frames»).
Как видите, всё просто. Скрипт remove_unused.js можно загрузить с сайта: www.publish.ru. Чтобы InDesign его распознал, поместите в папку C:Program FilesAdobeAdobe InDesign CSPresetsScripts.
Что дальше?
Одна из задач, где также в полной мере проявляется польза от скриптинга, — создание каталогов с продукцией, когда из заранее подготовленной и тщательно выверенной базы данных скрипт берёт информацию и вставляет в соответствующие места в публикации (контейнеры с определёнными идентификаторами). Всё выполняется очень быстро, и риск получения ошибки по сравнению с обычным способом сведён к минимуму. Аналогичный подход можно использовать и при печати переменных форм, экономя на приобретении специализированных решений от Datalogics, Em Software, Sansui Software или XMPie. Другая сфера использования скриптинга — форматирование: например, оформление некоторым образом первого слова во всех статьях публикации (например, всеми заглавными) либо вставка определённого значка в конце.
Автор недавно автоматизировал задачу сложного форматирования списков использованной литературы в одном научном журнале — номер источника должен был быть выполнен обычным начертанием, авторы — курсивом, а всё остальное — опять обычным. Раньше подобная задача решалась написанием соответствующего макроса в Word с последующим внедрением уже подготовленного текста в XPress, теперь же всё делается прямо в пакете вёрстки. А вообще, задач, решаемых с помощью скриптинга, множество. Человек создан для творчества, а не для рутины. Давайте поручим её компьютеру.
Об авторе: Михаил Борисов (mikeb@ukr.net), пишет для Publish полезные советы по допечатной подготовке и обзоры ПО.