# Вступ до написання додатків до &rkward;

## Вступ

Документація стосується &rkward; випуску 0.6.4.

У цьому документі описано способи створення додатків. Зауважте, що на час його написання не усі використані тут концепції набули остаточної форми. Тому цей документ слід вважати вступом до поточного підходу та основою для обговорення. Ми будемо раді будь-яким коментарям. З часом цей документ став доволі об’ємним. Нехай вас це не лякає. Ми рекомендуємо вам ознайомитися із чотирма базовими кроками (які наведено нижче), щоб вловити основні принципи роботи. Після цього ви можете перейти до таблиці змісту цього підручника, щоб визначити розділи, які могли б вас зацікавити.

Якщо у вас виникнуть питання або коментарі, будь ласка, поділіться ними у списку листування розробників &rkward;.

Вам не потрібно читати цей підручник, щоб користуватися &rkward;. Цей документ присвячено розширенню можливостей &rkward;. Його читачами мають стати досвідчені користувачі або ті, хто хоче допомогти у поліпшенні &rkward;.

Написання стандартного додатка, загалом, — це чотирикроковий процес:

- Додавання нового пункту у ієрархію меню.

- Описання вигляду та поведінки графічного інтерфейсу додатка.

- Визначення того, як слід створювати код R на основі параметрів, які користувач визначає за допомогою графічного інтерфейсу.

- Додавання сторінок довідки до вашого додатка.

Ми опишемо усі ці кроки послідовно.

Під час виконання цих чотирьох кроків може бути використано деякі додаткові концепції, але для простоти ми розібрали їх у окремих главах:

- Логіка графічного інтерфейсу

- Вбудовування додатків до додатків

- Корисні концепції щодо створення серій з подібних додатків

Крім того, у жодній з глав не викладено усіх можливостей, швидше там можна знайти лише загальні концепції. Повний довідник усіх параметрів наведено окремо.

## Попередні зауваження. Для чого призначено додатки у &rkward;? Як працюють додатки?

Звичайно ж, першим питанням, яке може у вас виникнути: яку частину функціональних можливостей &rkward; реалізовано за допомогою додатків або що можна зробити за допомогою додатків?

Ось один зі способів відповісти: зніміть позначки з усіх файлів &pluginmap; на сторінці Параметри Налаштувати &rkward;Додатки і подивіться, чого не вистачає у програмі. Трохи конструктивніша відповідь: більшість статистичних функцій, доступ до яких можна отримати з графічного інтерфейсу програми, реалізовано за допомогою додатків. Крім того, ви можете створити доволі гнучкий графічний інтерфейс до усіх типів дій за допомогою додатків.

Базова парадигма додатків &rkward; ґрунтується на саме такому порядку, у якому її викладено у цьому підручнику: файл XML описує вигляд графічного інтерфейсу додатка, додатковий файл JavaScript використовується для створення команд &R; на основі визначених у графічному інтерфейсі параметрів. Тобто, додатки насправді не виконують ніяких статистичних обчислень. Замість цього, додатки створюють набір команд &R;, за допомогою якого і виконуються ці обчислення. Команди &R; надсилаються до модуля обробки коду &R; для виконання, а результат, типово, буде показано у вікні виведення даних.

У наступних розділах можна знайти докладні відомості щодо цих питань.

## Створення пунктів меню

Для створення додатка вам слід повідомити &rkward; про нього. Отже, першим, що слід зробити, є створення файла &pluginmap; (або внесення змін до наявного файла). Форматом &pluginmap; є XML. Розгляньмо приклад (звичайно ж, вам слід подбати про те, щоб &rkward; було налаштовано на завантаження вашого файла &pluginmap; -- Параметри Налаштувати &rkward;Додатки):

Після прочитання цієї глави зверніться до пакунка rkwarddev. У ньому реалізовано декілька функцій &R; для створення більшості теґів XML &rkward;.

    <!DOCTYPE rkpluginmap>

Значення типу документа (doctype) насправді не обробляється, але для нього встановлюється значення `"rkpluginmap"`.

    <document base_prefix="" namespace="myplugins" id="mypluginmap">

Атрибутом `base_prefix` можна скористатися, якщо усі ваші додатки зберігаються у одному каталозі. Загалом, тоді ви можете не вказувати каталог у назвах файлів, визначених нижче. Можна залишити для цього атрибута значення `""`.

Як ви побачите далі, усі додатки мають власні унікальні ідентифікатори, `id`. Параметр `namespace` призначено для упорядковування таких ідентифікаторів з метою запобігання випадковому дублюванню ідентифікаторів. На внутрішньому рівні значення namespace і :: дописуються перед усіма ідентифікаторами, які ви визначаєте у цім &pluginmap;. Загалом, якщо ви маєте намір поширювати ваші додатки як пакунок &R;, вам варто скористатися для значення параметра `namespace` назвою вашого пакунка. Додатки, які постачаються разом із офіційним дистрибутивом &rkward; мають значення параметра `namespace="rkward"`.

Атрибут `id` є необов’язковим, але визначення ідентифікатора для вашого &pluginmap; уможливлює для інших програмістів автоматичне завантаження у їхніх &pluginmap; вашого &pluginmap; (див. розділ щодо залежностей).

    <components>

Компоненти? Ми ж, начеб-то, говорили про додатки? Так, але у майбутньому, додатки будуть нічим іншим, ніж особливим класом компонентів. Тому усе, що ми тут робимо, є реєстрацією усіх компонентів або додатків у &rkward;. Розгляньмо приклад запису:

    <component type="standard" id="t_test_two_vars" file="t_test_two_vars.xml" label="Two Variable t-Test" />

Спочатку, атрибут `type`: поки що залишимо для нього значення `"standard"`. Інші типи ще не реалізовано. Про `id` ми вже писали вище. Кожному компоненту має бути надано унікальний (у його просторі назв) ідентифікатор. Виберемо простий для розпізнавання. Не варто використовувати пробіли або символи, які не належать до типової латинської абетки. Використання таких символів не заборонено, але вони можуть мати якесь спеціальне призначення. За допомогою атрибута `file` ви вказуєте, де зберігається опис самого додатка. Адресу файла слід вказувати відносно каталогу, у якому зберігається файл &pluginmap; та `base_prefix`, вказаного вище. Нарешті, надамо компоненту мітку. Цю мітку буде показано у меню (або у інших місцях інтерфейсу у майбутніх версіях).

Типово у файлі &pluginmap; міститься декілька компонентів, отже, ось іще декілька компонентів:

    <component type="standard" id="unimplemented_test" file="means/unimplemented.xml" />
                    <component type="standard" id="fictional_t_test" file="means/ttests/fictional.xml" label="This is a fictional t-test" />
                    <component type="standard" id="descriptive" file="descriptive.xml" label="Descriptive Statistics" />
                    <component type="standard" id="corr_matrix" file="corr_matrix.xml" label="Correlation Matrix" />
                    <component type="standard" id="simple_anova" file="simple_anova.xml" label="Simple Anova" />
            </components>

Гаразд, на першому кроці ми повідомили &rkward;, що такі додатки існують. Як же тепер їх викликати? Слід розмістити відповідні пункти у ієрархії меню:

    <hierarchy>
                    <menu id="analysis" label="Analysis">

Одразу після теґу `<hierarchy>` ви маєте почати опис того, у якому `<menu>` буде ваш пункт додатка. У наведеному вище рядку ви повідомляєте, що пункт додатка має бути розташовано у меню Analysis (не обов’язково у основному списку пунктів, можливо, у підменю). Меню Analysis є стандартним у &rkward;, отже його не потрібно буде створювати з нуля. Втім, якщо меню ще не існує, за допомогою атрибута `label` ви створите його і дасте йому назву. Нарешті, атрибут `id` ще раз ідентифікує це `<menu>`. Він потрібен для того, щоб декілька файлів &pluginmap; могли розмістити пункти додатків у одному меню. Програма виконує упорядковування меню, шукаючи `<menu>` з вказаним `id`. Якщо меню з таким ідентифікатором ще не існує, програма створює нове меню. Якщо ж меню з таким ідентифікатором буде знайдено, пункт додатка буде додано саме до нього.

    <menu id="means" label="Means">

В основному, те саме: тепер ми визначаємо підменю у меню Analysis. Воно називатиметься Means.

    <menu id="ttests" label="t-Tests">

І остаточний рівень ієрархії меню: підменю меню Means.

    <entry component="t_test_two_vars" />

Тепер, нарешті, меню, у якому ми хочемо розташувати наш пункт додатка. Теґ `<entry>` повідомить програмі, що це, нарешті, сам пункт, а не ще одне підменю. Атрибут `component` посилається на `id`, який ми надали додатку або компоненту вище.

    <entry component="fictional_t_test" />
                                    </menu>
                                    <entry component="fictional_t_test" />
                            </menu>
                            <menu id="frequency" label="Frequency" index="2"/>

Якщо ви ще не зрозуміли, це ще одне підменю меню Analysis. Див. наведений нижче знімок вікна. Ми пропустили частину, яку не видно, позначивши її [...].

    [...]
                            </menu>
                            <entry component="corr_matrix"/>
                            <entry component="descriptive"/>
                            <entry component="simple_anova"/>
                    </menu>

Це завершальні пункти, які видно на наведеному нижче знімку вікна.

    <menu id="plots" label="Plots">
                            [...]
                    </menu>

Звичайно ж, ви можете розташувати ваші додатки у меню, відмінних від меню Analysis.

    <menu id="file" label="File">
                            [...]
                    </menu>

Навіть у стандартних меню, зокрема File. Вам лише треба вказати відповідне значення `id`.

    </hierarchy>
    </document>

Ось як це робиться. І знімок вікна, на якому показано результат:

Ієрархія меню, створена за допомогою наведеного вище коду Ієрархія меню, створена за допомогою наведеного вище коду

Незрозуміло? Найпростіше буде розпочати з файлів &pluginmap;, які постачаються разом із &rkward;, вносячи в них потрібні вам виправлення. Крім того, якщо вам потрібна допомога, не вагайтеся і пишіть до списку листування розробників.

### Керування порядком пунктів меню

Типово, усі пункти (записи або підменю) у меню буде автоматично упорядковано за абеткою. У деяких випадках варто втрутитися у цей процес. Якщо це так, ви можете згрупувати елементи у такий спосіб:

- Таким чином, ви можете визначити групи у будь-якому меню. Усі елементи, що належать одній групі буде згруповано:

      <group id="somegroup"/>

- Якщо ви хочете візуально відокремити групу від інших пунктів, скористайтеся такою синтаксичною конструкцією:

      <group id="somegroup" separated="true"/>

- Пункти, меню та групи можна додати до певної групи, ось так:

      <entry component="..." group="somegroup"/>

- Фактично, можна визначити групи (без ліній-роздільників) неявно:

      <entry component="first" group="a"/>
                      <entry component="third"/>
                      <entry component="second" group="a"/>

- Назви груп є специфічними для кожного меню. Наприклад, група «a» у меню «Data» не конфліктує з групою «a» у меню «Analysis».

- Найпоширенішим випадком визначення груп є пункти на початку і наприкінці меню. Для таких пунктів передбачено групи «top» (верх) і «bottom» (низ) у кожному меню.

- Записи у межах кожної з груп упорядковуються за абеткою. Групи упорядковуються за порядком оголошення (якщо їх, звичайно ж, не дописано до іншої групи).

- Меню і пункти без визначеної групи, логічно, також утворюють групу окрему групу ("").

## Визначення графічного інтерфейсу

### Визначення діалогового вікна

У попередньому розділі ми обговорювали питання щодо реєстрації додатка у &rkward;. Найважливішим є визначення шляху до файла XML із описом того, як має виглядати інтерфейс додатка. У цьому розділі ми спробуємо навчитися створювати такі файли XML.

Після прочитання цієї глави зверніться до пакунка rkwarddev. У ньому реалізовано декілька функцій &R; для створення більшості теґів XML &rkward;.

Знову ж таки, ми будемо обговорювати конкретний приклад. У нашому прикладі (дещо спрощеному) ми створимо інтерфейс до двофакторної t-перевірки.

    <!DOCTYPE rkplugin>

Значення типу документа (doctype) насправді ще не обробляється, але для нього встановлюється значення `rkplugin`.

    <document>
            <code file="t_test_two_vars.js"/>

Усі додатки створюють певний програмний код. У поточній версії єдиним способом створити цей код є використання JS, як це докладно описано у наступному розділі. Наведений вище фрагмент визначає, де шукати код JS. Назву файла слід вказувати відносно каталогу, у якому зберігається файл XML додатка.

    <help file="t_test_two_vars.rkh"/>

Зазвичай, непогано супроводжувати ваш додаток сторінкою довідки. У наведеному вище фрагменті вказано назву файла сторінки довідки відносно каталогу, у якому зберігається файл XML додатка. Документацію щодо написання сторінок довідки наведено тут. Якщо ви не надаєте файла довідки, пропустіть цей рядок.

    <dialog label="Two Variable t-Test">

Як ви знаєте, додатки можуть показувати діалогові вікна, можуть працювати як майстер налаштовування або можуть виконувати обидві функції. У нашому прикладі ми розпочнемо визначати інтерфейс діалогового вікна. Атрибут `label` визначити надпис на смужці заголовка цього діалогового вікна.

    <tabbook>
                            <tab label="Basic settings">

Елементи графічного інтерфейсу можна упорядкувати за допомогою книги із вкладками (tabbook). Тут ми визначили tabbook як перший елемент у діалоговому вікні. Використовуйте обгортку `<tabbook>`[...]`</tabbook>`, щоб визначити tabbook, потім перейдіть до визначення кожної сторінки у tabbook за допомогою конструкцій `<tab>`[...]`</tab>`. Атрибут `label` у елементі `<tab>` визначить надпис на відповідній вкладці tabbook.

    <row id="main_settings_row">

Теґи `<row>` і `<column>` визначають компонування елементів графічного інтерфейсу. Тут ми вказуємо програмі, що хочемо розташувати певні елементи інтерфейсу паралельно у стовпчиках (зліва праворуч). Атрибут `id` не є обов’язковим, але ми його пізніше використаємо, коли додаватимемо інтерфейс майстра до нашого додатка. Першим елементом у рядку є цей елемент:

    <varselector id="vars"/>

За допомогою цього простого теґу ви створюєте список, з якого користувач може вибрати змінні. Ви можете вказати `id` цього елемента, щоб &rkward; пізніше міг його знайти.

У рядку `id` не можна використовувати крапку (.).

    <column>

Далі, ми вкладемо `<column>` до row. Тобто, відповідні елементи буде розташовано один над одним (у стовпчик, згори униз), і всі вони розташовуватимуться праворуч від `<varselector>`.

    <varslot types="number" id="x" source="vars" required="true" label="compare"/>
                                                    <varslot types="number" id="y" source="vars" required="true" label="against" i18n_context="compare against"/>

Ці елементи є невід’ємною частиною `<varselector>`. Вони відповідають за гнізда, у яких користувач може задавати змінні. Як можна бачити, для `source` встановлено те саме значення `id`, що і для `<varselector>`. Це означає, що `<varslot>` також братимуть змінні з varselector. Теґу `<varslot>` також слід надати `id`. Такі теґи можуть мати атрибут `label`, а також можуть бути позначені як `required` (обов’язкові). Це означає, що кнопку Submit не буде доступною для натискання, доки у `<varslot>` не міститиметься коректного значення. Нарешті, атрибут `type` ще не обробляється, але його буде використано для забезпечення коректності типу змінної у `<varslot>` у наступних версіях.

Якщо вас зацікавив атрибут `i18n_context`: його призначено для надання контекстної довідки для перекладачів слова «against», яке є міткою `<varslot>`, але не впливає на функціональні можливості додатка безпосередньо. Докладніше про цей атрибут у окремому розділі.

    <radio id="hypothesis" label="using test hypothesis">
                                                            <option value="two.sided" label="Two-sided"/>
                                                            <option value="greater" label="First is greater"/>
                                                            <option value="less" label="Second is greater"/>
                                                    </radio>

Тут ми визначаємо групу кнопок взаємовиключних варіантів `<radio>`. У групи є аргумент `label` і ідентифікатор `id`. Кожен варіант, `<option>`, (кнопка) має власну мітку `label` і значення `value`. Це значення, яке елемент `<radio>` поверне, якщо буде вибрано відповідний варіант.

    </column>
                                    </row>
                            </tab>

Кожен теґ має бути завершено, початковому теґу має відповідати завершальний. Ми розмістили усі потрібні нам елементи (два `<varslots>` і `<radio>`) у стовпчику `<column>`. Ми також розмістили усі потрібні нам елементи (`<varselector>` і `<column>` з цими елементами) у `<row>`. І ми розмістили усі потрібні нам елементи на першій сторінці у `<tabbook>`. Ми ще не завершили визначення `<tabbook>` (інші сторінки доведеться визначити пізніше) і, звичайно ж, ще залишилося багато чого визначити у `<dialog>`. Але ось знімок вікна, як все визначене нами виглядатиме:

Додаток t-перевірки Додаток t-перевірки

Зауважте, що ми не визначали кнопки Submit, Close тощо і пов’язаний з ними код. Ці елементи створюються автоматично. Але, звичайно ж, нам доведеться визначити другу сторінку `<tabbook>`:

    <tab label="Options">
                                    <checkbox id="varequal" label="assume equal variances" value=", var.equal=TRUE"/>

Типово, елементи буде розташовано згори вниз, подібно до `<column>`. Оскільки це те саме, що нам потрібно, ми не будемо визначати явно компонування `<row>` або `<column>`. Першим визначеним нами елементом буде пункт з позначкою. Так само, як `<radio>` `<option>`, пункт для позначки має мітку `label` і значення `value`. Значення `value` буде повернуто, якщо користувач позначить пункт. Звичайно ж, пункт для позначки потребує власного ідентифікатора `id`.

    <frame label="Confidence Interval" id="frame_conf_int">

Тут ми маємо ще один елемент компонування: щоб повідомити програми, що два елементи нижче пов’язано між собою, ми малюємо `<frame>` (рамку). Ця рамка може мати атрибут `label` (надпис). Оскільки рамка є простим пасивним елементом компонування, вона не потребує ідентифікатора `id`. Втім, ми визначимо такий атрибут, оскільки ідентифікатор може нам знадобитися пізніше, коли ми визначатимемо додатковий інтерфейс майстра.

    <checkbox id="confint" label="print confidence interval" value="1" checked="true"/>
                                            <spinbox type="real" id="conflevel" label="confidence level" min="0" max="1" initial="0.95"/>
                                    </frame>

У рамці `<frame>` ми розташуємо ще один пункт для позначення `<checkbox>` (за допомогою атрибута `checked=``"true"` ми повідомляємо, що типово пункт має бути позначено) та поле лічильника `<spinbox>`. За допомогою поля лічильника користувач може вибрати значення від `"min"` до `"max"` з типовим або початковим значенням `"0.95"`. Встановленням типу `type` у значення `"real"` ми повідомляємо програмі, що прийнятними є дійсні числа, на відміну від типу `type=``"integer"`, для якого прийнятними були б лише цілі числа.

Також можна, а іноді навіть бажано, зробити `<frame>` придатним до позначення, замість додавання `<checkbox>` всередину. Див. довідник з форматування, щоб дізнатися більше. Тут ми цього не робили з міркувань збереження наочності.

    </tab>
                    </tabbook>
            </dialog>

Ось і усе для другої сторінки `<tabbook>`, усі сторінки у `<tabbook>` і усі елементи у `<dialog>`. Ми завершили визначення вигляду діалогового вікна.

    </document>

Нарешті, ми завершуємо теґ `<document>` і увесь опис. Графічний інтерфейс визначено. Тепер можна зберегти файл. Але як буде створено синтаксичні конструкції команд &R; на основі параметрів з графічного інтерфейсу? Ми поговоримо про це у наступному розділі. Втім, спершу, ми познайомимося із тим, якщо додати інтерфейс майстра та обговоримо ще декілька загальних питань.

### Додавання інтерфейсу майстра

Насправді, нам не потрібно визначати окремий інтерфейс майстра `<wizard>`, ми скористаємося іншим способом. Щоб додати інтерфейс майстра, додаємо теґ `<wizard>` на тому самому рівні, що і теґ `<dialog>`:

    <wizard label="Two Variable t-Test">
                            <page id="firstpage">
                                    <text>As a first step, select the two variables you want to compare against
                                            each other. And specify, which one you theorize to be greater. Select two-sided,
                                            if your theory does not tell you, which variable is greater.</text>
                                    <copy id="main_settings_row"/>
                            </page>

Дещо можна зрозуміти і без пояснень: ми додаємо теґ `<wizard>` із міткою `label` для створення майстра. Оскільки у майстрі може бути декілька сторінок, які буде показано одна за одною, далі ми визначаємо першу сторінку `<page>` і додаємо на неї пояснювальну нотатку `<text>`. Далі, ми користуємося теґом `<copy>`. Цей теґ позбавляє нас від потреби у визначенні того, що ми вже написали для `<dialog>`: теґ copy шукає інший теґ з таким самим ідентифікатором `id` у попередній частині коду XML. У нашому випадку це усе, що визначено у розділі `<dialog>`, тобто `<row>`, у якому є `<varselector>`, `<varslots>` і варіанти hypothesis у `<radio>`. Усе це копіюється без змін 1:1 і вставляється на місце елемента `<copy>`.

Тепер друга сторінка:

    <page id="secondpage">
                                    <text>Below are some advanced options. It's generally safe not to assume the
                                            variables have equal variances. An appropriate correction will be applied then.
                                            Choosing "assume equal variances" may increase test-strength, however.</text>
                                    <copy id="varequal"/>
                                    <text>Sometimes it's helpful to get an estimate of the confidence interval of
                                            the difference in means. Below you can specify whether one should be shown, and
                                            which confidence-level should be applied (95% corresponds to a 5% level of
                                            significance).</text>
                                    <copy id="frame_conf_int"/>
                            </page>
                    </wizard>

Майже те саме. Ми додаємо текст, а між ним `<copy>` (копіюємо подальші розділи з інтерфейсу діалогового вікна).

Звичайно ж, ви можете зробити вигляд інтерфейсу майстра дуже далеким від звичайного діалогового вікна, і можете не використовувати теґ `<copy>` взагалі. Втім, не забувайте призначати відповідним елементам однакові ідентифікатори `id` у обох інтерфейсах. Це використовується не лише для передавання параметрів з інтерфейсу діалогового вікна до інтерфейсу майстра і навпаки, коли користувач перемикає інтерфейси (що ще не реалізовано у поточній версії &rkward;), але і спрощує написання шаблонів коду (див. нижче).

### Деякі розмірковування щодо компонування інтерфейсу

У цьому розділі містяться деякі загальні розмірковування щодо того, де і які елементи графічного інтерфейсу слід використовувати. Якщо ви намагаєтеся створити свій перший додаток, можете пропустити цей розділ, оскільки він не стосується базової роботи з графічним інтерфейсом. Повертайтеся до цього розділу згодом, щоб дізнатися про те, як ви можете поліпшити графічний інтерфейс вашого додатка.

#### <radio>, <checkbox> і <dropdown>

Тре елементи `<radio>`, `<checkbox>`, `<dropdown>` мають подібне призначення: допомагають користувачеві вибрати один з декількох варіантів. Звичайно ж, поле з позначкою (checkbox) надає змогу вибрати лише один з двох варіантів: позначено чи не позначено. Отже, ним не можна скористатися, якщо варіантів більше за два. Але коли використовувати інші елементи? Ось декілька простих правил:

Якщо вам раптом захочеться створити `<radio>` або `<dropdown>` лише з двома пунктами, спочатку спитайте себе, чи не є питання, яке ви хочете задати користувачеві, питанням, відповіддю на яке буде «так» чи «ні». Наприклад, вибір між коригувати результати і не коригувати результати, або між вилучити пропущені значення і зберегти пропущені значення. Якщо це саме таке питання, оптимальним вибором буде `<checkbox>`: пункт з позначкою займає мало місця, має менше слів у мітках і є найпростішим для читання користувачем. Існує зовсім небагато ситуацій, коли варто вибирати `<radio>`, а не `<checkbox>`, якщо маємо лише два варіанти. Ось приклад: Метод обчислень: 'pearson'/'spearman'. Тут можливі і інші методи, а вибір методу не є вибором між двома взаємовиключними варіантами.

Вибір між `<radio>` і `<dropdown>` є здебільшого питанням наявності місця у вікні. `<dropdown>` має перевагу у тому, що споживає менше місця, навіть якщо варіантів вибору дуже багато. З іншого боку, `<radio>` має перевагу, яка полягає у тому, що усі варіанти можна бачити одразу, без натискання кнопки спадного списку. Загалом, якщо до вибору пропонується шість або більше варіантів, варто скористатися `<dropdown>`. Якщо ж варіантів п’ять або менше, перевагу слід надати `<radio>`.

## Створення коду &R; на основі параметрів графічного інтерфейсу

### Використання JavaScript у додатках &rkward;

Тепер, коли ми визначили графічний інтерфейс, слід попрацювати над створенням на його основі певного коду &R;. Для цього нам знадобиться ще один текстовий файл, `code.js`, який зберігатиметься у тому самому каталозі, що і `description.xml`. Ви можете бути знайомі з програмуванням JavaScript (або, якщо бути зовсім точним, ECMA-script) чи нічого не знайти про цю мову програмування. Документації щодо JS вдосталь, як у друкованій формі, так і на сторінках інтернету (приклад: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide). Але для виконання більшості завдань вам не потрібно багато знати про JS, достатньо бути ознайомленим із дуже базовими можливостями.

Після прочитання цього розділу ознайомтеся також із розділом щодо пакунка rkwarddev. У цьому пакунку можна знайти деякі функції &R; для створення коду JavaScript, який часто використовується у &rkward;. Також у пакунку є засоби автоматичного виявлення змінних, які використовуються у файлі XML додатка і створення базового коду JavaScript, з якого можна розпочати роботу над кодом додатка.

Текст файлів `.js` додатків має бути записано у кодуванні UTF-8. Якщо ви користуєтеся символами поза таблицею ASCII, переконайтеся, що ваш редактор використовує саме це кодування.

Для двопараметричної t-перевірки, файл `code.js` виглядатиме так (з проміжними коментарями):

#### preprocess()

    function preprocess () {
    }

Файл JS поділено між трьома окремими функціями: `preprocess()`, `calculate()` та `printout()`. Причиною є те, що не увесь код потрібен на усіх етапах роботи. У поточній версії функція попередньої обробки (preprocess) у більшості випадків не використовується (вам вона теж далеко не завжди буде потрібна).

#### calculate()

    function calculate () {
            echo ('res <- t.test (x=' + getString ("x") + ', y=' + getString ("y") + ', hypothesis="' + getString ("hypothesis") + '"' + getString ("varequal"));
            var conflevel = getString ("conflevel");
            if (conflevel != "0.95") echo (', conf.level=' + conflevel);
            echo (')\n');
    }

Ця функція виконує створення самого коду команд &R;, які буде виконано на основі параметрів з графічного інтерфейсу. Розгляньмо її детальніше: код, який буде використано створюється за допомогою інструкції `echo()`. Якщо розглянути інструкцію `echo()` крок за кроком, першою її частиною є

    res <- t.test (

у форматі звичайного тексту. Далі, нам слід заповнити значення, яке вибрано користувачем як перша змінна. Ми отримуємо це значення за допомогою функції `getString ("x")` і дописуємо його до рядка для трансляції. Це виводить значення елемента графічного інтерфейсу з `id=``"x"`: нашого першого поля для позначки, `<checkbox>`. Далі, ми дописуємо «, » і робимо подібну ж операцію для отримання значення елемента `"y"` — другого поля для позначки, `<checkbox>`. Для гіпотези (група `<radio>`) та поля для позначки `<checkbox>` щодо рівних дисперсій процедура дуже схожа на описану вище.

Зауважте, що замість об’єднання фрагментів виведення за допомогою + ви можете скористатися декількома інструкціями `echo()`. Усе буде виведено у один рядок. Щоб додати символ розриву рядка у створений код, вставте `"\n"` наприкінці рядка. Теоретично, ви навіть можете створити багаторядкову команду за допомогою однієї інструкції echo, але варто все ж обмежуватися одним рядком (або частиною одного рядка) у створеному однією інструкцією `echo()` коді.

Окрім функції `getString()`, передбачено функцію `getBoolean()`, яка намагатиметься повернути значення у логічному форматі (придатному до використання у інструкції `if()`), та функцію `getList()`, яка намагатиметься повернути спископодібні дані у `Array()` JS. Приклади застосування цих функцій буде наведено нижче.

У наявних додатках ви знайдете багато використань `getValue()` замість `getString()`. Фактично, ці дві функції майже ідентичні. Втім, використанню `getString()`, `getBoolean()` та `getList()` слід надавати перевагу, починаючи з версії 0.6.1.

Для довірчого рівня все трошки складніше. З естетичних міркувань ми не хочемо явним чином вказувати довірчий рівень, який слід використовувати, якщо він відповідає типовому значенню. Отже, замість безумовного виведення значення, нам слід спочатку отримати його до змінної. Далі, ми перевіряємо, чи відрізняється ця змінна від `"0.95"`, і якщо це так, виводимо додатковий аргумент. Нарешті, ми виводимо завершальну дужку та символ кінця рядка, `")\n"`. Ось і усе у функції calculate.

#### printout()

    function printout () {
            echo ('rk.header (' + i18n ("Two Variable t-Test") + ')\n');
            echo ('rk.print (res)\n');
    }

Ось це і все, що може знадобитися у більшості випадків для функції printout. `rk.header()` виводить стандартний рядок заголовка для результатів. Зауважте, що у файлах `.js` вам доведеться позначити усі придатні до перекладу рядки вручну за допомогою функції `i18n()` або альтернативних функцій. Докладніше про це у розділі щодо інтернаціоналізації. Ви також можете додати певні відомості щодо цього, якщо потрібно, наприклад:

    function printout () {
            new Header (i18n ("Two Variable t-Test"))
                      .addFromUI ("varequal")
                      .add (i18n ("Confidence level"), getString ("conflevel"))  // Note: written like this for illustration purposes. More automatic:
            //        .addFromUI ("conflevel")
                      .print ();
    echo ('rk.print (res)\n');
    }

`rk.print()` використовує пакунок R2HTML для створення даних у форматі HTML. Ще однією корисною функцією є `rk.results()`: ця функція також здатна виводити різні типи таблиць результатів. Втім, якщо ви не певні, просто скористайтеся `rk.print()`, — цього достатньо. Клас JS `Header` є допоміжним класом на рівні JS для створення викликів до `rk.header()` (достатньо зазирнути до створеного коду &R;). Іноді виникає потреба у безпосередньому виклику `echo ('rk.header (...)')` для виведення заголовка до ваших результатів.

Зауважте, що на внутрішньому рівні виведені дані є на цей момент часу простим документом &HTML;. Тому у вас може виникнути бажання додати нетиповий код &HTML; за допомогою `rk.cat.output()`. Хоча це і працюватиме, будь ласка, не робіть так. Формат виведення може бути змінено (наприклад на ODF) у майбутніх версіях, отже варто не додавати специфічного для &HTML; коду. Краще не ускладнювати речі і користуватися `rk.header()`, `rk.print()`, `rk.results()` і, якщо потрібно, `rk.print.literal()`. Якщо усі ці функції не задовольняють ваші потреби у форматуванні, повідомте про це розробникам &rkward; за допомогою списку листування розробників.

Вітаємо! Ви створили ваш перший додаток. За допомогою наступних глав ви зможете удосконалити і розширити ваші знання.

### Угоди, правила і основа

Існує багато способів написання коду &R; для виконання певного завдання, і ще більше існує способів створити цей код &R; за допомогою JS. Як саме ви це зробите — це ваша справа. Втім, існує певний набір правил, які ви маєте виконувати, і базові відомості, які ви маєте розуміти.

#### Опис середовища `local()`

Майже завжди вам доведеться створювати один або декілька тимчасових об’єктів &R; у коді, який створюватиметься вашим додатком. Зазвичай, поява цих об’єктів у робочому просторі користувача і потенційний перезапис змінних користувача є небажаним. Отже, увесь створений додатком код запускається у середовищі `local()` (див. сторінку довідки &R; щодо функції `local()`). Це означає, що усі створені вами змінні є тимчасовими і постійно не зберігатимуться.

Якщо користувач явним чином попросить зберегти змінну, вам доведеться надати об’єктові значення за допомогою виразу `.GlobalEnv$objectname <- значення`. Загалом, не використовуйте оператор `<<-`. Ви не обов’язково надає значення у .GlobalEnv.

Однією з важливих проблем є використання `eval()`. Вам варто пам’ятати, що типово eval використовуватиме для обчислень поточне середовище, тобто локальне середовище (local). У більшості випадків усе працюватиме як слід, але не завжди. Таким чином, якщо вам потрібно скористатися `eval()`, вам, ймовірно, варто вказати параметр `envir`: `eval(..., envir=globalenv()`).

#### Форматування коду

Найголовніше, щоб ваш код мовою &R; працював як слід, але також важливо, щоб його було просто читати. Тому, будь ласка, не забувайте про форматування. Ось декілька правил:

Звичайні інструкції верхнього рівня у &R; вирівнюються ліворуч.

Інструкції підлеглого блоку має бути записано із відступом у одну табуляцію (див. наведений нижче приклад).

Якщо ви виконуєте дуже складні обчислення, додавайте до них коментарі, особливо для позначення певних логічних частин коду. Зауважте, що існує спеціальна функція `comment()` для додавання придатних до перекладу коментарів у створений код.

Наприклад, створений код може виглядати так, як у наведеному нижче фрагменті. Той самий код без відступів і коментарів буде доволі важко читати, хоча він і не дуже складний:

    # спочатку визначаємо хилитання і обертання
    my.wobble <- wobble (x, y)
    my.rotation <- wobble.rotation (my.wobble, z)

    # метод ухилення має бути вибрано відповідно до обертання
    if (my.rotation > wobble.rotation.limit (x)) {
            method <- "foo"
            result <- boggle.foo (my.wobble, my.rotation)
    } else {
            method <- "bar"
            result <- boggle.bar (my.wobble, my.rotation)
    }

#### Робота зі складними параметрами

Багато додатків можуть виконувати декілька функцій. Наприклад, додаток Описова статистика може обчислювати середнє, діапазон, суму, добуток, медіану, довжину вибірки тощо. Втім, типово, користувачу буде потрібна лише частина з результатів обчислень. У цьому випадку, будь ласка, намагайтеся робити створений код &R; якомога простішим. Код має містити лише ті команди, які відповідають вибраним вами параметрам. Щоб досягти цього, скористайтеся прикладом типового взірця компонування (у JS; тут domean, domedian і dosd будуть елементами <checkbox>):

    function calculate () {
            echo ('x <- <' + getString ("x") + ')\n');
            echo ('results <- list ()\n');

            if (getBoolean ("domean.state")) echo ("results$" + i18n ("Mean value") + " <- mean (x)\n");
            if (getBoolean ("domedian.state")) echo ("results$" + i18n ("Median") + " <- median (x)\n");
            if (getBoolean ("dosd.state")) echo ("results$" + i18n ("Standard deviation") + " <- sd (x)\n");
            //...
    }

### Підказки і рецепти

Ось декілька різноманітних прийомів, які можуть зробити написання додатків трохи менш нудною справою:

Якщо вам потрібне значення параметра графічного інтерфейсу у декількох місцях коду вашого додатка, варто надати його значення якійсь змінній у JS, і використовувати її замість повторного отримання значення за допомогою `getString()/getBoolean()/getList()`. Такий спосіб є швидшим, зручнішим для читання та таким, що заощаджує час на набирання коду:

    function calculate () {
            var narm = "";        // na.rm=FALSE is the default in all functions below
            if (getBoolean ("remove_nas")) {
                    $narm = ", na.rm=TRUE";
            }
            // ...
            echo ("results$foo <- foo (x" + narm + ")\n");
            echo ("results$bar <- bar (x" + narm + ")\n");
            echo ("results$foobar <- foobar (x" + narm "\n");
            // ...
    }

Проста допоміжна функція `makeOption()` допоможе вам уникнути додавання параметрів із типовими значеннями:

    function calculate () {
            var options
            //...
            // Нічого не робити, якщо VALUE дорівнює 0.95 (типове значення). Інакше додати ', conf.int=VALUE' до параметрів.
            options += makeOption ("conf.int", getString ("confint"), "0.95");
            //...
    }

## Створення сторінки довідки

Оскільки додаток, загалом, вже працює як слід, наспів час створити для нього сторінку довідки. Хоча, зазвичай, вам не варто пояснювати кожен раз усе з початку, було б добре надати певні відомості щодо деяких з параметрів та посилання на пов’язані додатки і функції &R;.

Після прочитання цієї глави зверніться до пакунка rkwarddev. У ньому реалізовано декілька функцій &R; для створення більшості теґів XML &rkward;. Пакунок також допоможе вам створити базовий каркас файлів довідки на основі наявних файлів додатків XML.

Вам варто додати це до коду XML вашого додатка (якщо ви цього ще не зробили, зробіть це зараз):

    <document>
            [...]
            <help file="назва_файла.rkh" />
            [...]
    </document>

Де, очевидно, вам слід замінити вираз `назва_файла` на відповідну назву. Тепер, створимо цей файл `.rkh`. Ось приклад із наведеними в ньому описами:

    <!DOCTYPE rkhelp>
    <document>
            <summary>
    У цьому розділі мають бути основні відомості щодо того, які завдання виконує додаток.
    Цей розділ завжди буде показано на самому початку сторінки довідки.
            </summary>

            <usage>
    У розділі usage можуть міститися трохи практичніші відомості. Втім, тут не обов’язково
    пояснювати докладно усі параметри (це слід залишити для розділу «settings»).

    Щоб розпочати новий абзац, вставте порожній рядок, як у нашому прикладі.
    Цей рядок, навпаки, розташовуватиметься у тому самому абзаці.

    В усіх розділах ви можете використовувати простий код HTML, зокрема для <b>жирного</b> або
    <i>курсивного</i> тексту. Втім, не слід зловживати таким форматуванням.

    Розділ usage завжди є другим розділом, який буде показано на сторінці довідки.
            </usage>

            <section id="sectionid" title="Типовий розділ" short_title="Типовий">
    Якщо потрібно, ви можете додавати розділи між розділом usage та settings.
    Втім, зазвичай, у вас не повинно виникнути потреби у таких розділах під час документування додатків. Атрибут «id»
    дає точку прив’язки для переходу до цього розділу з меню навігації. Атрибут «short_title»
    визначає скорочений заголовок для панелі навігації. Цей атрибут є необов’язковим, типово,
    буде використано основний «title» для заголовка розділу і для посилання на панелі
    навігації.

    У будь-якому розділі ви можете вставити посилання на подальшу інформацію. Для цього вставте такий код:

    <link href="URL">назва посилання</link>

    Де URL може бути зовнішнім посиланням, наприклад http://rkward.kde.org .
    На сторінках довідки передбачено декілька спеціалізованих варіантів адрес:

    <link href="rkward://page/шлях/ід_сторінки"/>

    Такі адреси надають змогу посилатися на сторінки довідки з rkward (не сторінки додатків).

    <link href="rkward://компонент/[простір_назв/]ід_компонента"/>

    Так можна посилатися на сторінки довідки іншого додатка. Частину [простір_назв/] можна пропустити
    (у цьому випадку використовуватиметься стандартний простір назв rkward, приклад:
    <link href="rkward://component/import_spss"/> і
    <link href="rkward://component/rkward/import_spss"/> є еквівалентними).
    Ідентифікатор ід_компонента є тим самим, який було визначено у &pluginmap;.

    <link href="rkward://rhelp/rfunction"/>

    Посилання на довідку з R щодо «rfunction».

    Зауважте, що назви посилань для цього типу посилань буде створено автоматично.
            </section>

            <settings>
                    <caption id="ід_вкладки_або_фрейма"/>
                    <setting id="ід_елемента">
    Опис графічного елемента, що ідентифікується вказаним ідентифікатором
                    </setting>
                    <setting id="ід_елементаb" title="опис">
    Зазвичай, заголовок (title) елемента графічного інтерфейсу буде видобуто з
    визначення XML додатка автоматично. Втім,
    для деяких елементів графічного інтерфейсу цього опису може бути недостатньо для надійної ідентифікації.
    У цьому випадку ви можете додати заголовок явним чином за допомогою атрибута «title».
                    </setting>
                    <setting id="ід_елементаc">
    Опис графічного елемента, який позначено ідентифікатором «ід_елементаc»
                    </setting>
                    [...]
            </settings>

            <related>
    Типово, розділ related просто містить посилання, ось так:

    <ul>
            <li><link href="rkward://rhelp/mean"/></li>
            <li><link href="rkward://rhelp/median"/></li>
            <li><link href="rkward://component/related_component"/></li>
    </ul>
            </related>

            <technical>
    У розділі technical (необов’язковий, завжди останній) можуть міститися деякі подробиці
    щодо реалізації додатка, які можуть бути корисними лише розробникам RKWard. Цей розділ
    корисний для додатків, які було розроблено для вбудовування у багато інших додатків.
    Тут можуть бути подробиці щодо параметрів, доступних для налаштовування вбудованого додатка,
    і того, які розділи коду містять відповідний код R.
            </technical>
    </document>

## Логічна взаємодія між елементами графічного інтерфейсу

### Логіка графічного інтерфейсу

Усі базові поняття щодо створення додатків до &rkward; було описано у попередніх розділах. Цих базових понять достатньо для багатьох, якщо не більшості, випадків. Втім, іноді вам можуть знадобитися додаткові можливості з керування графічним інтерфейсом вашого додатка.

Наприклад, припустімо, що ви хочете розширити приклад з t-перевіркою, використаний у цій документації, так, щоб можна було виконувати два завдання: порівняння змінної з іншою змінною (як показано) і порівняння змінної зі сталим значенням. Одним зі способом це реалізувати є додавання пунктів варіантів для перемикання між двома режимами та додавання пункту лічильника для введення сталого значення, з яким слід порівнювати змінну. Розгляньмо цей спрощений приклад:

    <!DOCTYPE rkplugin>
    <document>
            <code file="code.js"/>

            <dialog label="T-Test">
                    <row>
                            <varselector id="vars"/>
                            <column>
                                    <varslot id="x" types="number" source="vars" required="true" label="compare"/>
                                    <radio id="mode" label="Compare against">
                                            <option value="variable" checked="true" label="another variable (select below)"/>
                                            <option value="constant" label="a constant value (set below)"/>
                                    </radio>
                                    <varslot id="y" types="number" source="vars" required="true" label="variable" i18n_context="Noun; a variable"/>
                                    <spinbox id="constant" initial="0" label="constant" i18n_context="Noun; a constant"/>
                            </column>
                    </row>
            </dialog>
    </document>

Здається усе добре, але з таким графічним інтерфейсом є декілька проблем. По-перше, і varslot, і spinbox буде завжди показано, хоча насправді буде використано лише один з цих елементів. Гірше того, varslot завжди потребуватиме коректного вибору, навіть якщо порівняння буде виконуватися лише зі сталою. Очевидно, якщо ми створюємо багатоцільовий графічний інтерфейс, подібний до цього, нам потрібна більша гнучкість. Введіть до розділу `<logic>` (вставлено на той самий рівень, що і `<code>`, `<dialog>` або `<wizard>`):

    [...]
            <code file="code.js"/>

            <logic>
                    <convert id="varmode" mode="equals" sources="mode.string" standard="variable" />

                    <connect client="y.visible" governor="varmode" />
                    <connect client="constant.visible" governor="varmode.not" />
            </logic>

            <dialog label="T-Test">
            [...]

Першим рядком у розділі logic є теґ `<convert>`. На базовому рівні, це створює нову булеву властивість (увімкнено або вимкнено, так або ні), якою можна згодом скористатися. Ця властивість (`"varmode"`) матиме значення «так», якщо буде вибрано верхній варіант, і значення «ні», якщо буде вибрано нижній варіант. Як же це досягається?

По-перше, у `sources` наведено список властивостей джерела, на якими слід працювати (у цьому випадку лише одну; декілька можна вказати так: `sources=``"mode.string;щось_іще"`, тоді `"varmode"` матиме значення true, якщо і `"mode.string"` і `"щось_іще"` дорівнюють рядку `"variable"`). Зауважте, що у цьому випадку ми не написали просто `"mode"` (як було у `getString("mode")`), а `"mode.string"`. Насправді, це пов’язано з тим, як працює засіб вибору з варіантів на внутрішньому рівні: він має властивість string, у якій зберігається її рядкове значення. `getString("mode")` — просто скорочення, яке є еквівалентним до `getString("mode.string")`. Ознайомитися із усіма властивостями різних елементів графічного інтерфейсу можна за допомогою відповідного розділу цього підручника.

По-друге, ми встановлюємо режим перетворення `mode=``"equals"`. Це означає, що ми хочемо перевірити, чи є джерело (чи джерела) рівним певному значенню. Нарешті, standard є значенням, із якими слід виконувати порівняння, отже, за допомогою `standard=``"variable"` ми перевіряємо, чи є властивість `"mode.string"` рівною рядку `"variable"` (значенню верхнього пункту варіанта). Якщо є, значенням змінної varmode буде true, інакше — false.

Тепер до справи: ми з’єднуємо (`<connect>`) змінну `"varmode"` з властивістю y.visible, яка керує видимістю varslot-а `"y"`. Зауважте, що будь-який елемент, який стає невидимим, неявним чином стає необов’язковим. Отже, якщо позначено верхній варіант, varslot `"y"` буде обов’язковим і видимим. Якщо ж позначено інший варіант, він стане необов’язковим і невидимим.

Для поля лічильника нам потрібне зовсім протилежне. На щастя, нам не обов’язково додавати ще одне `<convert>` для цього: булеві змінні легко перетворювати на протилежні за допомогою додавання модифікатора `"not"`, отже, ми з’єднаємо `"varmode.not"` із властивістю видимості поля лічильника. У результаті або буде показаним і обов’язковим varslot, або буде показаним і обов’язковим поле лічильника (spinbox). Усе залежатиме від вибраного варіанта. Графічний інтерфейс змінюватиметься автоматично у відповідь на дії користувача. Спробуйте поекспериментувати з нашим прикладом.

Повний список властивостей можна знайти у довідковій частині підручника. Втім, варто обговорити ще одну властивість, яка є специфічною для усіх елементів графічного інтерфейсу: enabled. Вона не така дієва, як visible. Вона не керує показом або приховуванням елемента графічного інтерфейсу, а лише вмикає або вимикає його. Вимкнені елементи типово буде показано сірим кольором, вони не реагуватимуть на дії користувача.

Окрім `<convert>` і `<connect>`, у розділі `<logic>` можна використати ще декілька елементів. Наприклад, розгалуження за умовою може бути реалізовано за допомогою елемента `<switch>`. Докладніший опис можна знайти у довідці щодо елементів логіки.

### Керування логікою графічного інтерфейсу за допомогою скриптів

Хоча з’єднання властивостей, описаного вище, часто достатньо, іноді гнучкішим і зручнішим способом керування логікою графічного інтерфейсу є використання скриптів JS. У цей спосіб наведений вище приклад може бути переписано так:

    [...]
            <code file="code.js"/>
    '
            <logic>
                    <script><![CDATA[
                            // У цьому блоці використано код ECMAScript
                            // інструкція вищого рівня викликається лише один раз
                            gui.addChangeCommand ("mode.string", "modeChanged ()");

                            // ця функція викликається кожного разу, коли змінюється режим «mode»
                            modeChanged = function () {
                                    var varmode = (gui.getString ("mode.string") == "variable");
                                    gui.setValue ("y.enabled", varmode);
                                    gui.setValue ("constant.enabled", !varmode);
                            }
                    ]]></script>
            </logic>

            <dialog label="T-Test">
            [...]

Перший рядок коду повідомляє &rkward;, що слід викликати `modeChanged()`, щоб визначити, чи змінилося значення пункту варіанта `id=``"mode"`. Всередині цієї функції ми визначаємо допоміжну змінну `"varmode"`, яка має значення true, якщо mode має значення `"variable"` як `"constant"`. Далі, ми використовуємо `gui.setValue()` для встановлення властивостей enabled `"y"` і `"constant"` у той самий спосіб, як ми робили це з інструкціями `<connect>` раніше.

Керування логікою графічного інтерфейсу за допомогою скриптів корисне зокрема тоді, коли ви хочете змінити доступні параметри відповідно до типу об’єкта, який вибрано користувачем. Із списком доступних функцій можна ознайомитися у довідковому розділі.

Зауважте, що підхід до керування графічним інтерфейсом за допомогою скриптів може бути поєднано із інструкціями `<connect>` і `<convert>`, якщо це потрібно. Крім того, зауважте, що теґ `<script>` надає змогу вказати назву файла скрипту на додачу або як альтернативу до вбудовування скриптового коду до файла інтерфейсу. Втім, типово, продемонстроване вище вбудовування коду є зручнішим.

## Вбудовування додатків до додатків

### Випадки застосування вбудовування

Під час написання додатків часто виникає ситуація, коли ви створюється декілька додатків, які відрізняються лише у певних аспектах, але мають багато спільного. Наприклад, для креслення є багато загальних параметрів &R;, якими можна скористатися для більшості типів креслень. То чи треба створювати графічний інтерфейс і шаблон JS для таких додатків знову і знову?

Звичайно ж, повторення однакових дій є дуже марудним. На щастя, робити це не треба. Достатньо створити загальні функції один раз, а потім вбудувати їх до декількох схожих додатків. Фактично, можна вбудувати будь-який додаток до будь-якого іншого додатка, навіть якщо початковий автор вбудовуваного додатка ніколи не думав про те, що його додаток будуть вбудовувати до іншого.

### Вбудовування до діалогового вікна

Гаразд, досить слів. Як це все працює? Дуже просто: достатньо скористатися теґом `<embed>`. Ось позбавлений усього зайвого приклад:

    <dialog>
            <tabbook>
                    <tab [...]>
                            [...]
                    </tab>
                    <tab label="Plot Options" i18n_context="Options concerning the plot">
                            <embed id="plotoptions" component="rkward::plot_options"/>
                    </tab>
                    <tab [...]>
                            [...]
                    </tab>
            </tabbook>
    </dialog>

Тут увесь графічний інтерфейс або додаток параметрів креслення (окрім, звичайно ж, стандартних елементів, подібних до кнопки Submit) вбудовано до нашого додатка (спробуйте!).

Як можна бачити, синтаксис теґу `<embed>` доволі простий. У ньому використовується `id`, як і у більшості елементів. Параметр component визначає, який додаток слід вбудувати, його значення можна знайти у файлі &pluginmap; (`"rkward::plot_options"` є результатом склеювання простору назв rkward, роздільника :: і назви компонента plot_options).

### Створення коду при вбудовуванні

Поки усе зрозуміло, але як щодо створеного коду? Як поєднуватиметься код основного і вбудованого додатка? Достатньо просто написати у коді JS основного додатка щось таке:

    function printout () {
            // ...
            echo ("myplotfunction ([...]" + getString ("plotoptions.code.printout"); + ")\n");
            // ...
    }

Отже, по суті, ми отримуємо код, створений вбудованим додатком, у той самий спосіб, у який отримуємо будь-які інші параметри графічного інтерфейсу. Тут рядок `"plotoptions.code.printout"` можна розгорнути так: Розділ printout створеного коду елемента із `id` plotoptions (plotoptions — ідентифікатор, який ми надали теґу `<embed>` вище). І так, якщо вам потрібні додаткові важелі керування, ви навіть можете отримати значення окремих елементів графічного інтерфейсу у вбудованому додатку (але не навпаки, оскільки вбудований додаток нічого не знає про своє середовище).

### Вбудовування до майстра

Якщо у вашому додатку передбачено графічний інтерфейс майстра, вбудовування, в основному, працює так само. Загалом, вам слід зробити так:

    <wizard [...]>
                    [...]
                    <page id="page12">
                            [...]
                    </page>
                    <embed id="plotoptions" component="rkward::plot_options"/>
                    <page id="page13">
                            [...]
                    </page>
                    [...]
            </wizard>

Якщо вбудований додаток надає інтерфейс майстра, його сторінки буде вставлено безпосередньо між `"page12"` і `"page13"` у вашому додатку. Якщо вбудований додаток використовує лише інтерфейс діалогового вікна, буде додано дону нову сторінку між вашими сторінками `"page12"` і `"page13"`. З точки зору користувача, вбудовування буде непомітним.

### Не таке вбудоване вбудовування: кнопка «Інші параметри»

Хоча вбудовування виглядає потужним механізмом, вам не варто ним зловживати. Забагато функцій у файлі графічного інтерфейсу ускладнить пошук відповідних параметрів. Звичайно ж, іноді може виникнути потреба у вбудовуванні значної кількості параметрів роботи додатка (зокрема усіх параметрів функції `plot()`), але оскільки вони, зазвичай, є лише параметрами необов’язкового налаштовування, не слід віддавати їм якесь визначне становище у графічному інтерфейсі.

Альтернативно, можна вбудувати ці параметри як кнопку:

    <dialog>
            <tabbook>
                    [...]
                    <tab label="Options">
                            [...]
                            <embed id="plotoptions" component="rkward::plot_options" as_button="true" label="Specify plotting options"/>
                    </tab>
                    [...]
            </tabbook>
    </dialog>

У цьому випадку до вашого додатка буде доданого одну кнопку із міткою Specify plotting options. Якщо користувач натисне цю кнопку, буде відкрито діалогове вікно із усіма параметрами вбудованого додатка. Хоча цей вбудований графічний інтерфейс і не видно більшу частину часу, ви можете отримати його параметри у той самий, описаний вище спосіб.

Кнопковий підхід варто використовувати лише для додатків, які ніколи не працюють некоректним чином (через пропущені або помилкові значення параметрів). Якщо це не так, користувач не зможе надіслати код на виконання, але не зможе дізнатися нічого про причину, оскільки її буде приховано під нашою кнопкою.

### Вбудовування або визначення незавершених додатків

Деякі додатки — фактично, додаток plot_options, використаний як приклад вище, є одним з них — не є самодостатніми. У них просто немає елементів графічного інтерфейсу для вибору деяких важливих значень. Їх призначено лише для вбудовування до інших додатків.

Наскільки незавершеним є додаток plot_options? Гаразд, для визначення своєї поведінки йому потрібні назви об’єктів або вирази для осей x і y (насправді, для його роботи достатньо одного з цих об’єктів чи виразів, але хоч один має бути задано, щоб додаток зміг працювати). Втім, у нього немає механізму для вибору цих об’єктів або введення їх у якийсь інший спосіб. То як же він дізнається про ці об’єкти?

У розділі логіки роботи додатка plot_options є ще два рядки, які ми ще не обговорили:

    <logic>
                    <external id="xvar" />
                    <external id="yvar" />

                    [...]
            </logic>

Це визначає дві додаткові властивості у додатку plot_options. Єдиною їхньою метою є з’єднування з певними (ще невідомими) властивостями додатка, до якого відбувається вбудовування. У додатку plot_options ці дві властивості просто використовуються як будь-які інші, наприклад, у шаблоні JS plot_options є виклики `getString("xvar")`.

Далі, для незавершеного додатка не можна наперед дізнатися, до якого додатка відбуватиметься вбудовування і які параметри викликатиме основний додаток. Отже, нам доведеться додати два рядки у розділ logic додатка, до якого ми вбудовуємо інший додаток:

    <logic>
                    [...]

                    <connect client="plotoptions.xvar" governor="xvarslot.available" />
                    <connect client="plotoptions.yvar" governor="yvarslot.available" />
            </logic>

Нічого принципово нового, ми вже розбирали інструкції `<connect>` у розділі щодо логіки графічного інтерфейсу. Ми просто з’єднали значення у двох varlot-ах (які у нашому прикладі називаються `"xvarslot"` і `"yvarslot"`) із зовнішніми властивостями вбудованого додатка. Ось і усе. Усі інші дії буде виконано автоматично.

## Робота з багатьма подібними додатками

### Огляд різних підходів

Іноді, виникає потреба у розробці додатків для реалізації послідовності подібних функціональних можливостей. Прикладом може слугувати побудова графіків розподілів. При цьому використовується подібний програмний код і, звичайно ж, графічні інтерфейси таких додатків мають бути подібними. Крім того, подібними будуть і значні частини файлів довідки додатків. Різними у додатках будуть лише декілька параметрів.

Найпримітивнішим підходом до вирішення цієї проблеми є розробка одного додатка з наступним простим копіюванням його вмісту, файлів `.js`,`.xml` та `.rkh`, до інших додатків та внесенням у скопійований текст змін. Втім, що трапиться, якщо згодом ви знайдете просту друкарську помилку, яку було скопійовано і вставлено до усіх додатків? Що, якщо вам захочеться додати підтримку нової можливості? Вам доведеться вносити зміни до усіх ваших додатків, один за одним. Це марудна і нудна справа.

Другий підхід полягає у використанні вбудовування. Втім, іноді і вбудовування не є повним вирішенням проблеми, яку ми розглядаємо, здебільшого через те, що вбудовувані фрагменти є надто великими для використання, а їхнє додавання обмежує можливості компонування коду. Для таких випадків передбачено можливості включення файлів `.js`, включення файлів `.xml` та фрагменти (втім, варто ознайомитися із думками щодо того, коли слід надавати перевагу вбудовуванню).

Трохи попереджень, перш ніж ви розпочнете читання цього розділу: ці концепції можуть спростити створення серії подібних додатків та поліпшити можливості із супроводу та читання коду таких додатків. Втім, зловживання ними може легко спричинити зворотний ефект. Використовуйте ці концепції виважено.

### Використання інструкції include JS

У додатках до &rkward; ви можете дуже просто включити один файл скрипту до іншого. Цінність цього стає очевидною, коли деякі з розділів вашого коду JS є однаковими у всіх додатках. Ви можете просто визначити ці розділи у окремому файлі `.js` і включити цей файл до усіх файлів `.js` додатка. Приклад:

    // цей файл називається "common_functions.js"

    function doCommonStuff () {
            // ймовірно, отримуємо деякі параметри тощо.
            // ...
            comment ("Це код R, який використовується у декількох різних додатках\n");
            // ...
    }

    // це один з ваших типових файлів .js додатків

    // включаємо загальні функції
    include ("common_functions.js");

    function calculate () {
            // виконуємо якісь дії
            // ...

            // вставляємо загальний код
            doCommonStuff ();
    }

Зауважте, що іноді ліпше зробити навпаки, і визначити каркас функцій `preprocess()`, `calculate()` і `printout()` у одному файлі, а потім викликати цей файл у тих частинах, які є різними для додатків. Приклад:

    // це файл, який називається «common_functions.js»

    function calculate () {
            // виконуємо якісь дії, які є спільними для усіх додатків
            // ...

            // додаємо щось, що є різним для додатків
            getSpecifics ();

            // ...
    }

    // це один із ваших звичайних файлів .js додатка

    // включити загальні функції
    include ("common_functions.js");

    // зауваження: тут не визначається функція calculate().
    // цю функцію визначено у common_functions.js.

    function getSpecifics () {
            // виведення якогось коду R
    }

Однією з проблем цього підходу, які вам слід мати на увазі, є область видимості змінних. Щоб дізнатися про область видимості більше, ознайомтеся із підручником з JS.

Ця методика широко використовується у додатках для малювання графіків розподілів та малюванні розподілів і ЦГТ, отже вам варто ознайомитися з кодом цих додатків, якщо ви шукаєте приклади.

### Включення файлів `.xml`

Майже та сама можливість включення існує і для файлів `.xml`, &pluginmap; і `.rkh`. У будь-якому місці цих файлів ви можете розташувати теґ `<include>`, як це показано нижче. У результаті увесь вміст включеного файла XML (якщо бути точним, усе у тезі `<document>` цього файла) буде буквально вставлено у відповідну позицію файла. Зауважте, що включати у такий спосіб можна лише інший файл XML.

    <document>
            [...]
            <include file="another_xml_file.xml"/>
            [...]
    </document>

Атрибут `file` визначає назву файла відносно каталогу, у якому зберігається поточний файл.

### Використання <snippets>

Хоча включення файлів, як це показано у попередньому розділі є достатньо потужним інструментом, найкориснішим він стає, якщо його поєднати з фрагментами, `<snippets>`. Фрагменти — малі шматки коду, які ви можете вставити у іншу частину файла. Найкращою ілюстрацією буде приклад:

    <document>
            <snippets>
                    <snippet id="note">
                            <frame>
                                    <text>
                    This will be inserted at two places in the GUI
                                    </text>
                            </frame>
                    </snippet>
            </snippets>
            <dialog label="test">
                    <column>
                            <insert snippet="note"/>
                            [...]
                            <insert snippet="note"/>
                    </column>
            </dialog>
    </document>

Отже, ви визначаєте фрагмент коду у одному місці на початку файла XML, а потім використовуєте `<insert>` для вставлення коду туди, куди ви хочете його вставити.

Хоча цей приклад і не є таким уже надкорисним сам собою, можна уявити його у поєднанні з включенням за допомогою `<include>` файла `.xml`. Зауважте, що ви також можете розташувати фрагменти для файла `.rkh` у тому самому файлі. Ви просто вкажете його за допомогою `<include>` і вставите відповідний фрагмент за допомогою `<insert>`:

    <!-- Це файл, який називається «common_snippets.xml» -->
    <document>
            <snippet id="common_options">
                    <spinbox id="something" [...]/>
                    [...]
            </snippet>
            <snippet id="common_note">
                    <text>Важлива нотатка для цього типу додатків</text>
            </snippet>

            <snippet id="common_help">
                    <setting id="something">Виконує якусь дію</setting>
                    [...]
            </snippet>
    </document>

    <!-- Це файл .xml додатка -->
    <document>
            <snippets>
                    <!-- Імпортуємо загальні фрагменти -->
                    <include file="common_snippets.xml"/>
            </snippets>

            <dialog label="test2">
                    <insert snippet="common_note"/>
                    <spinbox id="something_plugin_specific" [...] />
                    <insert snippet="common_options"/>
            </dialog>
    </document>

Подібно до включення до JS, зворотний підхід часто є навіть ще кориснішим:

    <!-- Це файл із назвою «common_layout.xml» -->
    <document>
            <column>
                    <insert snippet="note">
                    [...]
                    <insert snippet="plugin_parameters">
            </column>
            [...]
    </document>

    <!-- Це файл .xml додатка -->
    <document>
            <snippets>
                    <snippet id="note">
                            <text>Нотатка для цього додатка</text>
                    </snippet>

                    <snippet id="plugin_parameters">
                            <frame label="Специфічні для цього додатка параметри">
                                    [...]
                            </frame>
                    </snippet>
            </snippets>

            <dialog label="test3">
                    <include file="common_layout.xml"/>
            </dialog>
    </document>

Нарешті, можна вставляти фрагменти за допомогою `<insert>` у інші фрагменти, якщо виконуються такі умови: а) буде використано лише один рівень вкладеності і б) розділ `<snippets>` розташовано на початку файла (до вставляння вкладеного фрагмента); причиною цього є те, що обробка інструкцій `<insert>` відбувається у файлі згори вниз.

### <include>, <snippets> і <embed>

На перший погляд, теґи `<include>` і `<snippets>` надають можливість зробити те саме, що і вбудовування: ви можете повторно використати частину коду у різних додатках. Отже, у чому відмінність між цими підходами, і як вибрати з них той, яким слід скористатися?

Ключова відмінність між цими концепціями полягає у тому, що придатні до вбудовування додатки є ціліснішими. У них поєднується графічний інтерфейс, код для створення на його основі коду &R; і сторінка довідки. Include та insert, навпаки, можна використовувати дрібнішими частинами, але за рахунок погіршення модульності структури додатків.

Додатку, до якого вбудовується інший додаток, типово, не потрібні докладні відомості щодо внутрішньої структури вбудованого додатка. Яскравим прикладом цього є додаток plot_options. Додаткам, до яких його вбудовують не потрібні дані щодо усіх параметрів, які можна змінити, або способу їх надання. Це добре, оскільки інакше зміна додатка plot_options могла б призвести до потреби у коригуванні всіх додатків, до яких його вбудовано (а їх доволі багато). І навпаки, include та insert розкривають усі деталі включення та вставлення, отже усі додатки, у яких використовуються ці інструкції, наприклад, повинні містити точні ідентифікатори і використовувати відповідні типи елементів.

Отже, ось просте правило: include та insert є чудовим рішенням, якщо відповідні параметри потрібні лише у доволі обмеженій групі додатків. Вбудовані додатки є ліпшим рішенням, якщо група додатків, до яких планується вбудовування, не є жорстко визначеною, і якщо потрібна модульна структура комплекту додатків. Ще одне просте правило: якщо ви можете розташувати типові фрагменти коду до одного фрагмента, так і зробіть, і скористайтеся вбудовуванням. Якщо ж для спільних частин доведеться створювати багато невеличких фрагментів коду, скористайтеся `<snippets>`. Ну, і нарешті: якщо усі додатки надають дуже подібні функціональні можливості, ймовірно, варто скористатися include та insert. Якщо ж додатки, по суті, мають один або два спільні модулі, слід користуватися вбудовуванням.

## Концепції, якими можна скористатися у спеціалізованих додатках

У цій главі наведено відомості щодо певних тем, які є корисними лише для деяких класів додатків.

### Додатки для створення графіків

Створити креслення з додатка доволі просто. Втім, існує декілька неприємних речей, які слід обійти, та деякі чудові загальні функціональні можливості, про які ви маєте знати. У цьому розділі продемонстровано базові поняття та наведено канонічний приклад, якому вам варто слідувати під час створення додатків для креслення.

#### Малювання у вікні виведення результатів

Для створення креслення у вікні виведення даних скористайтеся `rk.graph.on()` безпосередньо перед створенням креслення і `rk.graph.off()` одразу після його створення. Це те саме, що, наприклад, викликати `postscript()` і `dev.off()` у звичайному сеансі &R;.

Втім, що важливо, вам слід завжди викликати `rk.graph.off()` після виклику `rk.graph.on()`. Якщо ви цього не зробите, файл результатів залишиться незавершеним. Щоб переконатися, що `rk.graph.off()` буде насправді викликано, вам слід загорнути усі команди &R; між двома викликами у інструкцію `try()`. Ніколи про таке не чули? Не переймайтеся, це просто. Усе, що вам слід зробити, — це дотримуватися взірця у прикладі, який наведено нижче.

#### Додавання функціональної можливості попереднього перегляду

У цьому розділі обговорюється додавання функціональної можливості попереднього перегляду до додатків, які створюють креслення. У підручнику є окремі розділи щодо попереднього перегляду виведеного тексту (HTML), попереднього перегляду (імпортованих) даних та нетипових попередніх переглядів. Втім, рекомендуємо вам спершу прочитати цей розділ, оскільки підхід у цілому є схожим в усіх цих випадках.

Дуже корисною можливістю усіх додатків для створення креслень і графіків є надання попереднього перегляду із автоматичним оновленням. Для створення такого попереднього перегляду потрібні дві речі: додати пункт з позначкою `<preview>` до вашого визначення графічного інтерфейсу і скоригувати створений код для отримання зображення попереднього перегляду.

Додавання пункту `<preview>` доволі просте. Достатньо просто розмістити відповідні теґи у описі графічного інтерфейсу. Система сама подбає про створення пристрою для попереднього перегляду, оновлення попереднього перегляду у відповідь на зміни параметрів тощо. Приклад:

Починаючи з версії 0.6.5 &rkward; елементи попереднього перегляду, `<preview>`, виокремлюються у діалогових вікнах додатків (не майстрів): вони розташовуються у стовпчику з кнопками, незалежно від того, де їх було визначено у описі графічного інтерфейсу. Втім, варто визначати їх у відповідному місці компонування з міркувань зворотної сумісності.

    <document>
                    [...]
                    <dialog [...]>
                            [...]
                            <preview id="preview"/>
                            [...]
                    </dialog>
                    [...]
            </document>

І це усе, що потрібно для визначення графічного інтерфейсу.

Коригування шаблона JS потребує більших зусиль. Вам доведеться створити функцію із назвою `preview()`, окрім функцій `preprocess()`, `calculate()` тощо. Ця функція має створювати код, потрібний для креслення, і лише його Зокрема, не містити виведення заголовків та викликів `rk.graphics.on()` і подібних функцій. Див. наведений нижче приклад із типовим взірцем того, який код вам потрібен.

#### Загальні параметри креслення

Як можна помітити, більшість додатків для креслення у &rkward; надають можливість змінювати широкий діапазон загальних параметрів креслення, наприклад, визначення підписів до осей та полів рисунка. Додати ці параметри до вашого додатка просто. Вони надаються придатним до вбудовування додатком із назвою `rkward::plot_options`. Вбудовування до інтерфейсу вашого додатка відбувається так:

    <document>
                    [...]
                    <logic [...]>
                            <connect client="plotoptions.xvar" governor="x.available"/>
                            <set id="plotoptions.allow_type" to="true"/>
                            <set id="plotoptions.allow_ylim" to="true"/>
                            <set id="plotoptions.allow_xlim" to="false"/>
                            <set id="plotoptions.allow_log" to="false"/>
                            <set id="plotoptions.allow_grid" to="true"/>
                    </logic>
                    <dialog [...]>
                            [...]
                            <embed id="plotoptions" component="rkward::plot_options" as_button="true" label="Plot Options"/>
                            [...]
                    </dialog>
                    [...]
            </document>

Це додасть до вашого графічного інтерфейсу кнопку для виклику вікна із параметрами креслення. Розділ логіки наведено лише для прикладу. За його допомогою ви можете керувати додатком параметрів креслення. Докладніше про це на сторінці довідки до додатка plot_options (посилання на неї є на сторінці довідки будь-якого додатка, який надає доступ до загальних параметрів).

Далі, вам слід забезпечити додавання коду, що відповідає вашим параметрам креслення, до коду, який створюється додатком для креслення. Для цього отримуємо властивості `code.preprocess`, `code.printout` і `code.calculate` з вбудованого додатка параметрів креслення і вставляємо їх до нашого коду так, яке це показано у наведеному нижче прикладі.

#### Канонічний приклад

Ось приклад файла .JS, яким ви можете скористатися як шаблоном, коли ви захочете створити додаток для креслення:

    function preprocess () {
        // «somepackage» потрібен для створення креслення
        echo ("require (somepackage)\n");
      }

      function preview () {
        // ми викликаємо усі етапи загального коду. Лише функцію  printout () для попереднього перегляду креслення слід викликати трохи інакше
        preprocess ();
        // calculate (); // у нашому прикладі у додатка немає функції calculate ().
        printout (true); // у цьому випадку «true» означає «Створити креслення, але без заголовків та виведення даних.
      }

      function printout (is_preview) {
        // Якщо «is_preview» має значення false, буде створено код повністю, разом із заголовками.
        // Якщо «is_preview» має значення true, буде створено лише основні елементи.

        if (!is_preview) {
          echo ('rk.header (' + i18n ("An example plot") + ')\n\n');
          echo ('rk.graph.on ()\n');
        }
        // Для is_preview==true буде створено лише наведений нижче розділ

        // пам’ятайте: усе між rk.graph.on() і rk.graph.off() слід загортати у інструкцію try():
        echo ('try ({\n');
        // вставте будь-який код зі встановлення параметрів, який має бути запущено до безпосередніх команд створення креслення.
        // Сам код буде створено вбудованим додатком параметрів креслення. printIndentedUnlessEmpty() забезпечить належне форматування.
        printIndentedUnlessEmpty ('\t', getString ("plotoptions.code.preprocess"), '', '\n');

        // створити саме креслення. plotoptions.code.printout забезпечує роботу частини загальних параметрів креслення,
        // які має бути додано до самого виклику функції креслення.
        echo ('plot (5, 5' + getString ("plotoptions.code.printout") + ')\n');

        // вставте тут будь-який код встановлення параметрів, який має бути виконано після креслення.
        printIndentedUnlessEmpty ('\t', getString ("plotoptions.code.calculate"), '\n');
        echo ('})'\n);  // завершуємо інструкцію try()

        if (!is_preview) {
          echo ('rk.graph.off ()\n');
        }
      }

### Панелі перегляду для даних, виведеного та інших результатів

#### Попередній перегляд результатів (HTML)

У цьому розділі ви знайдете обговорення додавання функціональної можливості попереднього перегляду до додатків для створення тексту або HTML для друку. Рекомендуємо вам перед прочитанням цього розділу, ознайомитися із розділом щодо попереднього перегляду креслень.

Створення попереднього перегляду виведення у форматі HTML дуже подібне до створення попереднього перегляду креслення. У цьому випадку просто переконайтеся, що `preview()` створює відповідні команди `rk.print()/rk.results()`. Втім, загалом, варто пропустити інструкції заголовка у попередньому перегляді. Ось спрощений приклад:

    <!-- У файлі XML додатка -->>
            <dialog label="Import CSV data" >
                    <browser id="file" type="file" label="File name"/>
                    <!-- [...] -->>
                    <preview id="preview" mode="output"/>
            </dialog>
    >

Зауважте специфікацію `mode="output"` у елементі `<preview>`.

    // У файлі JS додатка
            function preview () {
                    // створює код, використаний для попереднього перегляду
                    printout (true);
            }

            function printout (is_preview) {
                    // створює заголовок, лише якщо is_preview==false
                    if (!is_preview) {
                            new Header ("Це надпис").print ();
                    }
                    echo ('rk.print (result)');
            }

#### Попередній перегляд (імпортованих) даних

У цьому розділі ви знайдете обговорення додавання функціональної можливості попереднього перегляду до додатків для створення (імпортування) даних. Рекомендуємо вам перед прочитанням цього розділу, ознайомитися із розділом щодо попереднього перегляду креслень.

Створення попереднього перегляду імпортованих даних (будь-яких даних, які може обробляти `rk.edit()`) дуже подібне до створення попереднього перегляду креслення. У наведеному нижче спрощеному прикладі створюється попередній перегляд даних:

    <!-- У файлі XML додатка -->>
            <dialog label="Import CSV data" >
                    <browser id="file" type="file" label="File name"/>
                    <!-- [...] -->>
                    <preview id="preview" active="true" mode="data"/>
            </dialog>
    >

Зауважте, що цього разу елемент `<preview>` визначає `mode="data"`. `active="true"` просто робить попередній перегляд типово активним.

    // У файлі JS додатка
            function preview () {
                    // створює код, що використовується для попереднього перегляду
                    calculate (true);
            }

            function calculate (is_preview) {
                    echo ('imported <- read.csv (file="' + getString ("file") /* [+ options] */);
                    if (is_preview) {
                            echo ('preview_data <- imported\n');
                    } else {
                            echo ('.GlobalEnv$' + getString ("name") + ' >- imported\n');
                    }
            }

            function printout () {
                    // [...]
            }

Знову ж, функція `preview()` створює майже той самий код, що і функція `calculate()`, отже ми створимо допоміжну функцію `doCalcuate()`, яка міститиме спільні частини цих функцій. Найважливішим є те, що вам слід пов’язати імпортовані дані з об’єктом із назвою `preview_data` (у межах поточного середовища, local). Решту дій буде виконано автоматично (грубо кажучи, &rkward; викличе `rk.edit(preview_data)`, що містить виклик `.rk.with.window.hints()`).

Хоча панелі попереднього перегляду є чудовою можливістю програми, вони споживають системні ресурси. У випадку попереднього перегляду даних можливі ситуації, коли попередній перегляд призводитиме до серйозних проблем із швидкодією. Таке трапляється, якщо імпортують величезні набори даних (які надто великі, щоб їх можна було відкрити для редагування у вікні &rkward;), хоча і «звичайні» набори даних може бути імпортовано з помилками, коли створюється величезна кількість рядків або стовпчиків. Наполегливо рекомендуємо вам обмежити `preview_data` до розмірності, за якої попередній перегляд буде корисним без небезпеки створення значних проблем із швидкодією (наприклад, матриці з 50 рядками і 50 стовпчиками має бути більш ніж достатньо у більшості випадків).

#### Нетипові панелі попереднього перегляду

Елементом `<preview>` можна скористатися для створення панелей попереднього перегляду для будь-яких типів вікон «документів», які можна долучити до робочого простору &rkward;. Окрім креслень та вікон даних, можна створювати попередні перегляди файлів HTML, скриптів &R; та вікна резюме об’єктів. Для останніх вам слід скористатися елементом `<preview mode="custom">`.

Якщо ви прочитали розділи із описом створення попереднього перегляду креслень та даних, вам вже знайомі загальні кроки цієї процедури, але для створення «нетипових» попередніх переглядів доведеться виконати трохи більше ручної роботи. Найважливішою функцією у цьому випадку буде функція &R; `rk.assign.preview.data()`. У наведеному нижче короткому фрагменті коду показано, як має виглядати створений вами код &R; для додатка створення текстового файла:

    ## Буде створено у розділі коду preview() додатка
            pdata <- rk.get.preview.data("SOMEID")
            if (is.null (pdata)) {
                    outfile <- rk.get.tempfile.name(prefix="preview", extension=".txt")
                    pdata <- list(filename=outfile, on.delete=function (id) {
                            unlink(rk.get.preview.data(id)$filename)
                    })
                    rk.assign.preview.data("SOMEID", pdata)
            }
            try ({
                    cat ("This is a test", pdata$filename)
                    rk.edit.files(file=pdata$filename)
            })

Тут ми маємо отримати значення `SOMEID` з властивості `id` елемента `<preview>`. Тобто, використовуємо `getString ("preview.id")` у файлі .js додатка.

### Додатки, які залежать від контексту

Досі ми припускали, що усі додатки є самодостатніми і усі додатки створюють власний пункт у меню. Втім, деякі додатки працюють лише (або і) у певному контексті. Наприклад, додаток для експортування вмісту графічного пристрою X11 &R;, очевидно, корисний, коли його пункт розташовано у меню пристрою X11, а не у основному меню вікна програми. Крім того, такому додатку доведеться передавати номер пристрою, з яким йому доведеться працювати, без додаткового отримання від користувача даних щодо цього.

Такі додатки ми будемо називати контекстно-залежними. Відповідно, у файлі &pluginmap; їх не буде розташовано у основному елементі `<hierarchy>` (або буде розташовано не лише там). Вони розташовуватимуться у елементі `<context>`. У поточній версії передбачено лише два різних контексти (додаткові контексти буде додано у майбутніх версіях): x11 та імпортування файлів. Послідовно розгляньмо кожен з контекстів. Навіть якщо вам цікавий лише контекст імпортування, будь ласка, прочитайте й розділ щодо контексту x11, оскільки він є трохи докладнішим.

#### Контекст пристрою X11

Щоб використати додаток у контексті пристрою x11, тобто додати його пункт у меню вікна, яке ви отримуєте після виклику `x11()` у консолі, спочатку оголосимо його у звичайний спосіб у файлі &pluginmap;:

    <document [...]>
            <components>
                    [...]
                    <component id="my_x11_plugin" file="my_x11_plugin.xml" label="An X11 context plugin"/>
                    [...]
            </components>

Втім, вам не потрібно визначати його у ієрархії (ви можете, якщо він працюватиме і як додаток верхнього рівня):

    <hierarchy>
                    [...]
            </hierarchy>

Замість цього, додайте визначення контексту «x11» і додайте пункт у меню так:

    <context id="x11">
                    [...]
                    <menu id="edit">
                            [...]
                            <entry id="my_x11_plugin"/>
                    </menu>
            </context>
    </document>

У розділі логіки файла xml додатка ви можете тепер оголосити дві властивості `<external>`: `devnum` і `context`. Для властивості `context` (якщо її оголошено) буде встановлено значення `"x11"`, якщо додаток викликано у відповідному контексті. Для властивості `devnum` буде встановлено значення номера графічного пристрою, з якими слід працювати. Ось і все.

#### Контекст імпортування даних

Перш ніж читати цей розділ, будь ласка, прочитайте розділ щодо контексту пристрою X11, оскільки там наведено пояснення базових понять.

Контекст `"import"` використовується для оголошення додатків фільтрування файлів. Ви просто додаєте оголошення з контекстом та `id=``"import"` до файла &pluginmap;. Втім, у оголошеннях таких додатків є одна особливість: для забезпечення однорідності вигляду діалогового вікна вибору файлів для усіх підтримуваних типів файлів, вам слід оголосити ось що для вашого компонента:

    <document [...]>
            <components>
                    [...]
                    <component id="my_xyz_import_plugin" file="my_xyz_import_plugin.xml" label="Import XYZ files">
                            <attribute id="format" value="*.xyz *.zyx" label="XYZ data files"/>
                    </component>
                    [...]
            </components>
            <hierarchy>
                    [...]
            </hierarchy>
            <context id="import">
                    [...]
                    <menu id="import">
                            [...]
                            <entry id="my_xyz_import_plugin"/>
                    </menu>
            </context>
            [...]
    </document>

Рядок атрибута просто повідомляє, що пов’язаними суфіксами назв для файлів XYZ є `*.xyz` або `*.zyx`, і що фільтр слід називати у діалоговому вікні вибору файлів XYZ data files.

У вашому додатку ви можете оголосити дві властивості `<external>`. `filename` буде встановлено у значення файла з вказаною назвою, а `context` буде встановлено у значення `"import"`.

### Надсилання запитів щодо даних до &R;

Інколи може виникнути потреба у отриманні певних даних від &R; з метою показу їх у графічному інтерфейсі вашого додатка. Наприклад, ви можете запропонувати набір рівнів фактора, який користувач вибрав для аналізу. Починаючи з версії 0.6.2 &rkward;, це можна робити. Перш ніж ми розпочнемо пояснювати, як саме це робити, важливо ознайомитися з певними підводними каменями цього підходу:

Код &R;, який запускається у частині графічного інтерфейсу додатка, оброблятиметься у циклі обробки подій &R;, тобто його можна виконувати під час виконання інших обчислень. Так зроблено, щоб графічним інтерфейсом вашого додатка можна було користуватися, навіть коли &R; виконує якісь інші дії. Втім, це робить важливою відсутність у вашому коді сторонніх ефектів. Зокрема, має бути забезпечено такі вимоги щодо коду:

- Не виконувати надання змінним значень у .GlobalEnv або будь-якому іншому нелокальному середовищі.

- Не виводити нічого до файла виведення результатів.

- Не малювати нічого на екрані.

- Загалом, не віддавайте ніяких команд, які можуть мати побіжні наслідки. Ваш код може читати дані, але не повинен хоч щось робити.

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

    <script><![CDATA[
                                    last_command_id = -1;
                                    gui.addChangeCommand ("variable", "update ()");
                                    update = function () {
                                            gui.setValue ("selector.enabled", 0);
                                            variable = gui.getValue ("variable");
                                            if (variable == "") return;

                                            last_command_id = doRCommand ('levels (' + variable + ')', "commandFinished");
                                    }

                                    commandFinished = function (result, id) {
                                            if (id != last_command_id) return;  // зараз з’явиться новий результат
                                            if (typeof (result) == "undefined") {
                                                    gui.setListValue ("selector.available", Array ("ERROR"));
                                                    return;
                                            }
                                            gui.setValue ("selector.enabled", 1);
                                            gui.setListValue ("selector.available", result);
                                    }
                    ]]></script>

Тут `variable` — це властивість, що містить назву об’єкта (наприклад, у `<varslot>`). Кожного разу, коли назва змінюється, виникає потреба у оновленні показу рівнів у `<valueselector>` із назвою `selector`. Ключовою функцією є `doRCommand()`, функція, яка приймає як перший параметр рядок команди, яку слід виконати, і як другий параметр — назву функції, яку слід викликати, коли виконання команди буде завершено. Зауважте, що команда виконуватиметься у асинхронному режимі, і це дещо ускладнює речі. По-перше, вам слід зробити так, щоб ваш `<valueselector>` залишався вимкненим, доки у ньому не міститиметься актуальної інформації. По-друге, потенційно, до черги обробки може потрапити декілька команд, доки ви отримаєте перші результати. Ось чому кожній команді надано «id», і ми зберігаємо його у `last_command_id` для подальшого використання.

Під час виконання команди програма виконує вказаний виклик (у нашому випадку `commandFinished`) з двома параметрами: самим результатом та ідентифікатором відповідної команди. Результат належатиме до типу, який є відповідним представленню у &R;, тобто до числових масивів, якщо результат є числовим тощо. Результатом може бути навіть `list()` &R;, але у цьому випадку його буде представлено як `Array()` JS без назв.

Зауважте, що навіть це приклад є дещо спрощеним. Насправді, вам доведеться вжити певних застережних заходів, наприклад, уникати надмірної кількості вкладених рівнів у засобі вибору. Втім, ймовірно, вам не потрібно буде дбати про усе самому. Наведений вище приклад взято з додатка `rkward::level_select`, який ви можете просто вбудувати до вашого власного додатка. Це навіть надасть вам змогу вказати інший вираз для виконання замість `levels()`.

### Посилання на поточний об’єкт або поточний файл

Для багатьох додатків бажаною є обробка поточного об’єкта. Наприклад, додаток sort міг би попередньо вибрати для упорядковування об’єкт data.frame, який ви зараз редагуєте. Назву поточного об’єкта додатки можуть отримати за допомогою попередньо визначеної властивості із назвою `current_object`. Ви можете з’єднати цю властивість з додатком у звичайний спосіб. Якщо поточного об’єкта немає, властивість матиме значення порожнього рядка. Так само, доступ до адреси поточного файла скрипту можна отримати з попередньо визначеної властивості із назвою `current_filename`. Якщо у програмі не редагується жодного скрипту або скрипт ще не було збережено до файла, властивість буде порожньою.

У поточній версії `current_object` може належати лише до класу `data.frame`, але, будь ласка, не покладайтеся на це, оскільки у майбутніх версіях його належність може бути розширена на інші типи. Якщо вам потрібні лише об’єкти `data.frame`, краще з’єднайте додаток з властивістю `current_dataframe`. Крім того, ви можете примусово встановити тип, використовуючи відповідні обмеження на ваші `<varslot>` або скориставшись скриптовим керуванням логікою графічного інтерфейсу.

### Повторення (набору) параметрів

Іноді виникає потреба у повторенні набору параметрів для довільної кількості пунктів. Наприклад, припустімо, що вам хочеться створити додаток для упорядковування data.frame. Нехай потрібно упорядкувати набір даних за довільною кількістю стовпчиків (у випадку зв’язків у перших стовпчиках). Реалізувати це доволі просто: надаємо користувачу можливість вибрати декілька змінних у `<varslot>` за допомогою `multi="true"`. Але якщо виникне потреба розширення, наприклад, дозволити користувачеві вказати для кожної зі змінних, чи слід перетворювати її на символьне або числове значення, або визначити порядок записів (за зростанням чи спаданням), вам знадобиться гнучкіший спосіб. Іншими прикладами може бути малювання декількох графіків на одному кресленні (з можливістю вибору об’єкта, стилю лінії, кольору лінії тощо для кожного з графіків) або визначення відображення для перекодування з набору старих значень на набір нових значень.

Увійдімо до `<optionset>`. Розгляньмо простий приклад, спочатку:

    <dialog [...]>
            [...]
            <optionset id="set" min_rows="1">
                    <content>
                            <row>
                                    <input id="firstname" label="Ім’я" size="small">
                                    <input id="lastname" label="Прізвище" size="small">
                                    <radio id="gender" label="Стать">
                                            <optioncolumn label="Чоловіча" value="m"/>
                                            <optioncolumn label="Жіноча" value="f"/>
                                    </radio>
                            </row>
                    </content>

                    <optioncolumn id="firstnames" label="Ім’я" connect="firstname.text">
                    <optioncolumn id="lastnames" label="Прізвище" connect="lastname.text">
                    <optioncolumn id="gender" connect="gender.string">
            </optionset>
            [...]
    </dialog>

Тут нами створено інтерфейс для визначення кількості осіб (наприклад авторів). Для заповнення нам потрібен принаймні один запис (`min_rows="1"`). У елементі `<optionset>` ми починаємо з визначення вмісту, `<content>`, тобто елементів, які належать набору параметрів. Ви вже знайомі із більшістю елементів у `<content>`.

Далі, ми вкажемо потрібні нам змінні, які слід прочитати з набору пунктів до нашого файла JS. Оскільки ми матимемо справу з довільною кількістю записів, ми не можемо просто прочитати `getString ("firstname")` у коді JS. Замість цього, для кожного потрібного нам значення ми вказуємо `<optioncolumn>`. Наприклад, для першого optioncolumn `<connect="firstname.text">` означає, що вміст елемента `<input>` «firstname» буде прочитано для усіх записів. Значення `<optioncolumn>`, для яких задано `label`, буде показано на екрані у стовпчику з відповідною міткою. У коді JS ми тепер можемо отримати імена усіх авторів за допомогою `getList("set.firstname")`, прізвища — за допомогою `getList("set.lastnames")`, а стать — за допомогою `getList("set.gender")`.

Зауважте, що не існує обмежень щодо того, що ви можете розмістити у `<optionset>`. Ви навіть можете скористатися вбудованими компонентами. Так само, як із будь-яким іншим елементом, усе, що вам треба зробити, — це зібрати усі бажані змінні для виведення у специфікації `<optioncolumn>`. У випадку вбудованих додатків це часто розділ властивості «code». Приклад:

    <dialog [...]>
            [...]
            <optionset id="set" min_rows="1">
                    <content>
                            [...]
                            <embed id="color" component="rkward::color_chooser" label="Колір"/>
                    </content>

                    [...]
                    <optioncolumn id="color_params" connect="color.code.printout">
            </optionset>
            [...]
    </dialog>

Звичайно ж, ми також можемо скористатися логікою графічного інтерфейсу у optionset. Для цього передбачено два варіанта: ви можете зробити це створивши з’єднання (або скрипт) у основному розділі `<logic>` вашого додатка, як завжди. Втім, доступ до елементів графічного інтерфейсу у області вмісту доведеться здійснювати за допомогою (наприклад) «set.contents.firstname.XYZ». Зауважте префікс «set» (`id`, який ви призначили set і «contents»). Крім того, ви можете додати окремий розділ `<logic>` як дочірній елемент вашого `<optionset>`. У цьому випадку `id` буде адресовано відносно області вмісту, наприклад «firstname.XYZ». Втім, у розділі logic optionset не можна використовувати елемент `<script>`. Якщо вам потрібні скриптові команди, вам доведеться скористатися основним розділом `<logic>` додатка.

Якщо логіку скрипту розташовано у optionset, усе, що ви можете зробити, це отримати доступ до поточної області вмісту. Таким чином, типово, має сенс лише з’єднування елементів у області вмісту один з одним. З’єднування властивості поза `<optionset>` із властивістю у області вмісту може бути корисним для ініціалізації. Втім, внесення змін до області вмісту після ініціалізації не буде застосовано до пунктів, які користувач вже визначив. Вони стосуватимуться лише поточного позначеного пункту у наборі.

#### «Керовані» optionset-и

Досі ми розглядали `<optionset>`, у якому передбачено кнопки для додавання або вилучення пунктів. Втім, іноді набагато природнішим є вибрати пункти поза `<optionset>` і надати лише параметри налаштовування кожного з пунктів у `<optionset>`. Наприклад, припустімо, що вам потрібно надати користувачеві змогу вибрати декілька об’єктів для креслення. Для кожного з об’єктів, користувач повинен мати змогу вказати колір лінії. Реалізувати це можна, розташувавши `<varselector>` і `<varslot>` всередині області `<content>`, дозволивши користувачеві вибирати одночасно лише один пункт. Втім, користувачеві доведеться клацати кнопкою миші набагато менше, якщо ви замість цього скористаєтеся `<varslot multi="true">` ззовні щодо `<optionset>`. Далі, ви з’єднаєте засіб вибору об’єктів із так званим «керованим» набором пунктів. Ось реалізація:

    <dialog [...]>
            <logic>
                    <connect client="set.vars" governor="vars.available"/>
                    <connect client="set.varnames" governor="vars.available.shortname"/>
            </logic>
            [...]
            <varselector id="varsel"/>
            <varslot id="vars" label="Objects to plot"/>
            <optionset id="set" keycolumn="var">
                    <content>
                            [...]
                            <embed id="color" component="rkward::color_chooser" label="Line color"/>
                    </content>

                    [...]
                    <optioncolumn id="vars" external="true">
                    <optioncolumn id="varnames" external="true" label="Variable">
                    <optioncolumn id="color_params" connect="color.code.printout">
            </optionset>
            [...]
    </dialog>

Почнемо розгляд нашого прикладу з нижньої частини. Там можна бачити два визначення `<optioncolumn>` із `external="true"`. Це повідомляє &rkward;, що відповідні елементи керуються з-поза меж `<optionset>`. Тут єдиним призначенням optioncolumn «varnames» є надання простих для читання міток у області показу optionset (її з’єднано з модифікатором «shortname» властивості, що містить позначені об’єкти). Метою optioncolumn «vars» є виконання обов’язків «ключового» стовпчика, як це вказано за допомогою `<optionset keycolumn="vars"...>`. Це означає, що для кожного запису у цьому списку набір пропонуватиме один набір пунктів, а пункти логічно пов’язані з цими записами. Цей стовпчик з’єднано із властивістю, що містить позначені у `<varslot>` об’єкти. Отже, для кожного об’єкта, який позначено, `<optionset>` надаватиме змогу вказати колір лінії.

Зовнішній стовпчик також можна з’єднати за допомогою `connect` із властивостями у області `<content>`. Втім, варто зауважити, що optioncolumn, оголошені як `external="true"`, ніколи не слід змінювати з середини `<optionset>`, а optioncolumn, оголошені як `external="false"` (типово), ніколи не слід змінювати ззовні від `<optionset>`.

#### Альтернативи: коли не слід використовувати optionset

Optionset-и — потужний інструмент, але іноді вони здатні наробити більше шкоди, ніж принести користі, оскільки вони значно ускладнюють структуру додатка як з точки зору розробника додатка, так і з точки зору користувача. Тому двічі подумайте, перш ніж користуватися ними. Ось декілька порад:

- У простих випадках корисною альтернативою, яка не є такою складно, є елемент `<matrix>`.

- Не переобтяжуйте ваш додаток зайвими можливостями. У нашому прикладі optionset використовується для створення додатка, який малює на одному кресленні декілька ліній. Але, загалом, не варто створювати додатки, які робитимуть окремі креслення для кожного елемента з optionset. Краще створити додаток, який робитиме одне креслення, щоб користувач міг викликати його декілька разів з різними параметрами.

- Якщо у наборі має бути не більше двох-трьох записів, варто просто повторити пункти вручну.

## Проблеми залежностей і сумісності

### Сумісність із версіями &rkward;

Ми намагаємося робити так, щоб додатки, які було створено для старих версій &rkward;, могли працювати і у новіших версіях &rkward;. Втім, зі зворотною сумісністю все не так добре, адже у програмі весь час з’являються нові можливості. Оскільки не усі користувачі працюють із найсвіжішою версією &rkward;, ваш додаток може виявитися непрацездатним у деяких системах.

Якщо вам відомі такі проблеми сумісності, вам слід документувати їх у вашому файлі &pluginmap; за допомогою елемента `<dependencies>`. Елемент `<dependencies>` можна вказати або як безпосередній дочірній елемент елемента &pluginmap; <document>, або як дочірній елемент окремих визначень `<component>`. У першому випадку залежності буде застосовано до усіх додатків з карти. У другому випадку — лише до окремого `<component>`. Ви також можете визначити суміш верхніх «загальних» і «специфічних» залежностей. У цьому випадку загальні залежності буде додано до залежностей індивідуальних компонентів.

Розгляньмо невеличкий приклад:

    <document ...>
            <dependencies rkward_min_version="0.5.0c" />
            <components ...>
                    <component id="myplugin" file="reduced_version_of_myplugin.xml" ...>
                            <dependencies rkward_max_version="0.6.0z" />
                    </component>
                    <component id="myplugin" file="fancy_version_of_myplugin.xml" ...>
                            <dependencies rkward_min_version="0.6.1" />
                    </component>
                    ...
    x        </components ...>
    </document>

У цьому прикладі від усіх додатків вимагається, щоб було встановлено принаймні версію 0.5.0c &rkward;. Один з додатків, з `id="myplugin"`, постачається у двох альтернативних варіантах. Перший, спрощений, може бути використано для версій &rkward;, які передували версії 0.6.1. Інший же використовує можливості, які з’явилися у &rkward;, починаючи з версії 0.6.1, отже ним можна буде скористатися лише у &rkward; 0.6.1 та наступних версіях.

Надання таких альтернативних варіантів, як у наведеному прикладі, є дружнім до користувача способом скористатися новими можливостями, зберігши можливість користування у попередніх версіях &rkward;. У альтернативних версій має бути однакове значення `id` (якщо вказати різні, програма показуватиме попередження). Крім того, їх можна визначити лише у межах одного файла &pluginmap;.

Додаток, який є несумісним із запущеною версією &rkward; і який не має альтернативних версій, буде проігноровано із виведенням відповідного попередження.

Насправді, &rkward; 0.6.1 був першою версією, у якій можна було слідкувати за залежностями і повідомляти про проблеми із залежностями взагалі. Отже, на відміну від того, про що можна було б припустити з нашого прикладу, визначення будь-яких версій до 0.6.1 у описі залежностей не матиме ніякого безпосереднього впливу на працездатність додатка (втім, може бути корисним з міркувань документування).

Іноді навіть можна обробляти проблеми з несумісністю версій всередині єдиного файла &pluginmap; за допомогою елемента `<dependency_check>`, описаного у наступному розділі.

### Сумісність із версіями &R;

Подібно до `rkward_min_version` і `rkward_max_version`, елемент `<dependencies>` надає змогу визначити атрибути `R_min_version` і `R_max_version`. Втім, є такі відмінності:

- Додатки, які не задовольнятимуть вимогам щодо версії &R; у поточній версії не пропускатимуться під час читання файла &pluginmap;. Користувач все одно зможе викликати відповідний додаток, і не побачить негайного попередження (у майбутніх версіях таке попередження, ймовірно, буде показано).

- Як наслідок, не можна визначати альтернативні версії додатка, робота яких залежатиме від версії &R;.

- Втім, часто доволі просто досягнути зворотної сумісності у спосіб, показаний нижче. Якщо ви припускаєте проблеми із сумісністю з &R;, будь ласка, спробуйте цей спосіб замість визначення залежності від певної версії &R;.

У багатьох випадках доволі просто надати у розпорядження користувача обмежені функціональні можливості, якщо певна можливість є недоступною у запущеній версії &R;. Розгляньмо такий короткий приклад файла `.xml` додатка:

    <dialog [...]>
            <logic>
                    <dependency_check id="ris210" R_min_version="2.10.0"/>
                    <connect client="compression.xz.enabled" governor="ris210"/>
            </logic>
            [...]
            <radio id="compression" label="Compression method">
                    <option label="None" value="">
                    <option label="gzip" value="gzip">
                    <option id="xz" label="xz" value="xz">
            </radio>
            [...]
    </dialog>

У цьому випадку параметр стискання «xz» буде просто вимкнено, якщо запущена версія &R; виявиться старішою за 2.10.0 (версію, у якій не передбачено підтримки стискання xz). У елементі `<dependency_check>` передбачено підтримку тих сами атрибутів, що і у елементі `<dependencies>` у файлах &pluginmap;. Він створює булеву властивість, яка має значення true (так), якщо вказану залежність задоволено, і значення false, якщо це не так.

### Залежність від пакунків &R;

Можна визначати залежності від певних пакунків &R;, але, на час версії &rkward; 0.6.1, ці залежності не перевіряються, не встановлюються або завантажуються автоматично. Втім, їх буде показано у файлах довідки до додатка. Ось приклад визначення:

    <dependencies>
                    <package
                            name="heisenberg"
                            min_version="0.11-2"
                            repository="http://rforge.r-project.org"
                    />
            </dependencies>

Не забувайте завжди додавати відповідні виклики `require()`, якщо для роботи вашого додатка потрібно завантажити певні пакунки.

Якщо ви поширюєте вашу &pluginmap; як пакунок &R;, і усі додатки залежать від певного пакунка, вам слід визначити цю залежність на рівні пакунка &R;. Визначення залежностей від пакунків &R; на рівні &pluginmap; &rkward; є найкориснішим, якщо залежності потребує лише частина ваших додатків, залежності немає у CRAN або ваша &pluginmap; не поширюється як пакунок &R;.

### Залежності від інших &pluginmap; &rkward;

Якщо ваші додатки залежать від додатків, які визначено у іншому &pluginmap; (тобто від чогось, що не є частиною вашого пакунка), ви можете визначити цю залежність ось так:

    <dependencies>
                    <pluginmap
                            name="heisenberg_plugins"
                            url="http://eternalwondermaths.example.org/hsb"
                    />
            </dependencies>

У поточній версії не завантажуватиме, не встановлюватиме і навіть не попереджатиме щодо &pluginmap;, яких не вистачає, але дані щодо залежностей (та того, як їх отримати) буде показано на сторінці довідки додатка. Ви не повинні (і цього не слід робити) оголошувати залежності від &pluginmap;-ів, які постачаються разом із офіційним дистрибутивом &rkward;, або від &pluginmap;-ів, які є частиною вашого пакунка. Більше того, якщо потрібний вам &pluginmap; поширюється як пакунок &R;, оголошуйте залежність від пакунка (як показано у попередньому розділі), а не від &pluginmap;-а.

Щоб переконатися, що потрібні &pluginmap;-и буде насправді завантажено, скористайтеся теґом `<require>` (зверніться до довідника, щоб ознайомитися із докладнішим описом).

### Приклад

Щоб прояснити питання поєднання визначень залежностей, наведемо приклад із поєднанням:

    <document ...>
            <dependencies rkward_min_version="0.5.0c">
                    <package
                            name="heisenberg"
                            min_version="0.11-2"
                            repository="http://rforge.r-project.org"
                    />
                    <package
                            name="DreamsOfPi"
                            min_version="0.2"
                    />
                    <pluginmap
                            name="heisenberg_plugins"
                            url="http://eternalwondermaths.example.org/hsb"
                    />
            <dependencies>

            <require map="heisenberg::heisenberg_plugins"/>

            <components ...>
                    <component id="myplugin" file="reduced_version_of_myplugin.xml" ...>
                            <dependencies rkward_max_version="0.6.0z" />
                    </component>
                    <component id="myplugin" file="fancy_version_of_myplugin.xml" ...>
                            <dependencies rkward_min_version="0.6.1" />
                    </component>
                    ...
    x        </components ...>
    </document>

## Переклади додатків

Досі ми використовували декілька концепцій щодо перекладів або «i18n» (скорочення від «internationalization», де між «i» і «n» вставлено кількість літер, 18). У цьому розділі ми докладніше розглянемо функціональні можливості i18n для додатків &rkward;. Здебільшого, у вас не виникатиме потреби у застосуванні усього цього у ваших додатках. Втім, варто усе ж прочитати цей розділ повністю, оскільки розуміння цих концепцій має допомогти вам у створенні повністю придатних до перекладу додатків та забезпечить вищу якість перекладів.

### Загальні міркування

Однією з важливих речей, які слід розуміти, коли ми говоримо про переклад програмного забезпечення, на відміну від перекладу звичайного тексту, є те, що часто перекладачів позбавлено можливості бачити загальну картину того, що вони перекладають. Для перекладу програмного забезпечення вимушено використовуються короткі фрагменти тексту: усі мітки, які записано всередині теґів `<option>` у `<radio>`, усі позначені вами для перекладу рядки у викликах функції `i18n()` є окремими «модулями перекладу». Загалом, кожен такий фрагмент перекладач бачитиме ізольовано від коду, який використано у додатку. Якщо бути зовсім точним, ця ізоляція є неповною, оскільки ми намагаємося надати перекладачеві якомога ширший змістовний контекст модуля, автоматично видобуваючи його з коду. Але подекуди перекладачам буде важливим додатковий контекст, потрібний для розуміння рядка, особливо там, де рядки є короткими.

### i18n у файлах XML &rkward;

Для файлів xml &rkward; i18n здебільшого працює без будь-яких додаткових зусиль. Якщо ви створюєте власну `.pluginmap` (наприклад, для зовнішнього додатка), вам слід вказати `po_id` поряд із `id` у pluginmap. Це визначить «каталог повідомлень», який слід використовувати. Загалом, це має бути рядок, який є ідентичним до `id` вашого `.pluginmap`, але якщо ви надаєте у додатку декілька пов'язаних `.pluginmap` у одному пакунку, вам, ймовірно, варто вказати загальний `po_id` у ваших картах. Значення `po_id` з файла `.pluginmap` успадковується усіма оголошеними у ньому додатками, якщо у них не оголошено інше значення `po_id`.

У файлах опису графічного інтерфейсу та на сторінках довідки вам не потрібно повідомляти &rkward;, які саме рядки слід перекладати, оскільки це зрозуміло з використання цих рядків. Втім, як ми вже пояснювали раніше, вам варто слідкувати за тим, щоб не виникало двозначностей, та тим, щоб усі рядки мали достатні для правильного перекладу пояснення. Для рядків із неоднозначним тлумаченням можна вказати контекст `i18n_context` ось так:

    <checkbox id="scale" label="Scale" i18n_context="Показати шкалу"/>
    <checkbox id="scale" label="Scale" i18n_context="Масштабувати креслення"/>

Надання контексту `i18n_context` забезпечить можливість перекласти два рядки по-різному. Якщо б контекст не було вказано, обидва рядки мали б абсолютно однаковий переклад. Крім того, контекст буде показано перекладачеві. Підтримку атрибута `i18n_context` передбачено для усіх елементів, які можуть містити придатні до перекладу рядки, зокрема елементів, які містять у собі текст (наприклад елементів `<text>`).

У інших випадках рядок для перекладу може мати однозначне значення, але все ж потребує роз’яснення. Для таких рядків можна додати коментар, який буде показано перекладачам. Приклад:

    <!-- i18n: Ні, це не друкарська помилка у слові «screen»! -->
    <component id="scree_plot" label="Scree plot"/>

    <!-- i18n: Якщо можна, зробіть переклад якомога коротшим. Переклад з понад 15 символів виглядатиме
    тут доволі кострубато, значення має бути майже очевидним для користувача
    (вибір зі списку значень, показаного поряд із цим елементом) -->
    <valueslot id="selected" label="Pick one"/>

Зауважте, що такі коментарі мають передувати елементу, до якого їх застосовують, і мають починатися з «i18n:» або «TRANSLATORS:».

Нарешті, у рідкісних випадках, у вас може виникнути потреба у виключенні деяких рядків з перекладу. Це має сенс, наприклад, якщо ви надаєте користувачеві вибір між певними назвами функцій &R; у елементі `<radio>`. Звичайно ж, назви функцій не можна перекладати, тоді можна зробити так (втім, залежно від контексту, можна просто додати описову мітку функції):

    <radio id="transformation" label="R function to apply">
      <option id="as.list" noi18n_label="as.list()"/>
      <option id="as.vector" noi18n_label="as.vector()"/>
      [...]
    </radio>

Зауважте, що вам слід прибрати атрибут `label` і вказати замість нього атрибут `noi18n_label`. Також зауважте, що на відміну від використання `i18n_context` і коментарів, використання `noi18n_label` зробить ваш додаток несумісним із версіями &rkward; до версії 0.6.3.

### i18n у файлах і розділах JS &rkward;

На відміну від файлів `.xml`, для уможливлення перекладу файлів `.js` доведеться серйозно попрацювати. Ключовою відмінністю у цьому випадку є те, що не існує простого способу автоматично визначити, є той чи інший рядок показаною користувачеві текстовою інформацією чи просто фрагментом програмного коду. Отже, вам доведеться позначити відповідні рядки вручну. Вище ми вже наводили приклади цього. Далі наведено повніший опис функцій для перекладу рядків у коді js та деякі підказки щодо складніших випадків:

`i18n (msgid, [...])`

- Найважливіша функція. Позначає рядок для перекладу. Рядок (перекладений чи ні) повертається взятим у подвійні лапки («"»). Можна використовувати довільну кількість замінників у рядку, як це вже показано вище. Використання замінників замість з’єднання коротких рядків значно полегшує роботу перекладача:

      i18n ("Compare objects %1 and %2", getString ('x'), getString ('y'));

`i18nc (msgctxt, msgid, [...])`

- Те саме, що і `i18n()`, але із додаванням контексту повідомлення:

      i18nc ("proper name, not state of mind", "Mood test");

`i18np (msgid_singular, msgid_plural, n, [...])`

- Те саме, що і `i18n()`, але для повідомлень, у яких різні форми для однини і множини (у деяких мовах форм множини може бути декілька). Зауважте, що як і у випадку з `i18n()`, ви можете використовувати довільну кількість замінників, але перший з них, за яким розрізнятимуться форми множини («%1»), має бути цілим числом.

      i18np ("Comparing a single pair", "Comparing %1 distinct pairs", n_pairs);

`i18ncp (msgctxt, msgid_singular, msgid_plural, n, [...])`

- `i18np()` із доданим контекстом повідомлення.

`comment (коментар, [режим відступу])`

- Виводить коментар до коду, позначений для перекладу. На відміну від інших функцій i18n(), дані не беруться у лапки, а на початку кожного рядка коментаря додається символ «#».

      comment ("Transpose the matrix");
                              echo ('x <- t (x)\n');

Щоб додати коментарі для перекладачів (див. вище обговорення відмінностей між коментарем і контекстом), додайте коментар, що починатиметься з «i18n:» або «translators:» одразу перед викликом `i18n()`, який слід прокоментувати. Приклад:

    // i18n: З правописом усе гаразд, так і має бути: Scree plot.
                    echo ('rk.header (' + i18n ("Scree plot") + ')\n');

#### Інтернаціоналізація і лапки

Здебільшого, потреби перейматися тим, як поводить себе i18n() при використанні лапок у перекладі, немає потреби. Оскільки, типово, придатні до перекладу рядки є рядковими літералами, додавання до них лапок є природною річчю, яка навіть заощаджує зусилля на введення коду. Крім того, у функціях, подібних до `makeHeaderCode()/Header()`, у яких, зазвичай, аргументи беруть у лапки, рядки з i18n() захищено від дублювання лапок. З технічної точки зору, ми надсилаємо перекладений рядок спочатку до функції `quote()` (щоб додати лапки), а потім до функції `noquote()` (щоб запобігти появі зайвих лапок). Якщо вам потрібен придатний для перекладу рядок без лапок, скористайтеся конструкцією `i18n(noquote ("Ваше повідомлення"))`. Якщо ж вам потрібен придатний до перекладу рядок із лапками, ще раз пропустіть його крізь `quote()`, двічі.

Однак, загалом кажучи, навряд чи варто робити придатними до перекладу назви функції або змінних. По-перше, &R;, мова програмування, заснована на словах англійської мови, а самі команди мови не підлягають перекладу. Коментарі у коді можна перекладати, але для них слід використовувати функцію `comment()`. По-друге, якщо ви зробите синтаксично пов’язані частини створеного коду придатним до перекладу, невдалий переклад може зашкодити працездатності додатка. Наприклад, якщо переклад рядка, який є назвою змінної, складатиметься з двох слів із пробілом між ними, отриманий код просто не працюватиме.

### Супровід перекладів

Тепер, коли ми зробили додаток придатним до перекладу, як насправді його перекласти? Загалом, про це слід дбати окремо, лише якщо ви розробляєте зовнішній додаток. Для додатків у основному сховищі коду &rkward; відповідні дії буде виконано автоматично. Нижче наведено основні прийоми обробки для зовнішніх додатків. Зауважте, що вам доведеться встановити пакунок «gettext»:

- Позначте відповідним форматуванням усі рядки, надаючи потрібний контекст і коментарі.

- Віддайте команду `python3 scripts/update_plugin_messages.py --extract-only /шлях/до/вашого.pluginmap`. Скрипт scripts/update_plugin_messages.py не є частиною пакунка з початковими кодами випуску, але його можна знайти у копії сховища з початковим кодом &rkward;.

- Надайте доступ до створеного файла `rkward__`Ідентифікатор_PO`.pot` вашим перекладачам. Для зовнішніх додатків, рекомендуємо зберігати цей файл у підкаталозі «po» у inst/rkward.

- Перекладач відкриє файл у програмі для перекладу, наприклад у `lokalize`. Насправді, навіть якщо ви не маєте наміру щось перекладати, вам варто спробувати виконати цей крок власноруч. Перегляньте рядки, які було видобуто, і спробуйте знайти серед них проблемні або неоднозначні.

- Перекладач зберігає переклад у файлі `rkward__`Ідентифікатор_PO`.`xx`.po` (де `xx` — код мови) і надсилає його розробникам.

- Скопіюйте файл `rkward__`Ідентифікатор_PO`.`xx`.po` до коду вашого додатка, розмістивши його поряд із файлом `rkward__`Ідентифікатор_PO`.pot`. Віддайте команду `python3 scripts/update_plugin_messages.py /шлях/до/вашого.pluginmap` (Зауваження: цього разу без `--extract-only`). Ця команда узгодить переклад з усіма проміжними змінами у рядках, збере його і встановить як файл ``КАТАЛОГ_PLUGINMAP`/po/`xx`/LC_MESSAGES/rkward__`Ідентифікатор_PO`.mo` (де, знову ж таки, `xx` — код мови).

- Вам також слід включити нескомпільовані переклади (тобто файли `rkward__`Ідентифікатор_PO`.`xx`.po`) до вашого дистрибутива, у підкаталозі «po».

- Якщо ви внесли зміни до вашого додатка, віддайте команду `python3 scripts/update_plugin_messages.py /шлях/до/вашого.pluginmap`, щоб оновити файл .pot і наявні файли .po, а також компільовані каталоги повідомлень.

### Створення перекладів додатків

Ми припускаємо, що ви вмієте перекладати або навчитеся цьому у якийсь інший спосіб. Втім, маємо сказати декілька слів щодо особливостей перекладу додатків &rkward;:

- У додатках до &rkward; до версії 0.6.3 не було передбачено можливості перекладу. До цієї версії розробники взагалі не передбачали переклад додатків. Тому ви, напевне, зустрінетеся із неоднозначностями у рядках перекладу та іншими проблемами, яких немає у зріліших проєктах. Будь ласка, не мовчіть про проблеми, повідомте про них розробникам (або супровідникам додатків), щоб вони могли усунути ці проблеми.

- У багатьох додатках &rkward; використовується високоспеціалізована термінологія, яка походить з галузі обробки даних та статистики, а також з інших галузей науки. У багатьох випадках створення доброго перекладу потребує від перекладача принаймні базових знань у цих галузях. Іноді, не існує доброго перекладу для технічних термінів не існує, і варто залишити термін неперекладеним або включити термін англійською у дужках. Не зосереджуйтеся на тому, щоб обов’язково позначити для перекладу 100 % рядків, намагайтеся зосередитися на тому, щоб виконати якісний переклад, навіть якщо це означає, що слід пропустити деякі рядки (або навіть пропустити деякі каталоги повідомлень цілком). Можливо, пробіли у технічних термінах зможуть заповнити інші користувачі.

## Відомості про автора, умови ліцензування та версію

Отже, нехай вами створено набір додатків, і ви готові поділитися вашою роботою. Щоб повідомити користувачам про призначення вашої роботи, умови ліцензування та поширення та про те, з ким слід зв’язатися, якщо виникає потреба у сповіщенні про вади та побажання, вам слід додати відомості щодо ваших додатків. Зробити це можна за допомогою елемента `<about>`. Ним можна скористатися у &pluginmap; або файлах `.xml` окремих додатків (у обох випадках як безпосереднім дочірнім елементом теґу document). Якщо цей елемент використано у &pluginmap;, він стосуватиметься усіх додатків. Якщо `<about>` вказано у обох місцях, дані у `<about>` .xml окремого додатка матимуть пріоритет над даними з файла &pluginmap;. Ви також можете додати елемент `<about>` у сторінки .rkh, які не з’єднано з додатками, якщо у цьому є потреба.

Нижче наведено приклад файла &pluginmap; лише з декількома поясненнями. Якщо щось є незрозумілим, будь ласка, зверніться з довідника щодо теґів.

    <document
            namespace="rkward"
            id="SquaretheCircle_rkward"
    >
            <about
                    name="Square the Circle"
                    shortinfo="Squares the circle using Heisenberg compensation."
                    version="0.1-3"
                    releasedate="2011-09-19"
                    url="http://eternalwondermaths.example.org/23/stc.html"
                    license="GPL"
                    category="Geometry"
            >
                    <author
                            given="E.A."
                            family="Dölle"
                            email="doelle@eternalwondermaths.example.org"
                            role="aut"
                     />
                    <author
                            given="A."
                            family="Assistant"
                            email="alterego@eternalwondermaths.example.org"
                            role="cre, ctb"
                     />
            </about>
            <dependencies>
                    ...
            </dependencies>
            <components>
                    ...
            </components>
            <hierarchy>
                    ...
            </hierarchy>
    </document>

Більша частина коду доволі очевидна, тому ми не будемо обговорювати усі теґи. Втім, ми розглянемо детально елементи, які потребують пояснень для кращого розуміння.

Елемент `category` у `<about>` може визначатися довільним чином, але має бути зрозумілим для програміста, оскільки його має бути використано для упорядковування додатків за групами. Усі інші атрибути у цьому початковому тезі є обов’язковими і мають бути заповнені відповідним чином.

Має бути також вказано принаймні один елемент `<author>` із коректною адресою електронної пошти і роллю aut (автор). Якщо з вашим додатком виникатимуть проблеми або хтось захоче вам подякувати, має бути надійний спосіб зв’язатися із кимось причетним до додатка. Щоб дізнатися більше про інші коректні ролі учасників розробки, зокрема ctb для програмістів або cre для супровідників пакунка, будь ласка, зверніться до документації R з функції `person()`.

Пам’ятайте, що можна використовувати `<include>` і / або `<insert>` для повторювання інформації у декількох файлах `.xml` (наприклад, інформації щодо автора, який брав участь у розробці декількох додатків). Докладніша інформація.

Вам не обов’язково писати увесь код XML вручну. Якщо ви скористаєтеся функцією `rk.plugin.skeleton()` з пакунка rkwarddev і вкажете у цій функції усі потрібні дані за допомогою параметра `about`, програма автоматично створить файл &pluginmap; із готовим розділом <about>.

## Оприлюднення результатів вашої роботи

### Зовнішні додатки

Починаючи з версії 0.5.5, у &rkward; передбачено зручний спосіб встановлення додаткових сторонніх додатків, які не належать до основного пакунка програми. Такі додатки називаються зовнішніми додатками. Вони постачаються у форматі пакунка &R;. Ними можна безпосередньо керувати за допомогою звичайних можливостей з керування пакунками &R; і/або за допомогою &rkward;.

У цьому розділі ви знайдете відомості щодо того, як слід пакувати зовнішні додатки, щоб &rkward; міг їх використовувати. Написання самого додатка є, звичайно ж, ідентичним до наведеного у попередніх розділах. Тобто, вам варто спочатку написати працездатний додаток, а вже потім повернутися до читання цього розділу, щоб дізнатися про те, як його можна поширити.

Оскільки зовнішні додатки є доволі новою можливістю, подробиці може бути змінено у наступних випусках. Ми будемо раді ознайомитися із вашими ідеями щодо покращення процесу.

У цій документації описано подробиці щодо роботи зовнішніх додатків. Окрім того, ви можете ознайомитися із можливостями пакунка rkwarddev, який було створено для автоматизації рутинних дій з написання додатків.

### Навіщо створювати зовнішні додатки?

Кількість пакунків, які розширюють функціональні можливості &R; вже є величезною, і вона продовжує зростати. З одного боку, ми будемо раді, якщо ви писатимете додатки навіть для найбільш спеціалізованих завдань, які ви хочете розв’язати. З іншого боку, пересічний користувач не повинен мати справу зі величезними ієрархіями меню, повними невідомих йому статистичних термінів. Тому ми вважаємо, що підхід до роботи з додатками у &rkward; має бути таким самим модульним, як і у &R;. Команда розробників &rkward; має власне відкрите сховище пакунків за адресою https://files.kde.org/rkward/R/, призначене для зберігання наших зовнішніх додатків.

Як правило, додатки, які полегшують виконання широковживаних дій (наприклад t-перевірки) мають стати частиною основного пакунка програми, а ті додатки, які можуть знадобитися доволі обмеженій групі дослідників, які цікавляться вузькоспеціалізованими проблемами, слід постачати як додаткові пакунки. Для вас, як для автора додатків, найкраще розпочати з написання зовнішніх додатків.

### Структура пакунка з додатком

Щоб зовнішні додатки можна було встановити належним чином, так, щоб вони працювали, їхня ієрархічна файлова структура має відповідати певним правилам.

#### Ієрархія файлів

Погляньмо на взірцеву ієрархію файлів у добре спланованому архіві додатка. Вам не обов’язково включати усі ці каталоги і/або файли, щоб додаток міг працювати (прочитайте цей підручник далі, щоб дізнатися про те, які з них є абсолютно необхідними), вважайте це прикладом «найліпшого підходу»:

    назва_додатка/
                    inst/
                            rkward/
                                    plugins/
                                            назва додатка.xml
                                            назва_додатка.js
                                            назва_додатка.rkh
                                            ...
                                    po/
                                            ll/
                                                    LC_MESSAGES/
                                                            rkward__назва_додатка_rkward.mo
                                            rkward__назва_додатка_rkward.ll.po
                                            rkward__назва_додатка_rkward.pot
                                    tests/
                                            назва_набору_тестів/
                                                    RKTestStandards.назва_якогось_тесту.rkcommands.R
                                                    RKTestStandards.назва_якогось_тесту.rkout
                                                    ...
                                            набір_тестів.R
                                    назва_додатка.pluginmap
                                    ...
            ChangeLog
            README
            AUTHORS
            LICENSE
            DESCRIPTION

У цьому прикладі усі записи назва_додатка, назва_набору_тестів та назва_якогось_тесту слід замінити відповідними назвами у вашому додатку. Крім того, записом ll позначено код мови (наприклад de, en або es).

Вам не обов’язково створювати усю цю ієрархію файлів вручну. Якщо ви скористаєтеся функцією `rk.plugin.skeleton()` з пакунка rkwarddev, програма сама автоматично створить для вас усі потрібні файли і каталоги, окрім каталогу `po`, який створюється і керується скриптом перекладу.

##### Базові компоненти додатка

Обов’язковим є включення трьох файлів: одного &pluginmap;, одного файла опису .xml додатка і одного файла .js додатка. Іншими словами, навіть каталог «plugins» є необов’язковим. Він лише допомагає упорядковувати файли, особливо, якщо ви включаєте до архіву декілька додатків або діалогових вікон, що, звичайно ж, можна робити. Ви можете використовувати будь-яку бажану кількість каталогів для файлів додатків, достатньо лише, щоб вони відповідали &pluginmap;. Ви навіть можете включити декілька файлів &pluginmap;, якщо це відповідає вашим потребам, але тоді їх усі слід включити до файла назва_додатка.pluginmap.

У кожному пакунку &R; має бути коректний файл `DESCRIPTION`, який є критично важливим для розпізнавання &rkward; пакунка як пакунка, що містить додаток. Більша частина відомостей, що містяться у цьому файлі, також потрібна для метаданих пакунка і для визначення залежностей, але у іншому форматі (докладний опис файла `DESCRIPTION` можна знайти у документації до &R;).

Окрім звичного вмісту, файл `DESCRIPTION` має також містити рядок Enhances: rkward. Додавання цього рядка підкаже &rkward;, що слід автоматично шукати додатки у пакунку, якщо його встановлено. Приклад файла `DESCRIPTION`:

    Package: SquaretheCircle
            Type: Package
            Title: Square the circle
            Version: 0.1-3
            Date: 2011-09-19
            Author: E.A. Dölle <doelle@eternalwondermaths.example.org>
            Maintainer: A. Assistant <alterego@eternalwondermaths.example.org>
            Enhances: rkward
            Description: Squares the circle using Heisenberg compensation.
            License: GPL
            LazyLoad: yes
            URL: http://eternalwondermaths.example.org/23/stc.html
            Authors@R: c(person(given="E.A.", family="Dölle", role="aut",
                            email="doelle@eternalwondermaths.example.org"),
                            person(given="A.", family="Assistant", role=c("cre",
                            "ctb"), email="alterego@eternalwondermaths.example.org"))

Вам не потрібно писати цей файл вручну. Якщо ви скористаєтеся функцією `rk.plugin.skeleton()` з пакунка rkwarddev і вкажете потрібні дані за допомогою параметра about, придатний до використання файл `DESCRIPTION` буде створено автоматично.

##### Додаткові відомості (необов’язкові)

Призначення файлів `ChangeLog`, `README`, `AUTHORS`, `LICENSE` є очевидним з їхніх назв. Ці файли не є обов’язковими. Зокрема, вони не оброблятимуться &rkward;, отже, там зберігатимуться додаткові дані, які можуть знадобитися, наприклад, супровідникам пакунків для дистрибутивів. Більшість вмісту цих файлів (подяки авторам, умови ліцензування тощо) за будь-яких умов буде включено у файли самого додатка (див. розділ щодо метаінформації). Зауважте, що усі ці файли також можна розмістити десь у каталозі «inst», якщо ви хочете, щоб вони були не лише у архіві з початковими кодами додатків, але і у встановленому пакунку.

##### Автоматичне тестування додатка (обов’язкове)

Ще одним необов’язковим каталогом є каталог «tests». У цьому каталозі можуть міститися файли, потрібні для автоматизованої системи тестування додатків. Такі тести корисні для пришвидшення визначення того, чи є ваші додатки працездатними у нових версіях &R; або &rkward;. Якщо ви маєте намір включити до пакунка тести, вам слід жорстко дотримуватися наведеної у цьому підручнику схеми найменувань та ієрархії. Тобто, ваші тести мають зберігатися у каталозі із назвою `tests`, у якому має бути файл `testsuite.R` і тека із стандартами тестів, назва якої має збігатися із назвою відповідного комплексу тестів. Якщо ви не хочете збирати усі тести до одного файла `testsuite.R`, ви можете поділити їх так, щоб на кожен комплекс тестів припадав один файл, і створити один `testsuite.R` із викликами `source()` для кожного з файлів комплексу. За будь-яких умов, створіть окремі підкаталоги із стандартами тестування для кожного визначеного комплексу.

Перевагою дотримання такої структури є те, що тестування додатка можна запустити простим викликом з додатковими аргументами функції `rktests.makplugintests()` з пакунка rkwardtests. Докладніший опис можна знайти у документації щодо автоматичного тестування додатків.

### Збирання пакунка з додатком

Як ми вже пояснювали раніше, зовнішні додатки &rkward; є, по суті, пакунками &R;, і тому процедура пакування є ідентичною. На відміну від «справжніх» пакунків &R;, чистий пакунок додатка не містить коду &R; (хоча ви, звичайно ж, можете також додати додатки &rkward; до звичайний пакунків &R;, використовуючи ті самі методи, що і наведені у цьому підручнику). Це має ще більше спростити створення працездатного пакунка: достатньо мати коректний файл `DESCRIPTION` і дотримуватися ієрархічної структури файлів, описаної у попередніх розділах.

Найпростішим способом збирання і тестування вашого додатка є використання команди R у командному рядку. Приклад:

``R` `CMD build` ``SquaretheCircle```

``R` `CMD INSTALL` ``SquaretheCircle_0.1-3.tar.gz```

Вам не обов’язково збирати пакунок у цей спосіб з командного рядка. Якщо ви скористаєтеся функцією `rk.build.package()` з пакунка rkwarddev, вона збере і/або виконає перевірку пакунка за вас.

## Розробка додатка за допомогою пакунка rkwarddev

### Огляд

Написання зовнішніх додатків включає створення файлів трьома мовами програмування (XML, JavaScript та R) та стандартизованої ієрархії каталогів. Щоб спростити процедуру для розробників додатків, нами створено пакунок rkwarddev. У цьому пакунку реалізовано декілька простих функцій &R; для створення початкових версій коду XML усіх елементів діалогових вікон, зокрема книг з вкладками, пунктів для позначок, спадних списків та панелей вибору файлів, а також функції для створення коду JavaScript та файлів довідки &rkward;. Функція `rk.plugin.skeleton()` створює відповідну ієрархію каталогів та усі потрібні файли там, де вони мають зберігатися.

Цей пакунок не встановлюється типово, але його можна встановити вручну із власного сховища &rkward;. Ви можете зробити це або за допомогою графічного інтерфейсу (Параметри Налаштувати пакунки), або скористатися сеансом &R;:

    install.packages("rkwarddev", repos="https://files.kde.org/rkward/R")
                    library(rkwarddev)

rkwarddev залежить від іншого невеличкого пакунка із назвою XiMpLe, який є дуже простим обробником і засобом створення коду XML і який також зберігається у тому самому сховищі пакунків.

Там же можна знайти повну документацію у форматі PDF. Докладніший вступ до роботи з цим пакунком можна знайти у короткому описі rkwarddev.

### Практичний приклад

Щоб зрозуміти, що являє собою безпосереднє написання додатка, вам слід ознайомитися із попередніми розділами. Ми ж зараз створимо повноцінний додаток t-перевірки ще раз. Цього разу лише за допомогою функцій &R; пакунка rkwarddev.

Пакунок додасть нове діалогове вікно &rkward;, доступ до якого можна буде отримати за допомогою пункту меню Файл Експортувати Створити скрипт додатка &rkward;. Як можна здогадатися з назви пункту, за його допомогою ви зможете створити каркас скрипту додатка для його подальшого редагування. Відповідне діалогове вікно створюється скриптом rkwarddev, який ви можете знайти у каталозі demo встановленого пакунка, де зберігаються і коди пакунка, як додатковий приклад. Ви також можете запустити цей скрипт за допомогою команди `demo("skeleton_dialog")`

#### Опис графічного інтерфейсу

Тут можна одразу помітити, що принципи роботи є суттєво іншими: замість безпосереднього написання коду XML вручну, ви починаєте не з визначення `<document>`, а безпосередньо з елементів додатка, які ви хочете бачити у діалоговому вікні. Ви можете пов’язати кожен елемент інтерфейсу, — поля для позначок, спадні меню, слоти для змінних або щось інше, — з окремими об’єктами &R;, а потім поєднати ці об’єкти із справжнім графічним інтерфейсом. У пакунку є функції для кожного теґу XML, якими можна скористатися для визначення графічного інтерфейсу додатка. Більшість з цих функцій мають ті самі назви, що і елементи графічного інтерфейсу, лише додається префікс `rk.XML.*`. Наприклад, щоб визначити `<varselector>` і два елементи `<varslot>` для змінних `x` і `y` прикладу з t-перевіркою, слід написати такий код:

    variables <- rk.XML.varselector(id.name="vars")
    var.x <- rk.XML.varslot("compare", source=variables, types="number", required=TRUE, id.name="x")
    var.y <- rk.XML.varslot("against", source=variables, types="number", required=TRUE, id.name="y")

Найцікавішою деталлю, ймовірно, є визначення `source=``variables`: визначною можливістю пакунка є те, що усі функції здатні створювати ідентифікатори автоматично, отже, вам не треба буде вигадувати усі значення `id` і запам’ятовувати їх для використання у відповідному елементі додатка. Ви можете просто надати еталонні об’єкти &R;, оскільки усі функції, яким потрібен ідентифікатор якогось іншого елемента, також можуть прочитати їх з цих об’єктів. Функція `rk.XML.varselector()` має особливість: зазвичай, у ній немає специфічних елементів, на основі яких можна створити ідентифікатор (це можливо, лише якщо вами вказано мітку), тому доводиться встановлювати назву ідентифікатора. А ось `rk.XML.varslot()` не потрібні аргументи `id.name`, достатньо написати так:

    variables <- rk.XML.varselector(id.name="vars")
    var.x <- rk.XML.varslot("compare", source=variables, types="number", required=TRUE)
    var.y <- rk.XML.varslot("against", source=variables, types="number", required=TRUE)

Досі, для створення коду ми встановлювали усі ідентифікатори вручну. Але оскільки пакунок має полегшити наше життя, віднині ми більше цього не робитимемо.

rkwarddev може автоматично виконувати значний обсяг роботи зі створення ваших додатків. Втім, іноді не варто використовувати усю його можливу потужність. Якщо вашою метою є написання коду, який не лише працюватиме, але і буде простим у читанні і порівнянні для інших програмістів, вам варто завжди створювати зручні для розуміння ідентифікатори за допомогою `id.name`. Іменування ваших об’єктів &R; ідентично до цих ідентифікаторів також допоможе у тому, щоб зробити код скрипту зрозумілішим.

Якщо ви хочете побачити, як виглядатиме код XML визначеного елемента, якщо ви експортуєте його до файла, ви можете просто викликати об’єкт за його назвою. Отже, якщо ви тепер виконаєте виклик var.x у вашому сеансі &R;, ви маєте побачити щось таке:

    <varslot id="vrsl_compare" label="compare" source="vars" types="number" required="true" />

Деякі теґи мають сенс лише у контексті інших теґів. Тому, наприклад, ви не знайдете функцій для теґу `<option>` tag. Замість цього, у списках варіантів і спадних списках пункти визначаються за допомогою `<option>` як іменовані списки, де назви відповідають міткам, які буде показано у діалоговому вікні, а значення є іменованим вектором з двох записів: `val` для значення пункту та булевого значення `chk`, яке визначає, чи буде пункт типово позначено.

    test.hypothesis <- rk.XML.radio("using test hypothesis",
            options=list(
                    "Two-sided"=c(val="two.sided"),
                    "First is greater"=c(val="greater"),
                    "Second is greater"=c(val="less")
            )
    )

Результат виглядає десь так:

    <radio id="rad_usngtsth" label="using test hypothesis">
            <option label="Two-sided" value="two.sided" />
            <option label="First is greater" value="greater" />
            <option label="Second is greater" value="less" />
    </radio>

На вкладці Basic settings не вистачає лише елемента поля для позначки для парних вибірок та упорядковування елементів за рядками і стовпчиками:

    check.paired <- rk.XML.cbox("Paired sample", value="1", un.value="0")
    basic.settings <- rk.XML.row(variables, rk.XML.col(var.x, var.y, test.hypothesis, check.paired))

`rk.XML.cbox()` є рідкісним виключенням, коли назва функції не містить повної назви теґу. Так зроблено, щоб трохи заощадити час на набиранні цього широковживаного елемента. Ось, що тепер міститиме `basic.settings`:

    <row id="row_vTFSPP10TF">
            <varselector id="vars" />
            <column id="clm_vrsTFSPP10">
                    <varslot id="vrsl_compare" label="compare" source="vars" types="number" required="true" />
                    <varslot id="vrsl_against" label="against" i18n_context="compare against" source="vars" types="number" required="true" />
                    <radio id="rad_usngtsth" label="using test hypothesis">
                            <option label="Two-sided" value="two.sided" />
                            <option label="First is greater" value="greater" />
                            <option label="Second is greater" value="less" />
                    </radio>
                    <checkbox id="chc_Pardsmpl" label="Paired sample" value="1" value_unchecked="0" />
            </column>
    </row>

У подібний же спосіб, наступні рядки створять об’єкти &R; для елементів вкладки Options, впровадивши функції для полів лічильника, рамок та розтягування:

    check.eqvar <- rk.XML.cbox("assume equal variances", value="1", un.value="0")
    conf.level <- rk.XML.spinbox("confidence level", min=0, max=1, initial=0.95)
    check.conf <- rk.XML.cbox("print confidence interval", val="1", chk=TRUE)
    conf.frame <- rk.XML.frame(conf.level, check.conf, rk.XML.stretch(), label="Confidence Interval")

Тепер нам залишилося лише об’єднати об’єкти у книгу з вкладками (tabbook), тобто додати таке у розділ dialog:

    full.dialog <- rk.XML.dialog(
            label="Two Variable t-Test",
            rk.XML.tabbook(tabs=list("Basic settings"=basic.settings, "Options"=list(check.eqvar, conf.frame)))
    )

Ми також можемо створити розділ майстра з його двома сторінками, використовуючи ті самі об’єкти, їхні ідентифікатори буде видобути з теґів `<copy>`:

    full.wizard <- rk.XML.wizard(
                    label="Two Variable t-Test",
                    rk.XML.page(
                            rk.XML.text("As a first step, select the two variables you want to compare against
                                    each other. And specify, which one you theorize to be greater. Select two-sided,
                                    if your theory does not tell you, which variable is greater."),
                            rk.XML.copy(basic.settings)),
                    rk.XML.page(
                            rk.XML.text("Below are some advanced options. It is generally safe not to assume the
                                    variables have equal variances. An appropriate correction will be applied then.
                                    Choosing \"assume equal variances\" may increase test-strength, however."),
                            rk.XML.copy(check.eqvar),
                            rk.XML.text("Sometimes it is helpful to get an estimate of the confidence interval of
                                    the difference in means. Below you can specify whether one should be shown, and
                                    which confidence-level should be applied (95% corresponds to a 5% level of
                                    significance)."),
                            rk.XML.copy(conf.frame)))

Ну ось і все з графічним інтерфейсом. Загальний документ буде зібрано у кінці за допомогою `rk.plugin.skeleton()`.

#### Код JavaScript

Досі, використання пакунка rkwarddev здавалося не дуже корисним. Давайте змінимо цю точку зору зараз же.

Перш за все, подібно до того, як ми не маємо дбати про ідентифікатори елементів, коли визначаємо компонування графічного інтерфейсу, нам не потрібно дбати про назви змінних JavaScript на наступному кроці. Якщо вам потрібні додаткові важелі керування, ви можете написати звичайний код JavaScript і вставити його до автоматично створеного файла. Але, ймовірно, найефективнішим способом все ж є використання rkwarddev.

Найпомітнішим є те, що вам не потрібно буде визначати жодну зі змінних власноруч, оскільки функція `rk.plugin.skeleton()` виконає сканування усього вашого коду XML і автоматично визначить усі потрібні вам змінні. Наприклад, вам не потрібно включати поле для позначки, якщо ви не використовуєте його значення або не встановлюєте його пізніше. Отже, ви зможете негайно розпочати написання дійсного коду JS для створення команд &R;.

Функція `rk.JS.scan()` також може шукати змінні у наявних файлах XML.

У пакунку є декілька функцій для конструктів коду JS code, які часто використовуються у додатках &rkward;, зокрема функція `echo()` та умови `if() {...} else {...}`. Між кодом JS і &R; є певні відмінності. Наприклад, у функції `paste()` &R; для з’єднання символьних рядків використовується кома, а у функції `echo()` JS слід з цією ж метою використовувати +; крім того рядки у JS слід завершувати крапкою з комою. Якщо ви використовуватимете функції &R;, ви зможете майже забути про ці відмінності і писати просто код мовою &R;.

Ці функції можуть отримувати різні класи вхідних об’єктів: звичайні текстові об’єкти, об’єкти &R; із кодом XML, як у наведеному вище прикладі, або результати виконання якихось інших функцій JS у пакунку. Наприкінці завжди слід викликати `rk.paste.JS()`, функцію, яка працює подібно до `paste()`, але, залежно від вхідних об’єктів, замінює їх на ідентифікатори XML, назви змінних JavaScript або навіть блоки коду JavaScript.

Для прикладу з t-перевіркою нам знадобляться два об’єкти JS: один для обчислення результатів і один для виведення цих результатів у функції `printout()`:

    JS.calc <- rk.paste.JS(
            echo("res <- t.test (x=", var.x, ", y=", var.y, ", hypothesis=\"", test.hypothesis, "\""),
            js(
                    if(check.paired){
                            echo(", paired=TRUE")
                    },
                    if(!check.paired && check.eqvar){
                            echo(", var.equal=TRUE")
                    },
                    if(conf.level != "0.95"){
                            echo(", conf.level=", conf.level)
                    },
                    linebreaks=TRUE
            ),
            echo(")\n"),
            level=2
    )

    JS.print <- rk.paste.JS(echo("rk.print (res)\n"), level=2)

Як можна бачити, у rkwarddev передбачено реалізацію мовою &R; функції `echo()`. Ця функція повертає точно один рядок символів із коректною версією самої функції мовою JS. Також можна помітити, що усі об’єкти &R; тут є раніше створеними нами об’єктами. Їх буде автоматично замінено відповідними назвами змінних, отже, ніяких проблем із ускладненням розуміння коду бути не повинно. Якщо вам потрібна буде така заміна, ви можете скористатися функцією `id()`, яка також повертає точно один рядок із символів на основі усіх переданих їй об’єктів (можна сказати, що вона поводить себе подібно до `paste()` із дуже специфічним підставлянням об’єктів).

Функція `js()` є обгорткою, яка надає вам змогу використовувати умови &R; `if(){...} else {...}` у звичний спосіб. Такі інструкції буде безпосередньо трансльовано у код JS. Функція також зберігає деякі оператори, зокрема `<`, `>=` або `||`, отже ви зможете виконувати логічне порівняння ваших об’єктів &R; без потреби у взятті їх у лапки. Погляньмо на отриманий об’єкт JS.calc, у якому тепер зберігається рядок з таким вмістом:

    echo("res <- t.test (x=" + vrslCompare + ", y=" + vrslAgainst + ", hypothesis=\"" + radUsngtsth + "\"");
            if(chcPardsmpl) {
                    echo(", paired=TRUE");
            } else {}
            if(!chcPardsmpl && chcAssmqlvr) {
                    echo(", var.equal=TRUE");
            } else {}
            if(spnCnfdnclv != "0.95") {
                    echo(", conf.level=" + spnCnfdnclv);
            } else {}
            echo(")\n");

Крім того, для умов `if()`, які вкладено до `js()`, ви можете скористатися функцією `ite()`, яка працює подібно до `ifelse()` у &R;. Втім, умови, побудовані за допомогою `ite()`, зазвичай важче читати, тому варто використовувати замість неї `js()` усюди, де це можливо.

#### Карта додатка

Цей розділ буде дуже коротким: нам не потрібно взагалі писати &pluginmap;, оскільки ці дані може бути автоматично створено за допомогою `rk.plugin.skeleton()`. Ієрархію меню можна визначити за допомогою параметра `pluginmap`:

    [...]
            pluginmap=list(
                    name="Two Variable t-Test",
                    hierarchy=list("analysis", "means", "t-Test"))
            [...]

#### Довідкова сторінка

Цей розділ теж дуже короткий: `rk.plugin.skeleton()` не зможе повністю написати довідку на основі отриманої інформації. Але ця функція може виконати сканування документа XML і виявити елементи, які, ймовірно, потребують належного документування. На основі списку таких елементів буде автоматично створено шаблон сторінки довідки для нашого додатка. Нам достатньо буде дописати декілька пояснювальних рядків для кожного із розділів цієї сторінки.

Функція `rk.rkh.scan()` також може шукати дані у наявних файлах XML для створення каркасу файла довідки.

#### Створення файлів додатка

Нарешті, останній крок, на якому ми передамо усі створені об’єкти `rk.plugin.skeleton()`:

    plugin.dir <- rk.plugin.skeleton("t-Test",
            xml=list(
                    dialog=full.dialog,
                    wizard=full.wizard),
            js=list(
                    results.header="Two Variable t-Test",
                    calculate=JS.calc,
                    printout=JS.print),
            pluginmap=list(
                    name="Two Variable t-Test",
                    hierarchy=list("analysis", "means", "t-Test")),
            load=TRUE,
            edit=TRUE,
            show=TRUE)

Типово, файли буде створено у тимчасовому каталозі. Останні три параметри не є обов’язковими, але значно спрощують роботу: `load=``TRUE` автоматично додасть новий додаток до налаштувань &rkward; (оскільки це тимчасовий каталог і, отже, його буде спорожнено після закриття &rkward;, запис додатка буде автоматично вилучено &rkward; під час наступного запуску програми), `edit=``TRUE` відкриє усі створені файли для редагування у вкладках редактора &rkward;, а `show=``TRUE` спробує безпосередньо запустити додаток, щоб ви могли ознайомитися з його виглядом навіть не клацаючи кнопкою миші. Ви також можете скористатися параметром `overwrite=``TRUE`, якщо ви запускаєте ваш скрипт повторно (наприклад, після змін у коді), оскільки типово після таких змін файли не перезаписуватимуться.

Об’єкт-результат plugin.dir містить шлях до каталогу, у якому було створено додаток. Він буде корисним у поєднанні з функцією `rk.build.package()`, для створення самого пакунка &R;, яким ви зможете поділитися з іншими користувачами, наприклад, надіслати його команді розробників &rkward; для додавання до нашого сховища додатків.

#### Скрипт повністю

Підсумовуючи усе сказане вище, наведемо скрипт для створення працездатного прикладу t-перевірки повністю. Окрім вже описаного коду, у скрипті містяться команди завантаження пакунка за запитом та використання середовища `local()`, щоб усі створені об’єкти не потрапили до вашого поточного робочого простору (окрім plugin.dir):

    require(rkwarddev)

    local({
            variables <- rk.XML.varselector(id.name="vars")
            var.x <- rk.XML.varslot("compare", source=variables, types="number", required=TRUE)
            var.y <- rk.XML.varslot("against", source=variables, types="number", required=TRUE)
            test.hypothesis <- rk.XML.radio("using test hypothesis",
                    options=list(
                            "Two-sided"=c(val="two.sided"),
                            "First is greater"=c(val="greater"),
                            "Second is greater"=c(val="less")
                    )
            )
            check.paired <- rk.XML.cbox("Paired sample", value="1", un.value="0")
            basic.settings <- rk.XML.row(variables, rk.XML.col(var.x, var.y, test.hypothesis, check.paired))

            check.eqvar <- rk.XML.cbox("assume equal variances", value="1", un.value="0")
            conf.level <- rk.XML.spinbox("confidence level", min=0, max=1, initial=0.95)
            check.conf <- rk.XML.cbox("print confidence interval", val="1", chk=TRUE)
            conf.frame <- rk.XML.frame(conf.level, check.conf, rk.XML.stretch(), label="Confidence Interval")

            full.dialog <- rk.XML.dialog(
                    label="Two Variable t-Test",
                    rk.XML.tabbook(tabs=list("Basic settings"=basic.settings, "Options"=list(check.eqvar, conf.frame)))
            )

            full.wizard <- rk.XML.wizard(
                            label="Two Variable t-Test",
                            rk.XML.page(
                                    rk.XML.text("As a first step, select the two variables you want to compare against
                                            each other. And specify, which one you theorize to be greater. Select two-sided,
                                            if your theory does not tell you, which variable is greater."),
                                    rk.XML.copy(basic.settings)),
                            rk.XML.page(
                                    rk.XML.text("Below are some advanced options. It is generally safe not to assume the
                                            variables have equal variances. An appropriate correction will be applied then.
                                            Choosing \"assume equal variances\" may increase test-strength, however."),
                                    rk.XML.copy(check.eqvar),
                                    rk.XML.text("Sometimes it is helpful to get an estimate of the confidence interval of
                                            the difference in means. Below you can specify whether one should be shown, and
                                            which confidence-level should be applied (95% corresponds to a 5% level of
                                            significance)."),
                                    rk.XML.copy(conf.frame)))

            JS.calc <- rk.paste.JS(
                    echo("res <- t.test (x=", var.x, ", y=", var.y, ", hypothesis=\"", test.hypothesis, "\""),
                    js(
                            if(check.paired){
                            echo(", paired=TRUE")
                            },
                            if(!check.paired && check.eqvar){
                            echo(", var.equal=TRUE")
                            },
                            if(conf.level != "0.95"){
                            echo(", conf.level=", conf.level)
                            },
                            linebreaks=TRUE
                    ),
                    echo(")\n"), level=2)

            JS.print <- rk.paste.JS(echo("rk.print (res)\n"), level=2)

            plugin.dir <<- rk.plugin.skeleton("t-Test",
                    xml=list(
                            dialog=full.dialog,
                            wizard=full.wizard),
                    js=list(
                            results.header="Two Variable t-Test",
                            calculate=JS.calc,
                            printout=JS.print),
                    pluginmap=list(
                            name="Two Variable t-Test",
                            hierarchy=list("analysis", "means", "t-Test")),
                    load=TRUE,
                    edit=TRUE,
                    show=TRUE,
                    overwrite=TRUE)
    })

### Додавання сторінок довідки

Якщо ви хочете написати сторінку довідки для вашого додатка, найпростішим способом це зробити буде додавання певних інструкцій безпосередньо до визначень елементів XML:

    variables <- rk.XML.varselector(
      id.name="vars",
      help="Select the data object you would like to analyse.",
      component="Data"
    )

Текст, що передається параметру `help`, потім можна отримати за допомогою функції `rk.rkh.scan()` і записати до сторінки довідки компонента додатка. Втім, щоб це спрацювало з технічної точки зору, `rk.rkh.scan()` потрібно знати, які об’єкти &R; належать одному компоненту додатка. Ось чому вам слід вказати параметр `component` і переконатися, що він є однаковим для усіх об’єктів у межах одного компонента.

Оскільки у одному діалоговому вікні поєднується багато об’єктів, і у вас може виникнути бажання повторно використати об’єкти, подібні до `<varslot>`, у багатьох компонентах ваших додатків, передбачено можливість визначити компонент на загальному рівні за допомогою функції `rk.set.comp()`. Якщо такий компонент встановлено, припускається, що усі наступні об’єкти, використані у вашому скрипті, належать цьому компоненту, аж доки `rk.set.comp()` не буде викликано знову із іншою назвою компонента. Якщо використано цю функцію, ви можете пропустити параметр `component`:

    variables <- rk.XML.varselector(
      id.name="vars",
      help="Select the data object you would like to analyse.",
      component="Data"
    )

Щоб додати до сторінки довідки загальні розділи, зокрема `<summary>` або `<usage>`, скористайтеся відповідною функцією `rk.rkh.summary()` або`rk.rkh.usage()`. Результати роботи цих функцій потім використовуються для встановлення списку елементів, подібного до `summary` або `usage`, у параметрі `rkh` функції `rk.plugin.component()`/`rk.plugin.skeleton()`.

### Переклад додатків

Пакунок rkwarddev здатний створювати зовнішні додатки з повною підтримкою інтернаціоналізації. Наприклад, усі відповідні функції на основі об’єктів XML матимуть додатковий параметр для визначення `контексту i18n` або `мітки непридатності до перекладу`:

    varComment <- rk.XML.varselector(id.name="vars", i18n=list(comment="Main variable selector"))
    varContext <- rk.XML.varselector(id.name="vars", i18n=list(context="Main variable selector"))
    cboxNoi18n <- rk.XML.cbox(label="Power", id.name="power", i18n=FALSE)

Наведені вище приклад дадуть десь такий результат:

    # varComment
    <!-- i18n: Main variable selector -->
      <varselector id="vars" />

    # varContext
    <varselector id="vars" i18n_context="Main variable selector" />

    # cboxNoi18n
    <checkbox id="power" noi18n_label="Power" value="true" />

Передбачено також підтримку перекладів у коді JS. Фактично, пакунок намагається типово додати виклики `i18n()` у місця, де це зазвичай є корисним. Добрим прикладом є функція `rk.JS.header()`:

    jsHeader <- rk.JS.header("Test results")

Це дасть нам такий код JS:

    new Header(i18n("Test results")).print();

Втім, ви можете позначити рядки у вашому коді JS і вручну за допомогою функції `i18n()` так, як ви б це зробили, якби писали код файла JS з початку.

## Довідник

### Типи властивостей/Модифікатори

У деяких фрагмента цього вступу ми згадували властивості елементів графічного інтерфейсу або інших елементів. Фактично, існує декілька різних типів властивостей. Зазвичай, перейматися цим непотрібно, оскільки ви можете скористатися простим здоровим глуздом для з’єднування між собою властивостей. Втім, на внутрішньому рівні використовуються різні типи властивостей. Це має значення, коли ми отримуємо певні особливі значення у шаблоні JS. У інструкціях getString ("id")/getBoolean ("id")/getList ("id") ви також можете вказати якийсь із так званих модифікаторів ось так: `getString ("id.модифікатор")`. Цей модифікатор впливатиме на спосіб виведення значення. Ознайомтеся зі списком властивостей та ідентифікаторами, які можна використовувати з цими властивостями:

Рядкові властивості

- Найпростіший тип властивості, використовується для зберігання текстового фрагмента. Модифікатори:

  Без модифікатора ("")

- Рядок, яким його визначено або встановлено.

quoted

- Рядок у форматі з лапками (придатний для передавання &R; як символу).

Булеві властивості

- Властивості, які можуть мати значення «on» («увімкнено») або «off» («вимкнено»), «true» («так») або «false» («ні»). Наприклад, властивості, створені теґами <convert>, також властивість, що супроводжує <checkbox> (див. нижче). Відповідно до вказаного модифікатора, буде повернуто такі значення:

  Без модифікатора ("")

- Типово властивість повертає значення 1, якщо має значення true, і 0, якщо має значення false. Рекомендованим способом отримання булевих значень є використання `getBoolean()`. Зауважте, що `getString()` поверне рядок «0», якщо властивість матиме значення false. Такий рядок вважатиметься у JS значенням true, а не false.

"labeled"

- Повертає рядок «true» якщо має значення «так», і «false», якщо має значення «ні», або будь-які вказані програмістом нетипові рядки (типово використовується у <checkbox>).

"true"

- Повертає рядок, так, наче властивість мала істинне значення, навіть якщо вона його не має

"false"

- Повертає рядок, так, наче властивість не мала істинного значення, навіть якщо вона його має

"not"

- Повертає обернене булеве значення властивості, протилежне до поточного (тобто «ні», якщо «так», і «так», якщо «ні»)

"numeric"

- Застарілий, зберігається для зворотної сумісності. Те саме, що і модифікатор "". Повертає «1», якщо властивість має значення «так» (true), і «0», якщо властивість має значення «ні» (false).

Цілочисельні властивості

- Властивість, яку створення для зберігання цілих значень (але, звичайно ж, вона повертатиме шаблону JS рядок із символів запису чисел). Вона не приймає будь-яких модифікаторів. Використовується у елементах <spinbox> (див. нижче).

Властивості, які мають дійсні значення

- Властивість, яку створення для зберігання дійсних значень (але, звичайно ж, вона повертатиме шаблону JS рядок із символів запису чисел). Використовується у елементах <spinbox> (див. нижче).

  Без модифікатора ("")

- Для функцій `getValue() / getString()` повертає те саме, що і «formatted». У майбутніх версіях можна буде отримати числове представлення.

"formatted"

- Повертає форматоване число (як рядок).

Властивості RObject

- Властивість, створена для вибору одного або декількох об’єктів &R;. Найчастіше використовується у varselector-ах та varslot-ах. Повернуто буде такі значення, відповідно до вказаного модифікатора:

  Без модифікатора ("")

- Типово властивість повертає повну назву вибраного об’єкта. Якщо вибрано декілька об’єктів, назви об’єктів буде відокремлено символами розриву рядка ("\n").

"shortname"

- Подібно до попереднього, але повертає лише скорочені назви об’єктів. Наприклад, для об’єкта у списку буде повернуто його назву всередині списку, без назви списку.

"label"

- Подібно до попереднього, але повертає мітки &rkward; об’єктів (якщо мітки немає, повертає те саме, що і shortname)

Властивості зі значеннями, які є списками рядків

- Ця властивість містить список рядків.

  Без модифікатора ("")

- Для `getValue()/getString()`. Повертає усі рядки, відокремлені «\n». Усі символи «\n» у окремому записі буде екрановано як літерал «\n». Втім, рекомендованим способом отримання списків є функція `getList()`, яка повертає масив рядків.

"joined"

- Повертає список як єдиний рядок, пункти списку буде відокремлено у такому рядку символами «\n». На відміну від використання без модифікатора (""), вміст окремих рядків не екрануватиметься.

Властивості коду

- Властивість, яку мають додатки, які створюють код &R;. Важлива для додатків, до яких вбудовуються інші додатки, власне для вбудовування коду, створеного вбудованим додатком до коду, який створено основним додатком (додатком верхнього рівня). Повертає такі значення, залежно від вказаного модифікатора:

  Без модифікатора ("")

- Повертає код повністю, тобто розділи «preprocess», «calculate», «printout» (але не «preview»), з’єднані у один рядок.

"preprocess"

- Повертає лише розділ preprocess коду

"calculate"

- Повертає лише розділ calculate коду

"printout"

- Повертає лише розділ printout коду

"preview"

- Повертає розділ preview коду

### Елементи загального призначення, які можна використовувати у будь-якому файлі XML (`.xml`, `.rkh`, &pluginmap;)

<snippets>

- Можна використовувати як безпосередній дочірній елемент вузла <document>, і лише як такий елемент. Має бути розміщено на початку файла. Див. розділ щодо використання фрагментів коду. У файлі може бути лише один елемент <snippets>. Необов’язковий, не має атрибутів.

<snippet>

- Визначає окремий фрагмент. Можна використовувати лише як дочірній елемент елемента <snippets/>. Атрибути:

  <id>

- Рядок-ідентифікатор фрагмента. Є обов’язковим.

<insert>

- Вставити вміст <snippet>. Можна використовувати усюди. Атрибути:

  <snippet>

- Ідентифікатор рядка фрагмента, який слід вставити. Є обов’язковим.

<include>

- Включити вміст іншого файла XML (усі дані всередині елемента <document> у цьому файлі). Можна використовувати усюди. Атрибути:

  <file>

- Назва файла відносно каталогу, у якому зберігається поточний файл. Є обов’язковою.

### Елементи, які буде використано у описі XML додатка.

Властивості елементів наведено у окремому розділі.

#### Загальні елементи

<document>

- Має бути у будь-якому файлі description.xml як кореневий вузол. Не має спеціальних функцій. Не має атрибутів.

<about>

- Відомості щодо цього додатка (автор, умови ліцензування тощо). Цей елемент можна використовувати у файлах `.xml` окремих додатків та у файлах &pluginmap;. Докладний опис можна знайти у довіднику щодо файлів &pluginmap;, вступні зауваження — у розділі щодо даних «about».

<code>

- Визначає, де шукати шаблон JS додатка. Можна використовувати у файлі лише один раз, як дочірній елемент теґу document. Атрибути:

  `file`

- Назва файла шаблона JS відносно каталогу, у якому зберігається файл .xml додатка.

<help>

- Визначає, де шукати файл довідки додатка. Можна використовувати у файлі лише один раз, як дочірній елемент теґу document. Атрибути:

  `file`

- Назва файла довідки відносно каталогу, у якому зберігається файл .xml додатка.

<copy>

- Можна використовувати як дочірню властивість (безпосередню або опосередковану) елементів основного компонування, тобто <dialog> та <wizard>. Використовується для буквального копіювання цілого блоку елементів xml. Атрибути:

  `id`

- Ідентифікатор, який слід шукати. Теґ <copy> шукатиме попередній щодо нього елемент XML, якому надано той самий ідентифікатор і копіюватиме його разом із усіма підлеглими елементами.

`copy_element_tag_name`

- Іноді, у вас може виникнути потреба у майже буквальній копії, але зі зміною назви теґу елемента, який слід скопіювати. Найважливішим прикладом таких випадків є випадок, коли вам потрібно скопіювати вкладку <tab> з інтерфейсу діалогового вікна на сторінку <page> інтерфейсу майстра. У цьому випадку вам слід встановити copy_element_tag_name="page", щоб виконати перетворення автоматично.

#### Визначення інтерфейсу

<dialog>

- Визначає інтерфейс типу діалогового вікна. У цьому тезі ви маєте визначити графічний інтерфейс. Теґ можна використовувати лише один раз у одному файлі, як дочірній елемент теґу document. У додатку має бути принаймні один теґ «dialog» або «wizard». Атрибути:

  `label`

- Надпис діалогового вікна

`recommended`

- Визначає, чи має бути використано діалогове вікно як «рекомендований» інтерфейс (тобто інтерфейс, який буде типово показано, якщо користувач не налаштував &rkward; на використання визначеного ним інтерфейсу). Цей атрибут у поточній версії не використовується, оскільки неявним чином він має значення «true», якщо рекомендованим не визначено інтерфейс майстра.

<wizard>

- Визначає інтерфейс типу вікна майстра. У цьому тезі ви маєте визначити графічний інтерфейс. Теґ можна використовувати лише один раз у одному файлі, як дочірній елемент теґу document. У додатку має бути принаймні один теґ «dialog» або «wizard». Приймає як безпосередні дочірні елементи лише теґи <page> і <. Атрибути:

  `label`

- Надпис майстра

`recommended`

- Визначає, чи має бути використано вікно майстра як «рекомендований» інтерфейс (тобто інтерфейс, який буде типово показано, якщо користувач не налаштував &rkward; на використання визначеного ним інтерфейсу). Необов’язковий, типовим значенням є «false» («ні»).

#### Елементи компонування

В усіх елемента з цього розділу можна використовувати атрибут id="рядок-ідентифікатор". Цей атрибут є необов’язковим для усіх елементів. Ним можна скористатися, наприклад, для приховування або вимикання цілого елемента компонування та усіх елементів, які у ньому містяться (див. розділ щодо логіки графічного інтерфейсу). Рядок-ідентифікатор не повинен містити символів «.» (крапка) та «;» (крапка з комою), і, загалом, має складатися із літер латинської абетки, цифр та символів підкреслювання («_»). У списках атрибутів наведено лише необов’язкові атрибути.

<page>

- Визначає нову сторінку у майстрі. Може використовуватися лише як дочірній елемент елемента <wizard>.

<row>

- Усі безпосередні дочірні елементи теґу «row» буде розташовано зліва праворуч.

<column>

- Усі безпосередні дочірні елементи теґу «column» буде розташовано згори вниз.

<stretch>

- Типово, елементи графічного інтерфейсу займатимуть увесь доступний простір. Наприклад, якщо у інтерфейсі є два стовпчика пунктів, і лівий з них заповнено пунктами, а у правому міститься лише один елемент `<radio>`, елемент `<radio>` буде розгорнуто вертикально, навіть якщо для цього не потрібне усе доступне місце. Це виглядатиме доволі потворно. Щоб уникнути таких проблем, потрібно додати «порожній» елемент під `<radio>`. Для цього використовують елемент <stretch>. Він просто займає місце. Не зловживайте ним, оскільки, зазвичай, графічні елементи найкраще виглядають, коли займають усе доступне місце. Лише іноді це призводить до проблем із компонуванням. Елемент <stretch> не приймає жодних аргументів, навіть «id». Крім того, не можна розташовувати дочірні елементи всередині елемента <stretch> (іншими словами, він використовується лише як «<stretch/>»).

<frame>

- Малює рамку навколо свого безпосереднього дочірнього елемента. Може бути використаний для візуального групування пов’язаних параметрів. Компонування у рамці виконується згори вниз, якщо ви не вкажете всередині теґу <row>. Атрибути:

  `label`

- Надпис для фрейма (необов’язковий)

`checkable`

- Рамки можна зробити придатними для позначення. Якщо у рамки є поле для позначки і воно порожнє (не позначено), усі елементи у рамці буде вимкнено аж доти, доки користувач не поставить у полі позначку. (Необов’язковий, типовим значенням є «false».)

`checked`

- Лише для рамок із позначками: визначає, чи має бути пункт рамки типово позначено. Типовим значенням є «true». Не обробляється для рамок без позначок.

<tabbook>

- Збирає елементи у вікно з вкладками (tabbook). Як дочірні елементи можна використовувати лише елементи <tab>.

<tab>

- Визначає сторінку у tabbook. Усередині цього елемента слід розташовувати визначення графічного інтерфейсу вкладки. Можна використовувати лише як безпосередній дочірній елемент теґу <tabbook>. У <tabbook> має бути принаймні дві визначені вкладки. Атрибути:

  `label`

- Надпис для сторінки із вкладками (обов’язковий)

<text>

- Показує текст, розташований всередині цього теґу у графічному інтерфейсі. Передбачено підтримку простої розмітки у стилі HTML (зокрема `<b>`, `<i>`, `<p>` та `<br/>`). Будь ласка, не зловживайте форматуванням. За допомогою додавання порожнього рядка можна вручну почати новий абзац тексту. Атрибути:

  `type`

- Тип тексту. Одне зі значень: "normal", "warning" або "error". Впливає на вигляд тексту (необов’язковий, типовим є значення «normal»).

#### Активні елементи

Усім елементам у цьому розділі можна передавати атрибут id="рядок_ідентифікатора". Цей атрибут є обов’язковим для усіх елементів. Нижче наведено лише додаткові атрибути. Рядок ідентифікатора не повинен містить символів «.» (крапок).

<varselector>

- Надає список доступних об’єктів, з який користувач може вибрати один або декілька. Для використання слід вказати всередині елемента один або декілька елементів <varslot>. Атрибути:

  `label`

- Мітка varselector (необов’язкова, типовим є значення «Select variable(s)»)

<varslot>

- Використовується у поєднанні з «varselector» для того, щоб вибрати одну або декілька змінних. Атрибути:

  `label`

- Мітка для varslot (рекомендовано вказати, типовим значенням є «Variable:»)

`source`

- Елемент varselector, з якого слід отримувати варіанти вибору (обов’язковий, якщо немає з’єднування вручну або використання source_property).

`source_property`

- Довільна властивість, з якої слід скопіювати значення, коли натиснуто кнопку вибору. Якщо вказано, перевизначає атрибут «source».

`required`

- Визначає для надсилання коду, чи є обов’язковою наявність у varslot коректного значення. Див. документацію до властивості required (необов’язкова, типовим значенням є true).

`multi`

- Визначає, містить varslot лише один (типовий варіант, «false») чи декілька об’єктів.

`allow_duplicates`

- Визначає, може varslot приймати лише унікальні об’єкти (типовий варіант, «false») чи той самий об’єкт може бути додано декілька разів.

`min_vars`

- Має значення, лише якщо multi="true": мінімальна кількість змінних, які має бути позначено, щоб позначення вважалося коректним (необов’язковий, типовим значенням є 1).

`min_vars_if_any`

- Має значення, лише якщо multi="true": деякі varslot-и можуть вважатися коректними, якщо, наприклад, varslot є порожнім або містить принаймні два значення. Цей атрибут визначає, скільки змінних має бути позначено, якщо змінні позначено (2 у нашому прикладі). (необов’язковий, типовим значенням є «1»)

`max_vars`

- Має значення, лише якщо multi="true": максимальна кількість змінних, які може бути позначено (необов’язковий, типовим значенням є 0, що означає, що максимальну кількість не обмежено).

`класи`

- Якщо у цьому атрибуті ви вкажете одну або декілька назв класів &R; (відокремлених пробілами (« »)), varslot прийматиме лише об’єкти, що належать цим класам (необов’язковий, користуйтеся дуже обережно, не можна забороняти користувачеві вибирати коректні варіанти, а у &R; є багато різних класів!)

`types`

- Якщо у цьому атрибуті ви вкажете один або декілька типів змінних (відокремлених пробілами (" ")), varslot прийматиме лише об’єкти вказаних типів. Коректними вважаються такі типи: «unknown», «number», «string», «factor», «invalid». (необов’язковий, користуйтеся дуже обережно — не можна забороняти користувачеві вибирати коректні варіанти, а &rkward; не завжди може визначити тип змінної)

`num_dimensions`

- Кількість розмірностей, які повинен мати об’єкт. «0» (типове значення) означає, що прийнятними є усі розмірності. (Необов’язкова, типовим значенням є «0»)

`min_length`

- Мінімальна довжина, яку повинен мати об’єкт, щоб бути прийнятним. (Необов’язкова, типовим є значення «0»)

`max_length`

- Максимальна довжина, яку повинен мати об’єкт для того, щоб бути прийнятним. (Необов’язкова, типовим є значення найбільшого цілого числа, яке може бути представлене операційною системою)

<valueselector>

- Містить список доступних рядків (не об’єктів &R;), які можна вибрати у одному або декількох пов’язаних <valueslot>. Пункти рядків можна визначити за допомогою безпосередніх дочірніх теґів <option> (див. нижче) або встановити за допомогою динамічних властивостей. Атрибути:

  `label`

- Мітка для поля вибору значень (необов’язкова, типово мітки не буде)

<valueslot>

- Використовується у поєднанні з <valueselector> для уможливлення вибору користувачем одного або декількох рядкових пунктів. Цей елемент здебільшого ідентичний до <varslot> і має ті самі атрибути, окрім тих, що відповідають властивостям прийнятних пунктів (тобто classes, types, num_dimensions, min_length, max_length).

<radio>

- Визначає групу взаємовиключних кнопок-варіантів (одночасно позначено може бути лише один пункт варіанта). Потребує принаймні два безпосередніх дочірніх теґи <option>. Інші теґи не можуть бути дочірніми теґами radio. Атрибути:

  `label`

- Мітка для поля вибору з варіантів (рекомендовано вказати, типовою є «Select one:»)

<dropdown>

- Визначає групу пунктів, серед яких можна вибрати один і лише один за допомогою спадного списку. Функціонально еквівалентний до <radio>, але виглядає інакше. Потребує визначення принаймні двох безпосередніх дочірніх теґів <option>. Інші дочірні теґи використовувати не можна. Атрибути:

  `label`

- Мітка для спадного списку (рекомендовано вказати, типовою є «Select one:»)

<select>

- Містить список доступних рядків з яких користувач може вибрати довільну кількість рядків. Пункти рядків можна визначити за допомогою безпосередніх дочірніх теґів <option> (див. нижче) або встановити за допомогою динамічних властивостей. Атрибути:

  `label`

- Мітка для <select> (необов’язкова, типово її не буде)

`single`

- Якщо встановлено значення «true», вибрати можна буде лише одне значення, а не декілька значень одразу (булевий параметр, типове значення — «false»)

<option>

- Можна використовувати лише як безпосередній дочірній теґ елемента <radio>, <dropdown>, <valueselector> або <select>. Відповідає одному придатному для вибору пункту у списку вибору з варіантів або спадному списку. Оскільки елементи <option> завжди є частиною списку елементів, зазвичай, у них немає власного ідентифікатора (атрибута «id»), але можливі варіанти і з таким атрибутом (див. нижче). Атрибути:

  `label`

- Мітка варіанта (обов’язкова)

`value`

- Рядкове значення, яке повертатиме батьківський елемент, якщо пункт буде позначено або вибрано (обов’язкове)

`checked`

- Визначає, чи має бути типово позначено пункт, «true» або «false». У <radio> і <dropdown> значення `checked=``"true"` може бути використано лише для одного пункту. Якщо для жодного пункту не встановлено «checked», автоматично буде позначено перший пункт у батьківському елементі. У <select> може бути встановлено значення «checked» для довільної кількості пунктів. (необов’язкове, типовим значенням є «false»)

`id`

- Визначення параметра «id» для елементів <option> є необов’язковим (фактично, не рекомендуємо вам встановлювати «id», якщо у цьому немає нагальної потреби). Втім, визначення «id» надасть вам змогу вмикати або вимикати <option> у динамічному режимі, встановивши з’єднання із булевою властивістю `ідентифікатор_radio.ідентифікаор_пунктуX.enabled`. У поточній версії програми це працює лише у елементах <radio> і <dropdown>; для пунктів <valueselector> і <select> підтримки ідентифікаторів для пунктів не передбачено.

<checkbox>

- Визначає пункт для позначки, тобто однозначну відповідь (так чи ні) на певне питання, яку дають позначенням пункту або зняттям з нього позначки. Атрибути:

  `label`

- Мітка поля для позначки (обов’язкова)

`value`

- Значення, яке повертатиме пункт для позначки, якщо його позначено (обов’язкове)

`value_unchecked`

- Значення, яке буде повернуто, якщо пункт для позначки не позначено (необов’язкове, типовим є "", тобто порожній рядок)

`checked`

- Визначає, чи має бути пункт типово позначено, «true» (так) чи «false» (необов’язкова, типовим є значення «false»)

<frame>

- Елемент рамки, загалом, використовується як суто елемент компонування. Його опис розміщено у розділі щодо елементів компонування. Втім, його можна також зробити придатним для позначення, щоб він працював як звичайний пункт для позначки.

<input>

- Визначає поле для введення довільного тексту. Атрибути:

  `label`

- Мітка поля введення (обов’язкова)

`initial`

- Початковий текст у полі (необов’язковий, типовим значенням є «», тобто порожній рядок)

`size`

- Одне з таких значень: «small» (малий), «medium» (середній) та «large» (великий). «large» визначає багаторядкове поле для введення, «small» і «medium» — однорядкові (необов’язковий, типовим є значення «medium»).

`required`

- Визначає для надсилання коду, чи є обов’язковим заповнення цього поля. Див. документацію до властивості required (необов’язкова, типовим значенням є true).

<matrix>

- Таблиця для введення даних матриць (або векторів) у форматі графічного інтерфейсу.

  Цей елемент введення даних не оптимізовано для редагування великих масивів даних. Хоча немає строгих обмежень щодо розміру <matrix>, загалом, розмірності не повинні перевищувати десять рядків на десять стовпчиків. Якщо вам потрібен більший масив даних, дозвольте користувачам вибирати його як об’єкт &R; (цим варто скористатися як альтернативним варіантом майже всюди, де використовуються матриці).

  Атрибути:

  `label`

- Мітка таблиці (обов’язкова)

`mode`

- Одне зі значень, «integer», «real» або «string». Тип даних, які будуть прийнятними для таблиці (обов’язковий).

`min`

- Мінімальне прийнятне значення (для матриць типу «integer» або «real») (необов’язкове, типовим значенням є найменше придатне для представлення число)

`max`

- Максимальне прийнятне значення (для матриць типу «integer» або «real») (необов’язкове, типовим значенням є найбільше придатне для представлення число)

`allow_missings`

- Визначає, чи можна використовувати пропуски (порожні значення) у матриці. Використовується у матрицях з рядкових значень або у режимі «string» (необов’язковий параметр, типовим є значення «false» або не можна).

`allow_user_resize_columns`

- Якщо встановлено значення «true», користувач може додавати стовпчики введенням значень у найправіші (неактивні) комірки (необов’язковий параметр, типовим значенням є «true» або може).

`allow_user_resize_rows`

- Якщо встановлено значення «true», користувач може додавати рядки введенням значень у найнижчі (неактивні) комірки (необов’язковий параметр, типовим значенням є «true» або може).

`rows`

- Кількість рядків у матриці. Не працює, якщо allow_user_resize_rows="true".

  Цим значенням можна керувати за допомогою властивості "rows".

  (Необов’язковий параметр, типовим є значення 2).

`columns`

- Кількість стовпчиків у матриці. Не працює, якщо allow_user_resize_columns="true".

  Цим значенням можна керувати за допомогою властивості "columns".

  (Необов’язковий параметр, типовим є значення 2).

`min_rows`

- Мінімальна кількість рядків у матриці. Матрицю не можна буде стиснути до розміру, який є меншим за це значення. (Необов’язковий параметр, типовим є значення 0; див. також `allow_missings`.)

`min_columns`

- Мінімальна кількість стовпчиків у матриці. Матрицю не можна буде стиснути до розміру, який є меншим за це значення. (Необов’язковий параметр, типовим є значення 0; див. також `allow_missings`.)

`fixed_height`

- Примусово встановити для елемента графічного інтерфейсу його початкову висоту. Не використовуйте у поєднанні з матрицями, у яких у якийсь спосіб може змінитися кількість рядків. Особливо корисно, якщо створюються елементи введення векторів (columns="1"). Якщо для цього параметра встановлено значення «true», програма не показуватиме горизонтальної смужки гортання, навіть якщо матриця буде ширшою за доступну у вікні ширину (оскільки це впливатиме на висоту). (необов’язкова, типовим значенням є «false»).

`fixed_width`

- Трохи оманлива назва: припустімо, що кількість стовпчиків не зміниться. Останній (або типово єдиний) стовпчик буде розтягнуто так, щоб він зайняв усю доступну ширину. Не використовуйте у поєднанні з матрицями, де кількість рядків може змінитися. Особливо корисно під час створення елементів введення векторів (rows="1"). (необов’язкова, типовим значенням є «false»)

`horiz_headers`

- Рядки, які слід використовувати для горизонтального заголовка, відокремлені символом «;». Якщо встановити значення "", заголовок буде приховано. (Необов’язковий параметр, типовим значенням є номер стовпчика).

`vert_headers`

- Рядки, які слід використовувати для вертикального заголовка, відокремлені символом «;». Якщо встановити значення "", заголовок буде приховано. (Необов’язковий параметр, типовим значенням є номер рядка).

<optionset>

- Інтерфейс користувача для повторення набору параметрів для довільної кількості елементів (вступ до наборів параметрів). Атрибути:

  `min_rows`

- Якщо вказано, набір буде позначено як некоректний, якщо у ньому менше вказаної кількості рядків (необов’язковий атрибут, ціле число).

`min_rows_if_any`

- Подібний до min_rows, але перевірка щодо нього виконуватиметься, лише якщо існує принаймні один рядок (необов’язковий атрибути, ціле число).

`max_rows`

- Якщо вказано, набір буде позначено як некоректний, якщо у ньому більше вказаної кількості рядків (необов’язковий атрибут, ціле число).

`keycolumn`

- Ідентифікатор стовпчика, який працюватиме як keycolumn. optionset із (коректним) keycolumn працюватиме як «керований» optionset. optionset без keycolumn надаватиме змогу вручну вставляти або вилучати записи. keycolumn має бути позначено як зовнішній (необов’язковий, типовою є відсутність keycolumn).

Дочірні елементи:

<optioncolumn>

- Оголошує один елемент optioncolumn набору. Для кожного значення, яке ви хочете отримати з optionset вам слід оголосити окремий елемент <optioncolumn>. Атрибути:

  `id`

- Ідентифікатор optioncolumn (обов’язковий атрибут, рядок).

`external`

- Встановіть значення true (так), якщо optioncolumn керується з-поза меж optionset (необов’язкова, булева, типовим значенням є false).

`label`

- Якщо вказано, optioncolumn буде показано у стовпчику з цією міткою (необов’язковий, рядок, типово не показано).

`connect`

- Властивість, з якою слід з’єднати цей optioncolumn, задана як ідентифікатор у області <content>. Для зовнішніх <optioncolumn> відповідне значення буде встановлено у зовнішньо встановлене значення. Для звичайних (не зовнішніх) <optioncolumn> буде встановлено значення відповідного рядка властивості <optioncolumn>, якщо властивість змінюється у області вмісту. (необов’язкова, рядкова, типове значення — «не з’єднано»).

`default`

- Лише для зовнішніх стовпчиків: значення, яке є типовим для цього стовпчика, якщо значення у комірці немає. Використання є рідкісним. (необов’язкова, типовим значенням є порожній рядок)

<content>

- Оголошує вміст або графічний інтерфейс набору. Не має атрибутів. Як дочірні елементи можна використовувати усі звичайні активні, пасивні елементи та елементи компонування. Крім того, у ранніх версіях &rkward; (аж до 0.6.3) можна було використовувати спеціальний дочірній елемент `<optiondisplay>`. Цей елемент вважається застарілим з часу &rkward; 0.6.4, його слід просто вилучити з наявних додатків.

<logic>

- Додаткова специфікація логіки інтерфейсу, яку слід застосувати всередині області вмісту optionset. Див. довідкові матеріали щодо <logic>

<browser>

- Елемент призначено для вибору одної назви файла (або назви каталогу). Зауважте, що це поле приймає будь-який рядок, хоча його призначено лише для назв файлів:

  `label`

- Мітка вікна вибору файла (необов’язкова, типовим значенням є «Enter filename»)

`initial`

- Початковий текст у засобі вибору файлів (необов’язковий, типовим значенням є «», тобто порожній рядок)

`type`

- Одне зі значень: "file", "dir" або "savefile". Щоб вибрати наявний файл, наявний каталог або файл, якого не існує, відповідно (необов’язковий аргумент, типовим значенням є "file")

`allow_urls`

- Визначає, чи можна вибирати (нелокальні) адреси (необов’язковий аргумент, типовим є значення "false")

`filter`

- Фільтр типу файлів, наприклад ("*.txt *.csv" для файлів .txt і .csv). Автоматично буде додано запис "All files" (усі файли) (необов’язкова, типовим значенням є "", тобто «усі файли»).

`required`

- Визначає для полів надсилання коду, чи обов’язково поле має бути заповнено. Зауважте, що це не обов’язково значить, що назва файла є коректною! Див. документацію щодо властивості required (необов’язкова, типовим значенням є true).

<saveobject>

- Елемент призначено для вибору назви об’єкта &R; для збереження даних (тобто об’єкта, якого, загалом, ще не існує, на відміну від varslot):

  `label`

- Мітка поля введення (необов’язкова, типовим є значення «Save to:»)

`initial`

- Початковий текст у полі введення (необов’язковий, типовим значенням є «my.data»)

`required`

- Визначає для надсилання коду, чи є обов’язковою наявність у полі прийнятної назви об’єкта. Див. документацію до властивості required (необов’язкова, типовим значенням є true).

`checkable`

- У багатьох випадках збереження до об’єкта &R; є необов’язковим. У таких випадках поле для позначки можна інтегрувати до елемента saveobject за допомогою цього атрибута. Якщо для нього встановлено значення true, saveobject буде активовано або деактивовано цим полем для позначки. Див. документацію щодо властивості active saveobject (необов’язковий, типовим значенням є false).

`checked`

- Лише для saveobject з позначкою: визначає, чи буде пункт позначено типово (необов’язковий, типовим значенням є false (не позначено))

<spinbox>

- Поле лічильника, у яке користувач може або безпосередньо ввести числове значення, або скористатися для того, щоб вказати значення, маленькими стрілочками вгору і вниз ліворуч від поля значення. Атрибути:

  `label`

- Мітка поля лічильника (рекомендуємо вказати, типовим значенням є «Enter value:»)

`min`

- Найменше значення, яке користувач має право ввести до поля лічильника (необов’язкове, типовим значенням є найменше значення, яке технічно може бути показано у полі лічильника).

`max`

- Найбільше значення, яке користувач має право ввести до поля лічильника (необов’язкове, типовим значенням є найбільше значення, яке технічно може бути показано у полі лічильника).

`initial`

- Початкове значення, яке буде показано у полі лічильника (необов’язкове, типовим значенням є «0»)

`type`

- Одне зі значень: "real" або "integer". Визначає, можна у полі лічильника вказувати дійсні числа чи лише цілі (необов’язковий аргумент, типовим значенням є "real")

`default_precision`

- Має значення, лише якщо поле лічильника належить до типу «real». Впливає на кількість десяткових цифр, які може бути показано у полі лічильника (саме цю кількість кінцевих нулів буде показано). Після натискання користувачем кнопочки зі стрілкою вгору або вниз, ці десяткові знаки буде змінено. Втім, користувач може вручну ввести і значення із вищою точністю (див. нижче) (необов’язковий, типовим є значення «2»).

`max_precision`

- Максимальна кількість цифр, які може бути введено (необов’язковий аргумент, типовим є значення «8»)

<formula>

- За допомогою цього елемента із розширеними можливостями користувач може вибрати формулу або набір взаємодій на основі вибраних змінних. Наприклад, для узагальненої лінійної моделі користувач може вказати елементи взаємодії у моделі. Атрибути:

  `fixed_factors`

- Ідентифікатор varslot, що містить вибрані фіксовані фактори (обов’язковий)

`dependent`

- Ідентифікатор varslot, що містить вибрану залежну змінну (обов’язковий)

<embed>

- Вбудовування іншого додатка у поточний (див розділу щодо вбудовування). Атрибути:

  `component`

- Зареєстрована назва компонента для вбудовування (див. розділ щодо реєстрування компонентів) (обов’язкова)

`as_button`

- Якщо встановлено значення «true», у графічному інтерфейсі, до якого вбудовується графічний інтерфейс, буде показано лише кнопку, натискання якої відкриватиме (у окремому вікні) вбудований інтерфейс (необов’язковий, типовим значенням є «false»).

`label`

- Має значення, лише якщо as_button="true": мітка кнопки (рекомендуємо вказати, типовою є мітка "Options")

<preview>

- Поле для позначки для вмикання або вимикання функціональної можливості попереднього перегляду. Зауважте, що починаючи з версії 0.6.5 &rkward; елементи попереднього перегляду, `<preview>`, виокремлюються у діалогових вікнах додатків (не майстрів): вони розташовуються у стовпчику з кнопками, незалежно від того, де їх було визначено у описі графічного інтерфейсу. Втім, варто визначати їх у відповідному місці компонування з міркувань зворотної сумісності. Атрибути:

  `label`

- Мітка панелі (необов’язкова, типовим є значення "Preview")

`mode`

- Тип попереднього перегляду. Підтримувані типи: «plot» (див. розділ щодо попереднього перегляду графіків), «output» (див. розділ щодо попереднього перегляду виведених даних (HTML)), «data» (див. розділ щодо попереднього перегляду даних) і «custom» (див. розділ щодо нетипових попередніх переглядів) (необов’язковий, типовим є тип «plot»)

`placement`

- Розташування області попереднього перегляду: «attached» (у основній робочій області), «detached» (у окремому вікні), «docked» (у діалоговому вікні додатка) і «default» (у поточній версії те саме, що і «docked», але може стати чимось визначеним користувачем у майбутньому). Загалом, рекомендуємо лишити типовий варіант з міркувань збереження однорідності графічного інтерфейсу (необов’язковий, типовим є значення «default»).

`active`

- Визначає, чи буде панель попереднього перегляду типово активною. Загалом, типово варто робити активними лише панелі попереднього перегляду у вікні додатка (docked), і навіть для цих панелей є причина не робити їх активними (необов’язковий, типовим значенням є «false»).

#### Розділ логіки

<logic>

- Елемент, що визначає розділ «logic». Усі наведені нижче елементи можна використовувати лише всередині елемента <logic>. Елемент <logic> можна використовувати лише як безпосередній дочірній елемент елемента <document> (не більше одного на документ) або елемента <optionset> (не більше одного на optionset). Розділ logic документа одночасно стосується графічних інтерфейсів <dialog> і <wizard>.

<external>

- Створює (рядкову) властивість, яка призначається для з’єднування із зовнішньою властивістю, якщо додаток вбудовують. Див. розділ щодо «незавершених» додатків. Атрибути:

  `id`

- Ідентифікатор нової властивості (обов’язковий)

`default`

- Типове рядкове значення нової властивості, тобто значення, яке використовується, якщо властивість не з’єднано із зовнішньою властивість (необов’язкове, типовим значенням є порожній рядок).

<i18n>

- Створює нову (рядкову) властивість, яка має забезпечувати роботу придатної до перекладу мітки. Атрибути:

  `id`

- Ідентифікатор нової властивості (обов’язковий)

`label`

- Мітка. Її можна буде перекладати. (обов’язкова)

<set>

- Встановлює для властивості фіксоване значення (звичайно ж, якщо ви додатково з’єднаєте властивість із якоюсь іншою властивістю, значення не залишатиметься фіксованим). Наприклад, якщо вами вбудовано додаток, але ви хочете приховати якісь з його елементів, ви можете встановити для властивості «visibility» цих елементів значення «false». Це особливо корисно для вбудованих додатків та додатків, до яких відбувається вбудовування. Зауваження: якщо для одного `id` вказано декілька <set>, пріоритет матиме останнє з визначень. Це іноді буває корисним, якщо використовуються фрагменти коду за допомогою <include>. Атрибути:

  `id`

- Ідентифікатор властивості для встановлення (обов’язковий)

`to`

- Рядкове значення, яке слід встановити для властивості to (обов’язкове). Зауваження: для булевих властивостей, зокрема видимості, увімкненості, вам типово слід встановити для атрибута або to="true" або to="false".

<convert>

- Створити нові булеві властивості, які залежать від стану однією або декількох різних властивостей. Атрибути:

  `id`

- Ідентифікатор нової властивості (обов’язковий)

`sources`

- Ідентифікатори властивостей, від яких залежатиме ця властивість. Можна вказати одну властивість або декілька властивостей, відокремлених крапками з комами, «;» (обов’язковий).

`mode`

- Режим перетворення або дії. Одне з таких значень: «equals», «notequals», «range», «and», «or». У режимі equals властивість матиме значення «true», лише якщо значення обох операндів дорівнюють атрибуту «standard» (див. нижче). У режимі notequals властивість матиме значення «true», лише якщо значення усіх операндів буде відмінним від атрибута «standard» (див. нижче). У режимі «range» усі операнди мають бути числовими (цілими або дійсними значеннями). Властивість матиме значення «true», лише якщо усі операнди належатимуть діапазону, що визначається атрибутами min і max (див. нижче). У режимі «and» операнди мають бути булевими властивостями. Властивість-результат матиме значення «true», лише якщо усі операнди одночасно дорівнюють «true». У режимі «or» усі операнди мають бути булевими властивостями. Властивість-результат матиме значення «true», якщо принаймні один з операндів матиме значення «true». (обов’язковий)

`standard`

- Має значення лише у режимах equals або notequals: рядкове значення з яким слід виконати порівняння (обов’язковий, якщо використано один з цих режимів).

`min`

- Має значення лише у режимі range: мінімальне значення, з яким слід виконувати порівняння (необов’язкове, типовим є найменше число із рухомою крапкою, яке може бути представлено на комп’ютері).

`max`

- Має значення лише у режимі range: максимальне значення, з яким слід виконувати порівняння (необов’язкове, типовим є найбільше число із рухомою крапкою, яке може бути представлено на комп’ютері).

`require_true`

- Якщо встановлено значення «true», властивість стане обов’язковою і вважатиметься встановленою коректно, якщо її станом буде true/увімкнено. Отже, якщо властивість має значення false, натискання кнопки Надіслати блокуватиметься (необов’язкова, типовим значенням є «false»).

  Якщо ви використовуєте цей атрибут, переконайтеся, що користувач зможе легко визначити, що слід робити, наприклад, покажіть йому пояснювальний текст за допомогою <text>.

<switch>

- Створити нову властивість, яку буде пов’язано із різними іншими властивостями (або сталими рядками) на основі умов щодо певного значення властивості. Надає змогу створювати логічні конструкції, подібні до `if()` або `switch()`. Атрибути:

  `id`

- Ідентифікатор нової властивості (обов’язковий)

`condition`

- Ідентифікатор властивості condition (обов’язковий)

Дочірні елементи:

<true>

- Властивість, що визначає виконання умови, є булевою, ви можете вказати два дочірні елементи <true> і <false> (і лише ці елементи). (Обов’язковий, якщо також вказано <false>)

<false>

- Якщо властивість, що визначає виконання умови, є булевою, ви можете вказати два дочірні елементи <true> і <false> (і лише ці елементи). (Обов’язковий, якщо також вказано <true>)

<case>

- Якщо властивість в умові не є булевою, ви можете вказати довільну кількість елементів <case>, по одному на кожне значення властивості (обов’язково слід вказати принаймні один такий елемент, якщо властивість в умові не є булевою).

<default>

- Якщо властивість, яка визначає умову, не є булевою, поведінку у випадку, якщо жоден з елементів <case> не відповідає значенню властивості в умові, можна визначити за допомогою додаткового елемента <default>. (необов’язковий, можна використовувати лише один раз у поєднанні із одним або декількома елементами <case>)

Дочірні елементи <true>, <false>, <case> і <default> приймають такі атрибути:

`standard`

- Лише для елементів <case>: значення, з яким слід порівнювати властивість умови (обов’язковий, рядок).

`fixed_value`

- Фіксований рядок, який має бути надано як значення властивості <switch>, якщо справджується поточна умова (обов’язковий, якщо не вказано dynamic_value).

`dynamic_value`

- Ідентифікатор `id` властивості призначення, який має бути надано як значення властивості <switch>, якщо справджується поточна умова (обов’язковий, якщо не вказано fixed_value).

<connect>

- З’єднує дві властивості. Клієнтську властивість буде змінено при зміні керівної властивості (але не навпаки!). Атрибути:

  `client`

- Ідентифікатор клієнтської властивості, тобто властивості, яку буде скориговано (обов’язковий)

`governor`

- Ідентифікатор керівної властивості, тобто властивості, яка змінює клієнтську властивість. Може включати модифікатор (обов’язковий)

`reconcile`

- Якщо має значення «true», клієнтська властивість скоригує керівну властивість під час з’єднання так, щоб керівна властивість приймала лише ті значення, які є прийнятними для клієнтської (наприклад, припустімо, що керівна властивість є числовою із мінімальним значенням «0», а клієнтська — числовою властивістю із мінімальним значенням «100». Мінімальне значення обох властивостей стане рівним 100, якщо reconcile="true"). Загалом, працює лише для властивостей, які належать до одного базового типу (необов’язковий, типовим значенням є «false»).

<dependency_check>

- Створює булеву властивість, яка має значення true, якщо вказані залежності задоволено, і значення false, якщо це не так. Синтаксис xml цього елемента є таким самим, як і у елемента `<dependencies>`, описаного у довіднику щодо &pluginmap;. У версії &rkward; 0.6.1, до уваги беруться лише специфікації версій &rkward; і &R;, а не залежності від пакунків або pluginmap-ів.

<script>

- Визначає код скрипту для керування логікою графічного інтерфейсу. Докладніший опис можна знайти у розділі щодо керування логікою графічного інтерфейсу за допомогою скриптів. Код скрипту, який слід виконати, може бути подано або за допомогою атрибута `"file"`, або як (коментований) текст у елементі. Елемент `<script>` не можна використовувати у розділі `<logic>` optionset. Атрибути:

  `file`

- Назва файла скрипту. (обов’язкова)

### Властивості елементів додатка

Усі елементи компонування і усі активні елементи мають вказані нижче властивості, доступ до яких можна отримати за допомогою синтаксичної конструкції «ідентифікатор_елемента.назва_властивості»:

visible

- Визначає, чи є видимим елемент графічного інтерфейсу (boolean)

enabled

- Визначає, чи увімкнено елемент графічного інтерфейсу (boolean)

required

- Визначає, чи є елемент графічного інтерфейсу обов’язковим (чи повинен отримати коректне значення). Зауважте, що будь-який елемент, який вимкнено чи приховано, неявним чином є необов’язковим. (булеве значення)

Крім того, деякі елементи мають додаткові властивості для з’єднання. У більшості активних елементів є також властивість «default», чиє значення буде повернуто у відповідь на виклики `getBoolean/getString/getList ("...")`, якщо не вказано певної властивості за назвою, як це описано нижче.

<text>

- Типовою є властивість «text»

  text

- Показаний текст (text)

<varselector>

- Немає типової властивості

  selected

- Поточні позначені об’єкти. Ймовірно, цим не слід користуватися. Використовується для внутрішніх потреб (RObject)

root

- Кореневий або батьківський об’єкт об’єктів, які пропонуються до вибору (RObject)

<varslot>

- Типовою є властивість «available»

  available

- Усі об’єкти, що зберігаються у varslot (RObject)

selected

- З об’єктів, які містяться у varslot, ті, які позначено. Ймовірно, цим не слід користуватися. Використовується для внутрішніх потреб (RObject)

source

- Копія об’єктів, позначених у відповідному varselector. Ймовірно, цим не слід користуватися. Використовується для внутрішніх потреб (RObject)

<valueselector>

- Типовою є властивість «selected»

  selected

- Поточні позначені рядки. Скористайтеся модифікатором «labeled», щоб отримати відповідні мітки. У <valueselector> безпосередньо цим, ймовірно, користуватися не слід (лише у <select>). (читання і запис StringList)

available

- Список рядкових значень, з якого слід вибирати (StringList, читання-запис)

labels

- Мітки, які слід показувати для значень рядків. (StringList, читання-запис)

<valueslot>

- Те саме, що і <varslot>, але властивостями є списки рядків, а не RObject-и.

<radio>

- Типовою є властивість «string»

  string

- Значення поточного позначеного пункту (string)

number

- Номер поточного позначеного пункту (пункти нумеруються згори вниз, починаючи з 0) (integer)

<dropdown>

- Те саме, що і <radio>

<select>

- Те саме, що і <valueselector>

<option>

- Не має типової властивості. «enabled» є єдиною властивістю, і у поточній версії ця властивість недоступна для параметрів всередині <select> або <valueselector>. <option> не має властивостей «visible» і «required».

  enabled

- Визначає, чи має бути цей пункт увімкнено. Втім, у більшості випадків його зміна вмикає або вимикає увесь список <radio< або <dropdown<. Попри це, може бути використано для динамічного встановлення окремого пункту у <radio< або <dropdown< (булеве значення).

<checkbox>

- Типовою властивістю є «state.labeled», що означає, що повертаються значення, вказані атрибутами `value` і `value_unchecked`, а не показана мітка поля для позначки.

  state

- Стан поля для позначки (позначено чи ні). Зауважте, що для цієї властивості (як і для усіх булевих властивостей) можна використовувати модифікатори «not» і «labeled» (див. типи властивостей). Втім, найкориснішим варіантом є з’єднання властивості без жодних модифікаторів, тобто варіант «ідентифікатор_поля_для_позначки.state», за якого буде повернуто стан поля у форматі, зручному для використання у інструкції if (0 або 1). (булевий тип)

<frame>

- Типовою властивістю є «checked», якщо і лише якщо для рамки передбачено властивість позначення. Для рамок без позначок типової властивості немає.

  checked

- Доступна лише для придатних до позначення рамок: стан позначки (позначено чи ні). Зауважте, що для цієї властивості (як і для усіх булевих властивостей) можна використовувати модифікатори «not» та «numeric» (див. типи властивостей). (булевий тип)

<input>

- Типовою є властивість «text»

  text

- Поточний текст у полі для введення (string)

<matrix>

- Типовою властивістю є «cbind».

  rows

- Кількість рядків у матриці (integer). Якщо матриця дозволяє додавання або вилучення рядків користувачем, цю властивість слід вважати придатною лише для читання. Якщо ж це не так, зміна значення цієї властивості призводитиме до зміни розміру матриці.

columns

- Кількість стовпчиків у матриці (integer). Якщо матриця дозволяє додавання або вилучення стовпчиків користувачем, цю властивість слід вважати придатною лише для читання. Якщо ж це не так, зміна значення цієї властивості призводитиме до зміни розміру матриці.

tsv

- Дані у матриці у форматі tsv (рядок; читання і запис). Зауважте, що порівняно зі звичайним компонуванням tsv, символами нового рядка відокремлено стовпчики, а не рядки, а комірки у одному стовпчику відокремлено символами табуляції.

0,1,2...

- Дані з окремого стовпчика ( для найвищого рядка) `getValue()`/`getString()` повертає це як єдиний рядок, відокремлений «\n». Втім, рекомендованим способом отримання є використання функції `getList()`, яка повертає цей стовпчик як масив рядків.

row.0,row.1,row.2...

- Дані з окремого рядка (0 для найвищого рядка). `getValue()`/`getString()` повертає це як єдиний рядок, відокремлений «\n». Втім, рекомендованим способом отримання є використання функції `getList()`, яка повертає цей рядок як масив рядків.

cbind

- Дані у форматі, придатному до вставляння до &R; у обгортці інструкції cbind (string; лише читання).

<optionset>

- Немає типової властивості.

  row_count

- Кількість пунктів у наборі пунктів (integer). Можна лише читати.

current_row

- Поточний активний пункт у наборі пунктів (integer). -1, якщо немає активного пункту. Можна читати і записувати.

optioncolumn_ids

- Для кожної визначеної вами <optioncolumn> буде створено властивість типу списку рядків із вказаним ідентифікатором.

<browser>

- Типовою властивістю є «selection»

  selection

- Поточний текст (назва позначеного файла) у навігаторі файловою системою (string)

<saveobject>

- Типовою властивістю є «selection»

  selection

- Назва позначеного об’єкта повністю (string; лише для читання, щоб встановити програмно, скористайтеся «parent» і «objectname»)

parent

- Батьківський об’єкт позначеного об’єкта. Це завжди наявний об’єкт &R; типу, який може містити інші об’єкти (наприклад list або data.frame). Якщо вказано порожній рядок або некоректний об’єкт, використовується «.GlobalEnv» (RObject).

objectname

- Базова назва позначеного об’єкта, тобто рядок, введений користувачем (буде змінено до коректної назви &R;, якщо потрібно) (string)

active

- Лише для saveobject з позначкою: визначає, чи позначено пункт. Завжди має значення true для saveobject без пункту позначки. (булеве значення)

<spinbox>

- Типовою є властивість «int» або «real.formatted» залежно від режиму роботи лічильника

  int

- Ціле значення, що міститься у полі лічильника, або найближче ціле, якщо лічильник працює у режимі дійсних чисел (integer)

real

- Дійсне значення, що міститься у полі лічильника (або ціле значення, якщо лічильник для цілих чисел) (real)

<formula>

- Типовою властивістю є «model»

  model

- Рядок поточної моделі (string)

table

- data.frame, що містить потрібні змінні. Якщо використано змінні лише з одного data.frame, буде повернуто назву цього data.frame. Якщо ж це не так, буде побудовано новий data.frame із відповідними параметрами (рядок).

labels

- Якщо використовуються змінні з декількох data.frames, програма може сплутати їхні назви (наприклад, якщо обидва data.frame містять змінну із назвою «x»). Це повертає список з неоднозначними назвами як індексами та описову мітку як значення (рядок).

fixed_factors

- Фіксовані фактори. Ймовірно, цим не слід користуватися. Використовується для внутрішніх потреб (RObject)

dependent

- Залежні змінні. Ймовірно, цим не слід користуватися. Використовується для внутрішніх потреб (RObject)

<embed>

- Немає типової властивості

  code

- Код, створений вбудованим додатком (code)

<preview>

- Типовою властивістю є «state»

  state

- Визначає, чи позначено пункт попереднього перегляду (не обов’язково, чи вже показано попередній перегляд) (boolean)

<convert>

- Цей елемент (використовується у розділі <logic>) є особливим, оскільки з технічної точки зору це одна (рядкова) властивість, а не комплект зі однієї або декількох властивостей. Він належить до булевого типу. Зауважте, що придатними до використання модифікаторами цієї властивості (які і усіх булевих властивостей) є «not» і «numeric» (див. типи властивостей).

<switch>

- Цей елемент (використовується у розділі <logic>) є особливим, оскільки з технічної точки зору це одна (рядкова) властивість, а не комплект зі однієї або декількох властивостей. Він надає змогу перемикатися між декількома властивостями-цілями, залежно від значення властивості в умові, або змінювати прив’язку властивості в умові. Усі вказані вами модифікатор буде передано властивостям-цілям. Отже, якщо, наприклад, усі властивості-цілі є властивостями RObject, ви можете також використовувати для перемикання модифікатор «shortname». Втім, якщо властивості-цілі належать до різних типів, використання модифікаторів може призвести до помилок. Для `fixed_value` усі модифікатори без попередження буде відкинуто. Зауважте, що під час доступу до властивостей-цілей у switch можливе лише читання цих властивостей!

### Вбудовувані додатки, які є частиною офіційного пакунка &rkward;

Декілька придатних до вбудовування додатків постачаються разом із основною програмою &rkward;. Ви можете використовувати ці додатки у ваших власних додатках. Докладна документація щодо цих додатків у поточній версії доступна лише у початкових кодах додатків та на їхніх сторінках довідки. Втім, ось список із коротким оглядом доступних додатків:

### Стандартні вбудовувані додатки

Ідентифікатор | Pluginmap | Опис | Приклад використання
rkward::plot_options | embedded.pluginmap | Надає доступ до широкого спектру параметрів креслень. Використовується більшістю додатків для створення креслень. | Креслення -> Блокова діаграма, більшість інших додатків для креслення
rkward::color_chooser | embedded.pluginmap | Дуже простий додаток для задання кольору. У поточній реалізації надає користувачеві список назв кольорів. У майбутніх реалізаціях може надавати ширші можливості з вибору кольору. | Креслення -> Гістограма
rkward::plot_stepfun_options | embedded.pluginmap | Параметри креслення сходинкової функції | Креслення -> Креслення ECDF
rkward::histogram_options | embedded.pluginmap | Параметри гістограми (креслення) | Креслення -> Гістограма
rkward::barplot_embed | embedded.pluginmap | Параметри стовпчикової діаграми | Креслення -> Блокова діаграма
rkward::one_var_tabulation | embedded.pluginmap | Табуляція для однієї змінної. | Креслення -> Блокова діаграма
rkward::limit_vector_length | embedded.pluginmap | Обмеження на довжину вектора (до n найбільших або найменших елементів). | Креслення -> Блокова діаграма
rkward::level_select | embedded.pluginmap | Створює <valueselector>, заповнений рівнями (або неповторюваними значеннями) вектора. | Дані -> Перекодувати категоріальні дані
rkward::multi_input | embedded.pluginmap | Поєднує поле лічильника, поле введення та пункти варіантів для надання можливостей з введення символьних, числових і логічних даних. | Дані -> Перекодувати категоріальні дані

### Елементи, які можна використовувати у файлах &pluginmap;

<document>

- Має бути у будь-якому файлі &pluginmap; як кореневий вузол (лише один раз). Атрибути:

  base_prefix

- Назви файлів, вказані у файлі &pluginmap;, вважаються визначеними відносно каталогу файла &pluginmap; + префікс, вказаний вами тут. Особливо корисний, якщо усі ваші компоненти розташовано у одному підкаталозі.

namespace

- Простір назв для ідентифікаторів компонентів. Під час пошуку компонентів для вбудовування програма отримуватиме компоненти за допомогою рядка «namespace::ідентифікатор_компонента». У поточній версії встановлено у значення «rkward».

id

- Додатковий рядок ідентифікатора цієї &pluginmap;. Визначення такого ідентифікатора надасть змогу стороннім авторам посилатися на вашу &pluginmap; і завантажувати її з власних (див. розділ щодо обробки залежностей).

priority

- Одне з таких значень: `"hidden"`, `"low"`, `"medium"` або `"high"`. Файли &pluginmap; з рівнем пріоритетності «medium"» або «high» автоматично активуються, щойно їх буде вперше виявлено &rkward;. Рівнем `priority="hidden"` слід користуватися для &pluginmap;-ів, які не слід активувати, каталогів (які призначено лише для включення). Втім, у поточній реалізації це, насправді, не приховує &pluginmap;. (необов’язковий, типовим значенням є «medium»).

<dependencies>

- Цей елемент, що вказує залежності, можна використовувати як безпосередній дочірній елемент елемента <document> (лише один раз) або як дочірній елемент елементів <component> (по одному на кожен елемент <component>). Визначає залежності, які має бути задоволено для того, щоб додатком (або додатками) можна було користуватися. Огляд питань щодо залежностей наведено у відповідному розділі. Атрибути:

  rkward_min_version, rkward_max_version

- Мінімальна і максимальна дозволені версії &rkward;. Специфікація версій може включати нечислові суфікси, наприклад «0.5.7z-devel1». Якщо вказані умови залежності не виконуються, додаток, який їх використовуватиме, буде проігноровано. Докладніші відомості. Необов’язковий, якщо не вказано, вимог щодо мінімальної і максимальної версій &rkward; не висуватиметься.

R_min_version, R_max_version

- Мінімальна і максимальна дозволені версії &R;. У специфікації версій не можна включати нечислові суфікси, зокрема не можна визначати версію так: «0.5.7z-devel1». Дані щодо залежності від версії &R; буде показано на сторінках довідки додатка, але самі залежності не враховуватимуться (версія &rkward; 0.6.1). Докладніші відомості. Необов’язковий, якщо не вказано, вимог щодо мінімальної і максимальної версій &R; не висуватиметься.

Дочірні елементи:

<package>

- Додає залежність від вказаного пакунка &R;. Атрибути:

  name

- Назва пакунка (обов’язкова).

min_version, max_version

- Мінімальна або максимальна дозволена версія (необов’язкова).

repository

- Сховище, у якому зберігається пакунок. Необов’язкове, але дуже рекомендоване, якщо пакунок не можна отримати з CRAN.

<pluginmap>

- Додає залежність від вказаної &pluginmap; &rkward;. Атрибути:

  name

- Рядок-ідентифікатор потрібної &pluginmap; (обов’язковий).

min_version, max_version

- Мінімальна або максимальна дозволена версія (необов’язкова).

url

- Адреса, за якою можна знайти &pluginmap;. Обов’язкова.

<about>

- Можна використовувати лише один раз як дочірній елемент елемента <document>. Містить метаінформацію щодо &pluginmap; (або додатка). Див. розділ щодо відомостей про додаток, щоб дізнатися більше. Атрибути:

  name

- Видима назва для користувачів. Необов’язкова. Може бути іншою, ніж вказано у «id».

version

- Номер версії. Необов’язковий. Формат номера не обмежено, але щоб ним можна було користуватися, варто дотримуватися типової нумерації версій, зокрема «x.y.z».

releasedate

- Специфікація дати випуску. Необов’язкова. Формат: «РРРР-ММ-ДД».

shortinfo

- Короткий опис додатка або &pluginmap;. Необов’язковий.

url

- Адреса, за якою можна знайти додаткову інформацію. Необов’язкова, але рекомендована.

copyright

- Специфікація авторських прав, наприклад «2012-2013 by Ivan Ivanenko». Необов’язкова, але рекомендована.

licence

- Специфікація умов ліцензування, наприклад «GPL» або «BSD». Будь ласка, не забувайте додавати до ваших файлів текст відповідних умов ліцензування повністю! Необов’язкова, але рекомендована.

category

- Категорія додатків, наприклад «Item response theory». З &rkward; 0.6.1 немає попередньо визначеного жорсткого набору категорій. Необов’язкова.

Дочірні елементи:

<author>

- Додає відомості щодо автора. Атрибути:

  name, given, family

- Або вкажіть ім’я повністю за допомогою `name`, або визначте `given` (ім’я) та `family` (прізвище) окремо.

role

- Опис ролі автора (необов’язковий).

email

- Адреса електронної пошти, за допомогою якої можна зв’язатися з автором. Можна вказати адресу списку листування rkward-devel, якщо ви підписані на нього, а ваш додаток призначено для включення до офіційного випуску &rkward;.

url

- Адреса сторінки із додатковою інформацією про автора, наприклад домашньої сторінки (необов’язкова).

<components>

- Має бути використано лише один раз як безпосередній дочірній елемент елемента <document>. Містить окремі елементи <component>, які описано нижче. Не має атрибутів.

<component>

- Безпосередніми дочірніми елементами елемента <components> мають бути один або декілька елементів <component>. Їх можна використовувати лише так. Реєструє компонент або додаток у &rkward;. Атрибути:

  type

- Для подальшого розширення можливостей, тип компонента або додатка. У поточній версії завжди має значення «standard» (єдиний тип, підтримку якого зараз передбачено).

id

- Ідентифікатор, за яким можна отримати цей компонент (для розташовування його у меню (див. нижче) або для вбудовування). Див. простір назв <document> вище.

file

- Обов’язковий принаймні для компонентів з type="standard": назва файла XML з описом графічного інтерфейсу.

label

- Мітка для цього компонента, яка використовується для розташування компонента у ієрархії меню.

<attribute>

- Визначає атрибути компонента. Поки має значення лише для додатків імпортування. Можна використовувати лише як безпосередній дочірній елемент <component>. Атрибути:

  id

- Ідентифікатор атрибута

value

- Значення атрибута

labels

- Мітка, яку пов’язано з атрибутом

<hierarchy>

- Має бути використано точно один раз як безпосередній дочірній елемент елемента <document>. Описує, де у ієрархії меню має бути розташовано оголошені вище компоненти. Приймає як безпосередні дочірні елементи лише елементи <menu>. Не має атрибутів.

<menu>

- Як безпосередні дочірні елементи елемента <hierarchy> має бути вказано один або декілька елементів <menu>. Якщо меню із вказаним ідентифікатором (див. нижче) вже існує, меню буде об’єднано. Елемент <menu> можна використовувати лише як безпосередній дочірній елемент елемента <hierarchy> (меню верхнього рівня) або як безпосередній дочірній елемент іншого елемента <menu> (підменю). Сам же елемент <menu> приймає як дочірні елементи лише інші елементи <menu> або елементи <entry>. Атрибути:

  id

- Рядок-ідентифікатор меню. Є корисним, якщо визначення меню читаються з декількох файлів &pluginmap;, для забезпечення розташовування пунктів додатків у тих самих меню. Деякі ідентифікатори меню, зокрема «file» стосуються попередньо визначених типових меню (у цьому випадку на меню «Файл»). Щоб використовувати узгоджену систему ідентифікаторів пунктів меню, ознайомтеся із кодом наявних файлів &pluginmap;.

label

- Мітка меню.

group

- Надає змогу керувати упорядковуванням пунктів меню. Див. упорядковування пунктів меню. Необов’язковий.

<entry>

- Пункт меню, тобто пункт, за допомогою якого можна викликати додаток. Можна використовувати лише як безпосередній дочірній елемент елемента <menu>, не має дочірніх елементів. Атрибути:

  component

- Ідентифікатор компонента, який має бути викликано, якщо задіяно відповідний пункт меню.

group

- Надає змогу керувати упорядковуванням пунктів меню. Див. упорядковування пунктів меню. Необов’язковий.

<group>

- Оголошує групу пунктів у меню. Див. упорядковування пунктів меню. Атрибути:

  id

- Назва цієї групи.

separated

- Необов’язковий. Якщо встановлено значення «true» пункт у цій групі буде візуально відділено від навколишніх пунктів.

group

- Назва групи, до якої слід долучити цю групу (необов’язкова).

<context>

- Оголошує записи у контексті. Можна використовувати лише як безпосередній дочірній елемент вузла <document>. Приймає як дочірні елементи лише теґи <menu>. Атрибути:

  id

- Ідентифікатор контексту. Поки що реалізовано лише два контексти: «x11» і «import».

<require>

- Включити інший файл &pluginmap;. Цей файл &pluginmap; буде завантажено лише один раз, навіть якщо його буде визначено за допомогою <require> у якихось інших файлах. Найважливішим випадком використання є включення файла &pluginmap;, у якому оголошено певні компоненти, які вбудовуються компонентами, які оголошено у поточному файлі &pluginmap;. Елементи <require> можна використовувати лише як безпосередні дочірні елементи вузла <document>. Атрибути:

  file

- Назва файла &pluginmap;, який слід включити. Визначається відносно каталогу поточного файла &pluginmap; + base_prefix (див. вище у описі елемента <document>). Якщо вам невідомий відносний шлях до файла &pluginmap;, який слід включити, скористайтеся атрибутом `map` для посилання на нього за його ідентифікатором.

map

- Щоб включити файл &pluginmap; з іншого пакунка (або &pluginmap; &rkward; з вашого зовнішнього &pluginmap;), ви можете послатися на нього за його значенням `назва_простору_назв::ідентифікатор`, який вказано у елементі <document> файла &pluginmap;. Включення не відбудеться, що програма не виявить &pluginmap; з таким ідентифікатором (наприклад, його не встановлено у системі користувача). Вам слід використовувати цей метод лише для включення &pluginmap;, якого немає у вашому пакунку. Для карт у вашому пакунку швидшим і надійнішим способом є визначення відносного шляху (атрибута `file`).

### Елементи, які можна використовувати у файлах довідки .rkh

<document>

- Має бути в усіх файлах `.xml` як кореневий вузол (лише один раз). Не має атрибутів.

<title>

- Заголовок сторінки довідки. Не береться до уваги для сторінок довідки з додатків (для таких сторінок заголовком завжди буде назва самого додатка). Використовується лише для самодостатніх сторінок. Не має атрибутів. Як заголовок сторінки довідки буде використано вміст теґу <title>. Можна використовувати лише один раз як безпосередній дочірній елемент вузла <document>.

<summary>

- Коротка анотація сторінки довідки (або опис того, для чого призначено цей додаток). Цей розділ завжди буде показано на початку сторінки довідки. Не має атрибутів. Буде показано текст, що міститься у тезі <summary>. Є рекомендованим, але не є обов’язковим. Можна визначати лише один раз як безпосередній дочірній елемент вузла <document>.

<usage>

- Дещо докладніша анотація щодо користування. Завжди буде показано безпосередньо після розділу <summary>. Не має атрибутів. Буде показано текст, що міститься у тезі <usage>. Рекомендовано для сторінок довідки з додатків, але не є обов’язковим. Можна визначати лише один раз як безпосередній дочірній елемент вузла <document>.

<section>

- Розділ загального призначення. Можна використовувати довільну кількість разів як безпосередній дочірній елемент вузла <document>. Розділи, визначені цим теґом, розташовуватимуться у порядку їхнього визначення, але усі після розділу <usage> і перед розділом <settings>. Буде показано текст, що міститься у тезі <section>.

  id

- Ідентифікатор, потрібний для переходу до цього розділу з панелі навігації (або за посиланням). Має бути неповторюваним у межах одного файла. Обов’язковий, не має типового значення.

title

- Заголовок розділу. Обов’язковий, не має типового значення.

short_title

- Короткий заголовок для панелі навігації. Необов’язковий, типовим значенням є повна версія заголовка.

<settings>

- Визначає розділ, який містить довідкові дані щодо різноманітних параметрів графічного інтерфейсу. Має сенс і використовується лише для сторінок довідки, пов’язаних із додатками. Використовується як безпосередній дочірній елемент вузла <document>. Може містити як дочірні елементи лише елементи <setting> і <caption>. Не має атрибутів.

<setting>

- Стосується окремого параметра у графічному інтерфейсі. Можна використовувати лише як безпосередній дочірній елемент елемента <settings>. У інтерфейсі буде показано текст, який міститься у цьому елементі.

  id

- Ідентифікатор параметра у `.xml` додатка. Обов’язковий, не має типового значення.

title

- Додатковий заголовок параметра. Якщо не вказано (у більшості випадків рекомендовано не вказувати), заголовок буде запозичено з файла `.xml` додатка.

<caption>

- Надпис для візуального групування декількох параметрів. Можна використовувати лише як безпосередній дочірній елемент елемента <settings>.

  id

- Ідентифікатор відповідного елемента (типово <frame>, <page> або <tab>) у файлі `.xml` додатка.

title

- Додатковий заголовок надпису. Якщо не вказано (у більшості випадків рекомендовано не вказувати), заголовок буде запозичено з файла `.xml` додатка.

<related>

- Визначає розділ, що містить посилання на додаткову пов’язану з темою інформацію. Завжди буде показано після розділу <settings>. Не має атрибутів. Буде показано текст, що міститься у тезі <related>. Типово, там має міститися список у форматі &HTML;. Рекомендовано для сторінок довідки з додатків, але не є обов’язковим. Можна визначати лише один раз, як безпосередній дочірній елемент вузла <document>.

<technical>

- Визначає розділ, що містить технічні дані, які не потрібні кінцевому користувачеві (зокрема про внутрішню структуру додатка). Цей розділ на сторінці довідки завжди буде показано останнім. Не має атрибутів. Показано буде текст, що міститься всередині теґу <related>. Не є обов’язковим і не рекомендується для більшості сторінок довідки з додатків. Можна визначати лише один раз як безпосередній дочірній елемент вузла <document>.

<link>

- Посилання. Може бути використано у будь-якому з описаних вище розділів.

  href

- Адреса посилання. Зауважте, що можна використовувати декілька специфічних для &rkward; адрес. Див. розділ щодо написання сторінок довідки, щоб дізнатися більше.

<label>

- Вставляє значення мітки інтерфейсу користувача. Може бути використано у будь-якому з описаних вище розділів.

  id

- Ідентифікатор елемента у додатку, з якого слід скопіювати атрибут `label`.

<різноманітні теґи &HTML;>

- У цих розділах можна використовувати більшість теґів &HTML;. Втім, не слід зловживати форматуванням вручну.

### Функції для керування логікою графічного інтерфейсу за допомогою скриптів

Клас "Component"

- Клас, який відповідає одному компоненту або властивості компонента. Найважливішим екземпляром цього класу є змінна «gui», яку попередньо визначено як кореневу властивість поточного компонента. Для екземплярів класу «Component» доступні такі методи:

  absoluteId(base_id)

- Повертає абсолютний ідентифікатор base_id або, якщо базовий ідентифікатор base_id не вказано, ідентифікатор компонента.

getValue(ідентифікатор)

- Не рекомендовано. Навзамін слід користуватися `getString()`, `getBoolean()` або `getList()`. Повертає значення вказаної дочірньої властивості. Повертає значення поточної властивості, якщо ідентифікатор не вказано.

getString(ідентифікатор)

- Повертає значення вказаної дочірньої властивості у форматі рядка. Повертає значення поточної властивості, якщо ідентифікатор не вказано.

getBoolean(ідентифікатор)

- Повертає значення вказаної дочірньої властивості у форматі булевого значення (якщо це можливо). Повертає значення поточної властивості, якщо ідентифікатор не вказано.

getList(ідентифікатор)

- Повертає значення вказаної дочірньої властивості у форматі масиву рядків (якщо це можливо). Повертає значення поточної властивості, якщо ідентифікатор не вказано.

setValue(ідентифікатор, значення)

- Встановити вказане значення дочірньої властивості.

getChild(ідентифікатор)

- Повертає екземпляр дочірньої властивості із вказаним ідентифікатором.

addChangeCommand(ідентифікатор, команда)

- Виконати команду кожного разу, коли вносяться зміни до дочірньої властивості ідентифікатор.

Клас "RObject"

- Клас, який відповідає одному окремому об’єкту &R;. Екземпляр цього класу можна отримати за допомогою команди `makeRObject(назва_об’єкта)`. Для екземплярів класу RObject доступні такі методи:

  Якщо у черзі модуля обробки є якісь команди, дані, які може бути отримано за допомогою цих методів, можуть бути застарілими на час запуску коду додатка. Не покладайтеся на них, якщо це критично (існує ризик втрати даних).

  getName()

- Повертає абсолютну назву об’єкта.

exists()

- Повертає true, якщо об’єкт існує. Вам слід виконати таку перевірку, перш ніж використовувати методи з наведеного нижче списку.

dimensions()

- Повертає масив розмірностей (подібна до команди `dim()` у R).

classes()

- Повертає масив класів (подібна до команди `class()` у R).

isClass(клас)

- Повертає true, якщо об’єкт є класом клас.

isDataFrame()

- Повертає true, якщо об’єкт належить до типу data.frame.

isMatrix()

- Повертає true, якщо об’єкт є матрицею.

isList()

- Повертає true, якщо об’єкт є списком.

isFunction()

- Повертає true, якщо об’єкт є функцією.

isEnvironment()

- Повертає true, якщо об’єкт є середовищем.

isDataNumeric()

- Повертає true, якщо об’єкт є вектором числових даних.

isDataFactor()

- Повертає true, якщо об’єкт є вектором даних факторів.

isDataCharacter()

- Повертає true, якщо об’єкт є вектором символьних даних.

isDataLogical()

- Повертає true, якщо об’єкт є вектором булевих даних.

parent()

- Повертає екземпляр RObject, який є батьківським щодо цього об’єкта.

child(назва дочірнього об’єкта)

- Повертає екземпляр RObject, що відповідає дочірньому об’єкту назва дочірнього об’єкта поточного об’єкта.

Клас "RObjectArray"

- Масив екземплярів RObject. Екземпляр цього класу можна отримати за допомогою команди `makeRObjectArray(назви об’єктів)`. Може бути корисним при роботі з varslot, у яких можна вибирати декілька об’єктів.

Функція include()

- `include(назва файла)` можна скористатися для включення окремого файла JS.

Функція doRCommand()

- Функцією `doRCommand(команда, зворотній виклик)` можна скористатися для отримання від &R; інформації. Будь ласка, ознайомтеся із розділом щодо отримання даних &R; з додатка, щоб дізнатися більше.

## Діагностика проблем при розробці додатків

Отже, ви ознайомилися з усією документацією, зробили все як слід, і все ж воно не працює? Не хвилюйтеся — ми зможемо з усім розібратися. По-перше, слід зробити ось що: активуйте вікно Діагностичні повідомлення &rkward; (це можна зробити за допомогою меню Вікна або клацання правою кнопкою миші на одній з панелей інструментів), а потім запустіть ще раз ваш додаток. Зазвичай, у вікні повідомлень після виклику вашого додатка або інших дій ніяких повідомлень не з’являтиметься. Якщо з’явилися повідомлення, ймовірно, їх пов’язано із роботою вашого додатка. Можливо, вони допоможуть вам розібратися із проблемами.

Якщо у консолі усе добре, спробуйте підвищити рівень діагностики (з командного рядка, за допомогою команди `rkward --debug-level 3`, або встановивши для рівня діагностики значення 3 на сторінці Параметри Налаштувати &rkward; Діагностика). Не усі повідомлення, які буде показано на високих рівнях діагностики, обов’язково свідчать про проблеми, але, може бути, серед них є і повідомлення, які вкажуть на джерело проблеми.

Якщо ви попри усе не можете розібратися з тим, де помилка, не зневірюйтеся. Ми знаємо, що це не проста справа, і, крім усього, причиною може бути просто вада у &rkward;, і для вирішення треба її виправити у &rkward;. Просто повідомте про свої проблеми до списку листування розробників. Ми будемо раді вам допомогти.

Нарешті, навіть якщо ви в усьому розібралися самі, але вважаєте, що у цій документації чогось немає, або вона є навіть помилковою у певних аспектах, повідомте нам про це за допомогою списку листування розробників, щоб ми могли виправити або поліпшити документацію.

## Умови ліцензування

Переклад українською: Юрій Чорноіван yurchor@ukr.net

&underFDL;
&documentation.index;