Универсальное меню

1. Общее описание.

Проект движка универсального меню для малоразмерных текстовых дисплеев (индикаторов).

Малоразмерные текстовые дисплеи (например 20×4 или 40×8 – 8 строк по 40 символов в строке) до сих пор активно применяются во встаиваемых системах. Особенностью данного дисплея, ввиду его малого размера, является невозможность организации классических тестовых окон как было в DOS. В тоже время достаточно актуальна задача организации всевозможных меню на этом дисплее. Известные мне реализации малофункциональны, громоздки, в них нет четкого разделения описания меню и кода (движка меню). Поэтому возникла идея создания универсального движка. Принцип движка основан на листах. Каждое меню – текстовый лист произвольных размеров. Для упрощения ширину листа можно принять равной ширине дисплея. В произвольных местах листа могут быть вставлены пункты меню – переменные, которые можно просмотреть и/или изменить. Переменные могут быть двоичные, числовые, тестовые, выбор из списка или выбор подменю – другого листа. Лист – обычный тестовый массив, с включенной в него разметкой. Разметка простая, по типу printf. Разметка полностью определяет тип переменной, можно ли её изменять, пределы изменения, а также разбивает массив на строки символами конца строки. В конце листа, также в тестовом виде, размещаются индексы адресов переменных, строки выбора в порядке их указания в разметке (также как в prinf). Таким образом лист состоит из нескольких элементов – строк меню, которые будут выводится, ссылок на переменные и элементы выбора из списка. Элементы листа разделяются специальным разделителем, который не может использоваться для вывода на экран. Таким разделителем может быть, например символ точка с запятой “;”. Индексы используются потому, что вписать адрес в лист сразу не представляется возможным, т.к. адреса переменных становятся известны как минимум на этапе компиляции, а не написания программы. Кроме того, писать адреса напрямую очень неудобно и чревато ошибками. Поэтому все адреса сводятся в массив указателей, а в листе в тестовом виде указан индекс указателя в этом массиве. По моему досточно удобно.

Клавиатура состоит из 6-ти клавиш. 4 клавиши навигации вверх/вниз, влево/вправо и 2 клавиши действия – “ввод/выбор” и “отмена”. Навигация выполняется либо по пунктам меню, либо при их отсутсвии производится прокрутка листа на экране (если число строк в листе больше числа строк на экране). При выборе переменной её можно редактировать клавишами вверх/вниз поразрядно или выбором из списка. Нажатие “ввод” применяет изменения, “отмена” возвращает назад. Опционально возможен вызов функции для применения изменений. Индикация выбранного пункта меню осуществляется в соотвествии с возможностями устройства отображения. Это или инверсия или мигание, или просто курсор.

Требования к дисплею можно обобщить. Он должен поддерживать команды:

  • очистка clrstr();
  • установка позиции для ввода setpos(столбец, строка);
  • установка позиции курсора setcur(столбец, строка);
  • ввод в режиме поверх имеющегося текста putc(символ);

Аппаратную прокрутку (скроллинг) большинство многострочных индикаторов поддерживают весьма своеобразно, поэтому можно считать что её нет и можно выполнить только программно. Выделение части теста инверсией в большинстве ндикаторов возможно только программно и связано с перезагрузкой знакогенератора, поэтому оставим только курсор.

2. Работа движка.

Работа движка состоит из следующих этапов:

  1. Интерпретация листа – функция ParseList.
    На входе: адрес листа, адрес массива описаний, адрес массива опций выбора. На выходе: заполненный массив описаний, заполненный массив опций выбора.
    Интерпретатор получает в качестве входных значений адрес предыдущего листа (или NULL – если главное меню и предыдущего листа нет) и адрес листа для разбора. В процессе разбора интерпретатор выполняет следующие действия:

    1. Заполняет массив структур описаний переменных:
      адрес;
      код типа;
      можно ли редактировать;
      начальный индекс в массиве опций выбора;
      нижний предел;
      верхний предел;
      позиция вывода на экран (строка и столбец);
      длина (сколько символов занимает);
      адрес функции для изменения переменной (или NULL);
      Массив статический, рассчитан не некоторое максимально возможное количество переменных в одном меню.
    2. Заполняет массив опций выбора. Массив также статический, рассчитан на некоторое суммарное максимально возможное количество опций выбора в одном меню и длину каждой опции.
  2. Сбор листа в многострочном буфере – функция RenderList.
    На входе: адрес буфера, адрес массива описаний, адрес массива опций выбора. На выходе: заполненный буфер.
    Буфер статический, представляет собой массив максимально возможного количества строк максимально возможной длины. Собирает меню. Выводит строку с разметкой, делая пропуски в местах переменных. Проходит по массиву структур и для каждого типа переменной вызывает свою функцию для её перевода в тестовый вид.
  3. Вывод меню из буфера на дисплей – функция ShowList.
    На входе: адрес буфера, номер начальной строки. На выходе: заполненный дисплей. Пользуется функцией putc().
  4. Основной цикл.
    Выполняется либо периодическим вызовом, либо вызовом по нажатию клавиш. При вызове по нажатию клавиш, теряется возможность обновления информации на дисплее, если значение переменной меняется.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *