10. ОБЩЕНИЕ С ПОЛЬЗОВАТЕЛЕМ

Любая программа для своей работы нуждается в получении данных от пользователя. Также она должна сообщать пользователю результаты и состояние процесса выполнения операций. Данные от пользователя обычно разделяют на два типа. Данные первого типа условно назовем таблицами. Это, как правило, система чисел, слов, картинок, имеющая некоторую структуру, иногда достаточно сложную, и записанная в файлы. Данные второго типа условно назовем инструкциями. Это указания программе какие вычисления надо проводить, какие таблицы записать и что нужно делать с уже имеющимися таблицами. В первых языках программирования, написанных для компьютеров без экрана, инструкции также записывались в специальные текстовые файлы, либо в саму программу. Такой способ и сейчас используется и даже иногда является достаточно удобным. Например, одна программа может генерировать таблицы и одновременно инструкции для другой программы, которая работает сразу за ней. Вторая программа прочитывает инструкции, преобразует таблицы и точно так же передает весь арсенал третьей программе. В этом случае пользователь участвует только в самом начале, после чего программы общаются между собой автоматически.

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

Что касается языка ACL, то в нем таких средств пока немного, но все необходимое есть. Возможно со временем их будет больше, если мне что-то понадобится. Существующие средства мы как раз и обсудим в этом разделе. Первая команда такого типа уже рассмотрена нами в разделе 4. Это #m (message). Она показывает форматированные тексты с определенной информацией и иногда просит пользователя сделать выбор, нажав на определенные кнопки. К операциям общения с пользователем относятся также операции edit, html и choo команды #f (file). Первая из них предлагает набрать текст в редакторе, вторая показывает информацию в виде форматированного html-текста со ссылками, а третья предлагает выбрать файл, одновременно показывая какие файлы есть на компьютере. В этом разделе мы рассмотрим еще пять команд такого типа. Первая команда #select или

.

 #sel [nx=; ny=; mo=; wid=; hei=; tfo=; tki=; tsi=; col=; emp=; xs=; ys=;] FT FT.

Эта команда открывает новую панель, показывающую прямоугольную таблицу кнопок. Число кнопок в одном ряду задается параметром [nx], а число рядов - параметром [ny]. Команда предлагает пользователю сделать выбор одного варианта из многих вариантов кликнув на одной кнопке из многих кнопок. Панель имеет заголовок, который определяется первым аргументом FT. Второй аргумент FT содержит имена всех кнопок. Имена внутри FT разделяются символом вертикальной черты [ | ]. Имена кнопок сначала заполняют первый ряд, затем второй и т. д. Есть несколько модификаций работы программы. Если [mo=2;], то кнопки задаются картинками из файлов с расширением png, которые ищутся в "рабочей" папке. Не забывайте правильно определить "рабочую" папку перед использованием команды. Но можно использовать и сложные имена типа (папка/файл). В этом случае именами кнопок являются имена файлов, но без расширения. Например, "run" означает файл "run.png" в текущей папке.

Если [mo=1;], то ситуация аналогичная, только предполагается, расширение файлов jpg. Если [mo=0;], то именами всех кнопок являются тексты, которые показываются внутри прямоугольника некоторого размера, окрашенного в некоторый цвет. В этом случае определение параметра [col=j;] означает, что j равно индексу элемента массива цветов (см. об этом в главе 14), который задает номер цвета текста (стандартно 255), следующий элемент этого массива задает цвет фона (прямоугольника). Массив цветов может быть переопределен командой #color. Параметры [wid] и [hei] определяют размер прямоугольника в пикселах экрана. Параметр [tsi] задает размер текста. Когда пользователь кликает одну из кнопок, панель исчезает и переменная [&] становится равной номеру выбранной кнопки. Если окно закрывается крестиком, то получаем [&]=-1. Программист может использовать эту информацию по своему усмотрению. Как правило, после этой команды стоит серия условных команд #case .... #end | , которая обрабатывает каждое значение переменной [&] из нужного диапазона.

До 2006 года таблица кнопок устанавливалась автоматически в середине экрана. Затем был введен новый параметр [emp] (enhanced mode parameter), стандартное значение которого всегда равно нулю. В этом случае действует старый режим для совместимости с ранее написанными программами. Если его значение отлично от нуля, то положение таблицы кнопок определяется параметрами [xs] и [ys], а именно, они задают смещение верхнего левого угла панели кнопок. При этом, если [emp=1;], то отсчет идет от верхнего левого угла экрана, а если [emp=2;], то отсчет идет от левого верхнего угла главного окна программы. Для среды разработки оба режима совпадают, но для специального варианта интерпретатора, работающего в режиме проигрывателя одной программы (см. главу 25) это не так. В нем положение и размер основного окна задается самой ACL программой, но только в самом начале. Если пользователь перенесет окно программы на экране, то окно команды все равно будет устанавливаться относительно начального положения окна. Это недоработка, поэтому такой режим надо использовать в крайнем случае. Иногда возникает желание спрятать основное окно программы. Для этого тоже лучше использовать режим [emp=1;]. При изменении параметра [emp] не забывайте обнулять его после выполнения команды.

После 2007-го года текст на кнопках кроме параметра [tsi] определяется также параметрами [tfo] и [tki]. Эти параметры имеют тот же самый смысл, что и в операции рисования текстов команды #g (см. главу 14), то есть [tfo]=1,2,3,4,5, а [tki]=0,1,2,3. После 2012-го года появился также новый режим [mo=3;] для специального варианта интерпретатора. В этом случае кнопки определяются картинками в png формате, которые надо ставить внутрь самого интерпретатора в папку [com.vk]. Имена файлов относительно этой папки надо писать без расширения. Если все файлы сгруппированы в отдельной папке, то ее надо писать явно, например, 1/01 -- это файл 01.png в папке [1] внутри папки [com.vk]. Это удобно, если основное окно программы спрятано, а окно Select является основным окном программы. При этом картинки можно пользователю не показывать, он даже не будет знать о их существовании. Кроме того, есть специальный режим, когда первый аргумент FT задает слово "null". В этом случае окно программы выводится совсем без рамки. Закрыть такое окно можно только по кнопке, которую должен предусмотреть сам программист.

В старых версиях JRE если текстов для кнопок было мало, то ошибка не фиксировалась. Сейчас необходимо обязательно указать все тексты для всех кнопок, даже и пустых. С картинками это было очевидно, а с текстами нет. И по этой причине некоторые программы, написанные давно, перестали работать. Нужно исправить текст программы и добавить текстов.

Вторая полезная команда #inp (input) открывает новую панель, на которой в определенном порядке расположены окна ввода с комментариями.

.

 #inp [n=; le=; mo=; emp=; xs=; ys=;] FT FT FT ...

Каждое окно ввода позволяет ввести одну строку текста. Число строк определяется параметром [n]. Простейший случай [n=1;] с одним окном ввода. В этом случае панель имеет заголовок, определяемый первым аргументом FT. Комментарий к окну задается вторым аргументом FT. Наконец, третий аргумент FT содержит начальный текст, который будет введен в это окно ввода. Но если [n] > 1, то возможны две модификации задания комментариев и текстов. Если [mo] - четное число (0,2,...), то 2-й аргумент FT определяет первый комментарий, 3-й аргумент FT определяет первый текст, 4-й аргумент FT определяет второй комментарий, 5-й аргумент FT определяет второй текст и так далее. Так что в этом случае каждой аргумент FT определяет один комментарий или текст. В противоположном случае, если [mo] - нечетное число (1,3,...), то 2-й аргумент FT определяет все комментарии, отделяемые один от другого символом вертикальной черты [ | ], а 3-й аргумент FT определяет все тексты отделяемые таким же способом.

Есть также несколько модификаций размещения комментариев и окон ввода на панели. Если [mo] = 0,1, то каждый комментарий и каждое окно ввода размещаются на новой строке сверху вниз. В этом случае комментарий помещается над окном ввода. Если [mo] = 2,3,4,5, то каждая пара комментарий+текст будут помещены на одной строке, все строки образуют один столбец. Если [mo] = 6,7, то пары комментарий+текст будут помещены в два столбца. В этом случае параметр [n] должен иметь четное значение и первая половина окон ввода попадет в первый столбец, а вторая -- во второй. Если [mo] = 8,9, то пары комментарий+текст будут помещены в три столбца. В этом случае параметр [n] должен делиться на три и первая треть окон ввода попадет в первый столбец, вторая -- во второй и третья -- в третий. Если [mo] > 9, то окна ввода будут размещены по 4,5,.. в строке, но столбцы при этом не выравниваются. Последний режим я еще ни разу не использовал.

Нижняя линия панели содержит две кнопки [OK] и [Cancel]. Параметр [le] определяет длину пустого пространства с обоих сторон от этих кнопок в тех случаях, когда они размещаются в центре. Это единственный способ задать длину окон ввода, так как комментарии записываются целиком, а окна ввода не имеют размер и их длина зависит от общей ширины панели, определяемой плотной упаковкой строк с заданным размером. Такой строкой как раз и является строка с кнопками. В частности, если [mo=0;] или [mo=1;], то ширина панели зависит от максимальной длины заданных строк. С помощью параметра [le] можно сформировать любую ширину строки с кнопками. Обычно [le] = 50, но может быть больше или меньше. Значение [le] оптимизируется эмпирически. Панель в нормальных условиях помещается в центре экрана автоматически.

Содержание всех окон ввода может быть изменено пользователем. После выхода из диалога новые тексты будут помещены в текстовый массив t() аналогично команде #print. Содержание разных окон ввода разделяется ASCII кодом 10 (разделителем строк). Напомню, что индекс первого элемента для записи в массив символов t() определяется параметром s(3). После операции параметр s(4) указывает на начальный индекс первого элемента записи в t() с новым текстом (s(3) будет уже другим) и s(5) покажет длину всех записей включая и код 10 после каждой строки. Поэтому соблюдайте осторожность в работе с введенным текстом. Например, в случае [n=1;] его длина будет s(5)-1.

Как уже отмечалось, панель содержит две кнопки [OK] и [Cancel]. Если пользователь выбирает кнопку [Cancel], то текстовый массив t() не будет заполнен, а переменная [&] будет равна 2. Текстовый массив будет записан только при выборе кнопки [OK] и в этом случае [&] будет равен 1. Расположение кнопок тоже зависит от модификации. Если [mo] = 0,1 или > 5, то они расположены в центре и [le] задает пустое пространство с обоих сторон. Но если [mo] = 2,3, то они расположены в левой стороне, а все пустое пространство длиной 2*[le] справа. Если [mod] = 4,5, то они расположены в правой стороне, а все пустое пространство длиной 2*[le] слева.

Первоначально панель с окнами ввода всегда устанавливалась в середине экрана. Сейчас введены новые режимы аналогично предыдущей команде #sel, то есть реакция на параметр [emp] (enhanced mode parameter), стандартное значение которого всегда равно нулю. При стандартном значении [emp] действует старый режим для совместимости с ранее написанными программами. Но если значение отлично от нуля, то положение таблицы кнопок определяется параметрами [xs] и [ys], а именно, эти параметры задают смещение верхнего левого угла панели кнопок из левого верхнего угла экрана, если [emp=1;], или из левого верхнего угла главного окна программы, если [emp=2;]. Последний режим удобен для приложений, запускаемых через проигрыватель и комбинируемых с внутренними окнами программы. Для проигрывателя положение и размер основного окна задается самой ACL программой. При изменении параметра [emp] не забывайте обнулять его после выполнения команды.

Команда #inp позволяет также вводить пароль. Это реализуется запуском команды с [n=0;]. При этом используется только один параметр [le] для формирования длины окна и только один аргумент FT для заголовка окна. В этом случае команда выставляет одно пустое окно ввода без подписи и при вводе в него текста вместо текста показываются звездочки. Набранный текст возвращается, как обычно, в строку t() начиная с s(4) и всего [s(5)-1] символов.

Есть еще одна дополнительная возможность. Параметр [emp] может быть двух-разрядным целым числом. Если второй справа разряд больше нуля, то есть число >= 10, то на панель выставляется дополнительная строка, имеющая четыре кнопки с именами [Help] [Notes] [Save Var] [Choose Var]. Размер этой строки достаточно большой и панель уже не может быть тоньше это размера. Но, с другой стороны, эти кнопки позволяют сразу показать пользователю возможности дополнительного сервиса. Дело в том, что для некоторых простых программ панель с окнами ввода является главной панелью программы. И хотя окна ввода подписаны, но пользователю может понадобиться дополнительная информационная помощь, которую он может сразу получить, нажимая кнопку [Help]. Далее, данные всех окон ввода представляют собой текущий вариант. Может быть много вариантов, поэтому желательно иметь способ спасти текущий вариант в базу данных или выбрать новый вариант из базы данных. Такой сервис предоставляется кнопками [Save Var] и [Choose Var]. Кнопка [Notes] позволяет вести записи комментариев по вариантам и проделанной работе. На самом деле эти кнопки просто возвращают в переменной [&] значения 3,4,5,6 и новые значения всех окон ввода. Весь описанный выше сервис программист должен обеспечить самостоятельно дополнительным кодом на ACL. Наличие кнопок только позволяет узнать о намерениях пользователя. Когда этого режима не было тот же самый сервис приходилось делать с помощью дополнительной команды #sel после выхода из панели по кнопке [Cancel]. Данный режим делает это более прямым способом.

.

Третья команда #fr (frame) дает возможность программисту выставить на экран картинку без остановки работы программы, а после выполнения некоторых операций снять картинку с экрана без участия пользователя (программно). Показывается картинка, заранее спасенная в память компьютера с номером от 1 до 100. Записать такую картинку в память позволяют команды #w , #g , #eg , которые рассмотрены в последующих главах. Номер картинки определяет параметр [n]. Картинка показывается как есть. Ее положение на экране определяют параметры [xs] и [ys]. Они показывают смещение левого верхнего угла картинки от левого верхнего угла экрана в пикселах экрана. Есть два режима работы команды. Если параметр [mo=0;], то картинка выставляется во внутреннем окне главного окна интерпретатора со специальным оформлением. Это внутреннее окно имеет имя и оно приклеено к окну программы. Оно исчезает и появляется вместе с ним, его нельзя свернуть или перенести за пределы окна, которому оно принадлежит, то есть окна интерпретатора. Соответственно этот вариант не работает в версии интерпретатора без окна (номер 2).

Если параметр [mo] отличен от нуля, например равен 1, то картинка будет показана без рамки, то есть анонимно. Она не имеет имени. Но задавая разные значения параметра [mo] можно выставить разные картинки даже одну поверх другой. Это удобно в том случае, если необходима буферизация изображений для быстрой смены кадров. Основное применение этой команды состоит в показе разного рода комментариев, сопровождающих таблицу кнопок или окна ввода, устанавливаемые ACL-программой. Такие комментарии должны исчезать одновременно с окнами диалога. Другое применение -- возможность показа в автоматическом режиме серии сообщений о выполнении вычислений или другой информации, не требующей действий пользователя, в течение времени ожидания окончания вычислений. Вариант анонимной картинки можно оформить как статусную строку в нижней или верхней части экрана, которая автоматически исчезает и появляется вновь с другим содержанием. При установке таких картинок полезно знать размеры экрана дисплея. Эти размеры показывают параметры s(106) и s(107). У этой команды есть две операции. В имени операции достаточно одной буквы. Итак, первая операция:

 #fr [op=o; mo=; n=; xs=; ys=;] FT

Эта операция (open) выставляет картинку на экран. Параметры [xs] и [ys] задают положение картинки на экране. Картинка ставится на экран как есть, то есть с теми размерами, которые она имеет в файле. В режиме [mo=0;] окно с картинкой имеет имя, которое задается аргументом FT. В анонимном режиме [mo>0;] аргумент не требуется, так как окна нет, картинки различаются по значению параметра [mo]. Всего можно выставить 10 картинок. В режиме интерпретатора без окна вариант с mo=0 не работает, а вариант с mo>0 работает и его даже можно использовать для создания некоторого подобия внешнего вида программы. Но надо следить за тем, чтобы другие картинки или анимационные окна не закрывались этой картинкой, иначе при клике на ней они потеряют фокус и получить его больше не смогут. Она будет закрывать их и программа потеряет свою функциональность. Вторая операция:

.

 #fr [op=c; mo=;] FT

Эта операция (close) снимает картинку с экрана. В режиме [mo=0;] аргументом команды является имя окна, которое было присвоено окну при установке картинки. Это удобно, так как можно выставить несколько картинок и тогда их надо различать между собой. В режиме анонимной картинки [mo>0;] аргумент не требуется. Команда снимает с экрана картинку с заданным значением параметра [mo].

Четвертая команда #pf (progress form) позволяет сообщать пользователю в красивой и стандартной форме о процессе выполнения какой-либо работы, если этот процесс занимает длительное время. Это очень важно с психологической точки зрения потому, что когда компьютер молчит и ничего не происходит, то может показаться, что он завис или возникла аварийная ситуация. Поэтому надо делать так, чтобы компьютер периодически показывал, что он работает и двигается. Эта команда открывает новое окно с именем "Progress". В этом окне изначально показывается пустой длинный прямоугольник, который постепенно закрашивается голубым цветом. Одновременно в середине строки указывается процент выполнения данной работы. Эта команда имеет 3 операции. В имени операции достаточно одной буквы. Первая операция:

.

 #pf [op=o; le=;] 

Эта операция (open) открывает окно с пустым прямоугольником. Параметр [le] задает максимальное целое значение, соответствующее полному выполнению работы. Например, если производятся вычисления в цикле, то это может быть число повторений цикла минус 1. Эту операцию надо поставить до выполнения цикла. Окно всегда появляется в центре экрана. Вторая операция:

.

 #pf [op=m; siz=;] 

Эта операция (move) закрашивает прямоугольник в соответствие с значением параметра [siz]. Это значение должно быть больше нуля, но меньше, чем [le]. Если оно вылезает за эти границы, его принудительно ставят на границу. Обычно эта операция должна стоять внутри цикла и параметр [siz] должен быть равен параметру цикла. Одновременно показывается процент выполнения работы как число [siz]/[le]*100. Наконец, третья операция (close):

.

 #pf [op=с;] 

просто закрывает окно. Ее надо ставить после цикла.

Пятая, относительно простая команда тоже позволяет сделать выбор, но более сложным и универсальным способом. Для ее описания необходимо принять на веру информацию, которая более подробно будет описана в последующих главах. Эта команда называется #choice, сокращенно #ch, и имеет вид

.

 #ch [n=; xs=; ys=;] 

Она показывает на экране картинку, заранее спасенную в память компьютера с номером от 1 до 100. Записать такую картинку в память позволяют команды #w , #g , #eg , которые будут рассмотрены в последующих главах. Номер картинки определяет параметр [n]. Картинка показывается как есть и без рамки. Ее положение на экране определяют параметры [xs] и [ys]. Они показывают смещение левого верхнего угла картинки от левого верхнего угла экрана в пикселах экрана. После показа картинки программа останавливается и ждет реакции пользователя. Пользователь должен кликнуть на картинке мышкой, поставив курсор мыши в нужное место, или нажать нужную клавишу на клавиатуре. После этого картинка исчезает, а координаты курсора мыши, модификатор и код клавиши будут возвращены в программу в параметрах s(102), s(103), s(1) и s(2). Эту информацию можно использовать для последующей работы. Координаты курсора отсчитываются от левого нижнего угла картинки. Модификатором называется способ, каким был сделан клик мышкой. Можно просто кликнуть, а можно одновременно нажать какую-либо служебную клавишу. Значения модификатора, а также коды клавиш описаны в главе 13.

Эта команда позволяет предложить пользователю сделать выбор общего вида. Например, на картинке может быть записана инструкция какая работа будет выполнена при нажатии определенной клавиши. В соответствие с этой инструкцией пользователь делает выбор, нажимая нужную ему клавишу. Или на картинке может быть изображена карта. Кликая мышкой в определенной точке карты пользователь определяет какой район его интересует. Картинка также может показывать серию кнопок фасонного вида в сложной конфигурации, например, Таблицу Менделеева. При этом выбор кнопки определяется по координате курсора или по коду клавиши. Возможны и многие другие варианты. Следует отметить, что такой режим требует написания сложного кода на языке ACL, по анализу координат курсора мыши, в то время как рассмотренная выше команда #sel все делает автоматически. С другой стороны, возможности данной команды намного выше.