Избранное »

22.09.2014 – 07:27 | 2 комментария | 27 557 views

Здравствуйте все, кто работает в Индизайне!
Извещаем вас о том, что на youtube.com работает канал «InDesign Мастерская вёрстки». Там уже размещены более 70 видео с полным описанием как работать с программой DoTextOK. Другие интересные темы, касающиеся работы …

Читать полностью »
Работа в InDesign

Хитрости и секреты, приемы работы, уроки

Новая версия!

Особенности новой версии Индизайна

Плагины

Описание плагинов, информация о плагинах для работы с Adobe InDesign

Скрипты

Готовые к использованию скрипты для Adobe InDesign

Скриптинг

Описание языка, приёмов и методов программирования для Adobe InDesign

Home » Скриптинг

Руководство на русском языке по созданию интерфейса скриптов (ScriptUI для чайников)

Добавлено на 08.11.2010 – 22:50Без комментариев | 13 328 views

Чтобы разобраться во всех возможностях скриптинга, надо не один раз прочитать руководство 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 ( );

Вот что будет при его запуске:
ScriptUI-01
Первая строка определяет новое окно типа 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 ( );

ScriptUI-02
Попробуйте оба скрипта, чтобы убедиться, что первый блокирует работу, пока не закроешь окно, а второй позволяет работать при открытом окне.

Налицо и некоторые несущественные различия в оформлении окон в части скругления углов и разного размера кнопок.

Добавление элементов интерфейса

Элемент интерфе́йса — примитив графического интерфейса пользователя, имеющий стандартный внешний вид и выполняющий стандартные действия. Он также может называться как контро́л (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 ();

ScriptUI-03
Обратите внимание, что окно теперь с заголовком «Форма». Заметьте также, что поле ввода стоит ниже приглашения («Имя:»), что не есть хорошо. Предположительно, что ориентация окна по умолчанию имеет тип column. Чтобы изменить этот тип, нужен соответствующий оператор в скрипте (вторая строка):

var myWindow = new Window ("dialog", "Форма");
myWindow.orientation = "row";
myWindow.add ("statictext", undefined, "Имя:");
var myText = myWindow.add ("edittext");
myWindow.show ();

ScriptUI-04
Результат несколько лучше, но поле ввода очень маленькое. Кроме того, надо сделать так, чтобы по умолчанию были введены какие-то данные.

var myWindow = new Window ("dialog", "Форма");
myWindow.orientation = "row";
myWindow.add ("statictext", undefined, "Имя:");
var myText = myWindow.add ("edittext", undefined, "Петр");
myText.characters = 30;
myWindow.show ();

ScriptUI-05
Теперь можно для элемента интерфейса 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 ();

ScriptUI-06
Теперь добавим кнопки, в нашем случае 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 ();

ScriptUI-07
Поскольку тип ориентации окна выбран 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 ();

ScriptUI-08
Для объединения полей или кнопок кроме элемента интерфейса 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 ();

ScriptUI-09
Добавим в окно контейнер типа 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 ();

ScriptUI-10
Обратите внимание, что в группах теперь не определен явно тип ориентации. В данном случае он не нужен: ведь в окне всего два объекта, и стандартная ориентация для панели — колонка, а для группы — строка.

{Но явным указанием ориентации в панели и группе можно получить такие результаты:
ScriptUI-11
ScriptUI-12

Панели — это хорошие инструменты скриптинга в создании окон. При правильном использовании создаваемые окна легко настраиваются. Например, если надо, чтобы кнопки были справа одна над другой, то всё, что надо сделать — это поместить в скрипт два оператора ориентации.

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 ();

ScriptUI-13
Для выравнивания групп по вертикали надо добавить строку

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 ();

ScriptUI-14
Предположим, что окно нас устраивает, и вернемся к вопросу, как в скрипте сохранить введенный пользователем текст. В нашем примере есть два события — пользователь щелкает на кнопке ОК (это эквивалентно нажатию на клавишу 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 ();

ScriptUI-15
Можно сделать фрейм без бордюра:

myWindow = new Window ("dialog", "Example", undefined, {borderless: true})
myWindow.add ("statictext", undefined, "borderless: true");
myWindow.show ();

ScriptUI-16
Такие безбордюрные фреймы минималистичны, по сути это просто серые панели. Их вид можно улучшить, нарисовав вокруг них контур (добавив панель):

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 ();

ScriptUI-17
На этом основы построения окон завершены, вернемся к деталям организации содержимого окон.

Элементы интерфейса

Элемент интерфейса 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 ();

ScriptUI-18
Второй параметр элемента управления 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 ();
}

ScriptUI-19
Эта функция имеет один недостаток — при работе с большими массивами заметно время их обработки.

Элемент интерфейса button

Нажимаемые кнопки
Можно использовать различные типы кнопок. Ранее были рассмотрены стандартные нажимаемые кнопки ОК и Cancel, часто используемые в окнах

var w = new Window ("dialog");
w.add ("button", undefined, "OK");
w.add ("button", undefined, "Cancel");
w.show ();

ScriptUI-20
По умолчанию щелчок на клавише ОК эквивалентен нажатию на клавишу 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 ();

ScriptUI-19а

После щелчка на кнопке ‘Переключить в верхний регистр’ буквы станут прописными. Это простой пример, но функции, вызываемые событием onClick могут быть любой сложности. (Есть несколько других откликов на события /в оригинале callback/, с которыми мы познакомимся позднее.

Кнопки-пиктограммы (icon buttons)

Кроме стандартных нажимаемых кнопок можно использовать пиктограммы как кнопки. На них отображается не текст, такой как ОК, а изображение. Картинка может быть в формате PNG, IDRC или JPEG.

Вот как выглядит запись такой кнопки в программе:

w.add ("iconbutton", undefined, <strong>File </strong>(myFile));

Это добавляет кнопку (как pushbutton, т.е. стартовую кнопку) на кнопочной панели, а не текст (например, первая кнопка на следующем рисунке кнопочной панели).
ScriptUI-21a
Кнопки могут быть добавлены как инструментальные кнопки (в оригинале 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 ();

ScriptUI-21
В интерфейсе индизайна примеры кнопок-тумблеров можно найти на панелях 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 ();

Если указанного файла не найдено, на экран выводится такое окно:
ScriptUI-22

Элемент интерфейса 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 ();

ScriptUI-23
По умолчанию свойство 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 ();

ScriptUI-24
А так можно проверить, установлен ли первый флажок:

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 ();

ScriptUI-25
Чтобы узнать, какая из радиокнопок в группе нажата, надо перебирать все кнопки, пока не будет найдена активная.
В случае группы из двух кнопок всё намного проще:

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 &lt; rbuttons.length; i++)
   if (rbuttons[i].value == true)
   return i;
}

ScriptUI-26ScriptUI-27

Важно установить блок радиокнопок в исходное состояние, т.е. программа возвращает результат выбора. Если начальной установки нет, и выбор не сделан, программа вернет значение undefined.
Для возврата текстовой строки, а не индекса используйте возвращенное число как индекс обращения к массиву. Например, в последнем примере вывод сообщения о выборе можно сделать так:

alert ("Выбрано: " + ["indd", "pdf", "idml", "txt"][selected_rbutton (formats)]);

т.е. выводится выбранное расширение файла.
Если у вас несколько блоков радиокнопок, они должны быть размещены в отдельных группах.
Вот, например, как в скрипте batch/convert/export documents
сделано два блока радиокнопок:
ScriptUI-28
Радиокнопки для From: и To: размещены в отдельных группах.

Элемент интерфейса listbox (список)

Это список текстовых строк. Он может заполняться в момент создания окна или позже. Для заполнения списка в момент создания окна объекты списка помещаются в массив. Вот пример:

var w = new Window ("dialog");
var myList = w.add ("listbox", undefined, ["one", "two", "three"]);
w.show ();

ScriptUI-29
Для создания списка позже, или добавления объектов в существующий список используйте показанный ниже метод:

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 ();

Когда свойством

{multiselect: true}

разрешен выбор нескольких строк, объекты выбираются стандартно: Ctrl+клик добавляет один объект, Shift+клик добавляет диапазон.
Чтобы после запуска скрипта одна из строк, например, первая, уже была выбрана, надо, чтобы было определено свойство selection этого списка:

var w = new Window ("dialog");
var myList = w.add ("listbox", undefined, ["one", "two", "three"], {multiselect: true});
myList.selection = 0;
w.show ();

ScriptUI-30
Для выбора в таком списке более одной позиции при запуске скрипта надо записать в массив индексы выбираемых объектов:

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 &lt; 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 &lt; 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 ();

ScriptUI-31

Упорядочение списков
Вот пример обработки списка — вставка объекта в список и сортировка обновленного списка по алфавиту. Программа активирует приглашение, поэтому можно ввести букву незамедлительно. Заметьте, что функция управления окном необязательно должна быть определена в том блоке, что определяет окно (т.е. между операторами 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 ();

ScriptUI-32

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 &lt; stop &amp;&amp; new_item &gt; 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 &gt; 0)
{
  swap (list.items [n-1], list.items [n]);
  list.selection = n-1;
}
}
down.onClick = function ()
{
var n = list.selection.index;
if (n &lt; 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 ();

ScriptUI-33
На самом деле объекты списка остаются на месте, меняются местами их свойства 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 &lt; descriptions.length; i++)
{
    myList.add ("item", descriptions[i]);
    myList.items[i].image = File ("~/Desktop/"+imgs[i])
}
w.show ();

ScriptUI-34

Первые две строки создают массивы имен иллюстраций и текстовые названия иллюстраций. Затем цикл 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 ();

ScriptUI-35
Ширины колонок определяются автоматически, но можно задать ширину вручную, определив значение свойства 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]});

ScriptUI-36
Иллюстрации могут добавляться в любую из строк любой из колонок:

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 ();

ScriptUI-37
Чтобы узнать, какая стока выбрана, воспользуйтесь свойством 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 ();

ScriptUI-38
По умолчанию все вложенные списки свернуты (в таких списках их часто называют узлами). Чтобы развернуть любой из них, дважды щелкните по названию, или один раз по плюсику, предваряющему название списка.
Чтобы развернуть содержимое узла при открытии окна, надо свойству 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 ();

ScriptUI-39
Пример использования элемента интерфейса 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 ();

ScriptUI-40
{на нашем сайте мы рассматривали скрипт по работе с вкладками}

Элемент интерфейса 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 &lt; 100; ++i, pBar.hit() )
          {
          $.sleep(10);
          }
 
     // Routine #2
     var i;
     pBar.reset("Processing Routine #2...", 10);
     for( i=0 ; i &lt; 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 &lt; $.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 ();

ScriptUI-41
Обратите внимание, что в таком способе можно только определить название шрифта и размер, и ничего более. Если надо определить еще и начертание, то для этого предусмотрено другое решение:

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 ();

ScriptUI-42
Если не важно, какая гарнитура используется в окне, а важны только размер букв и начертание, то можно указать для использования в текущем окне стандартный системный шрифт, определив его начертание и размер букв:

button2.graphics.font = ScriptUI.newFont (ScriptUI.applicationFonts.palette.name, "Bold", 18);

К сожалению, невозможно за один раз определить шрифты для всех окон, групп или панелей, для каждого варианта это надо делать отдельно. Вот такая функция упростит решение этой задачи:

function set_font (control, font)
{
for (var i = 0; i &lt; control.children.length; i++)
{
    if ("GroupPanel".indexOf (control.children[i].constructor.name) &gt; -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");

ScriptUI-43
ScriptUI-44
Замечание: в 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 ();

ScriptUI-45
Похоже, есть проблемы в назначении цвета кнопкам, это обсуждалось на форуме 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();

ScriptUI-46
Первая линия [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 ();

ScriptUI-47
Поскольку для окна и двух групп используется выравнивание fill, при изменении объектов в группе длина линий тоже изменяется. Чтобы увидеть это, измените строку p1.preferredSize = [100, 50] на p1.preferredSize = [100, 100], а строку p3.preferredSize = [100, 50] на p3.preferredSize = [200, 50], чтобы получить другой вариант оформления окна:
ScriptUI-48
(Замечание: замороченный на первый взгляд оператор 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 ();

ScriptUI-49
Выше показаны окно и консоль после нажатия обеих кнопок. Нажатие на кнопку выводит на консоль её имя.
Код функции отклика на примере нажатия кнопки 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 ();

ScriptUI-50
Скрипт отображает два пустых текстовых поля. После набора текста в первом окне и нажатия клавиши перевода строки или клавиши табуляции этот текст будет скопирован во второе поле.
Обратите внимание, что этот оклик не активизируется раньше, чем вы завершите ввод текста.
Для отслеживания событий со время ввода текста надо использовать обработчики событий (см. ниже).
Работа со списками также может отслеживаться. Вот скрипт, отображающий трехстрочный список с выбранной первой строкой. Выбор любой строки в списке будет отображен на консоли.

var w = new Window ("dialog");
var list = w.add ("listbox", undefined, ["ОДИН", "ДВА", "ТРИ"]);
list.selection = 0;
list.onChange = function () {$.writeln (this.selection.text + " ВЫБРАНО.")}
w.show ();

ScriptUI-51
Вот вывод на консоль после щелчка на строке ТРИ.

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 &lt; 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

Оставить комментарий!

Вы должны быть в системе чтобы оставить комментарий.