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

Іноді виникає потреба у повторенні набору параметрів для довільної кількості пунктів. Наприклад, припустімо, що вам хочеться створити додаток для упорядковування 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. Краще створити додаток, який робитиме одне креслення, щоб користувач міг викликати його декілька разів з різними параметрами.

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