Table of Contents

Управление всем UI происходит, как правило, работой с элементами DOM.

DOM (Document Object Model) — это дерево всех элементов, из которых состоит отображаемый HTML. В первом приближении можно считать, что один DOM-элемент соответствует одному теги исходного текста HTML, впрочем, из этого правила есть исключения (см. Примечание 1).

Изменение DOM (состава, внешнего вида, состояния) происходит только следующими способами (весь API для этого описан в заголовочном файле htmlayout_dom.h, тонкая C++-обертка “для примера” — htmlayout_dom.hpp):

  1. Навигация по DOM — используется для того, чтобы найти элемент, который собираешься менять.
  2. Добавление/удаление DOM элементов — используется, собственно, для изменения элементов UI.
  3. Изменение HTML элементов DOM — альтернатива модификации DOM путем удаления/вставки элементов
  4. Изменение аттрибутов элементов DOM — используется для изменения представления элементов
  5. Изменение состояния элементов DOM — используется для того, для чего и можно предположить по названию
  6. Изменение "значения" (value) элементов DOM — быстрый способ изменения значимой части состояния элемента

Далее подробнее.

Навигация по DOM

Методы навигации:

Добавление/удаление элементов

Реализуется, соответственно, функциями: HTMLayoutInsertElement, HTMLayoutDetachElement.

Полезно знать:

.hidden{display:none;}

Изменение HTML элементов DOM

Выполняется, естественно, функциями HTMLayoutGetElementHtml/HTMLayoutSetElementHtml.

Важно понимать, что не все прямые изменения HTML одинаково полезны (и безопасны). Например, попытка установить для элемента <tr> какой-нибудь другой html, кроме набора <td>, может привести к совершенно непредсказуемым последствиям.

Лично я предпочитаю использовать HTMLayoutSetElementHtml только в простейших случаях, когда нужно, скажем, в ячейке таблицы написать “немножко <b>жирного</b> текста”, а все более глобальные изменения UI выполнять методами, описанными в разделе Добавление/удаление элементов.

Изменение текста элементов DOM

Чтобы узнать текст, используются функции HTMLayoutGetElementText, HTMLayoutGetElementInnerText — первая вернет текст с “дырками” на месте дочерних элементов, вторая — полный текст. (например, для элемента ”<p>some text with <b>bold</b> part</p>” первая вернет “some text with \0 part”, вторая — “some text with bold part”).

Чтобы изменить текст, используется функция HTMLayoutSetElementInnerText. Внимание! Все дочерние элементы будут удалены. (То есть вызывать эту функцию для <table> — не очень разумная идея).

Эти функции (как и большинство других функций HTMLayout) работают с текстом в кодировке UTF-8.

Существуют также UTF-16 варианты: HTMLayoutGetElementInnerText16, HTMLayoutSetElementInnerText16.

Изменение аттрибутов элементов DOM

Перебор всех аттрибутов: HTMLayoutGetAttributeCount, HTMLayoutGetNthAttribute Запрос/установка значения аттрибута по имени: HTMLayoutGetAttributeByName, HTMLayoutSetAttributeByName.

Сброс всех аттрибутов: HTMLayoutClearAttributes.

Основные цели, ради которых используются аттрибуты:

Имена аттрибутов можно использовать любые, соответствующие стандарту (ссылка?), но обратить внимание, что есть некоторые аттрибуты, которые обрабатывает сам HTMLayout, и их изменение вызовет side effects. Примеры:

Изменение состояния элементов DOM

HTMLayoutGetElementState/HTMLayoutSetElementState

Используется для запроса и установки состояний элементов, которые изменяются под действиями пользователя.

Например:

Вообще, все возможные состояния перечислены в enum ELEMENT_STATE_BITS в файле htmlayout_dom.h. Там же — подробные комментарии, какое состояние что означает.

Очевидно, что элемент может иметь несколько состояний одновременно (допустим, FOCUS | HOVER | CHANGED).

Полезные применения состояний:

Вообще, работа с состояниями идет согласно с человеческой логикой: если нужно изменить состояние некоего элемента (например, свернутый/развернутый для вершины дерева), нужно в первую очередь поискать соответствующую константу STATE (STATE_COLLAPSED/STATE_EXPANDED).

Изменение "значения" (value) элементов DOM

HTMLayoutControlGetValue/HTMLayoutControlSetValue — удобные “шорткаты” для работы с элементами ввода, позволяет однообразно запросить/установить значение для разных элементов. Все, что делается этими функциями, может быть сделано и без них (но несколько менее удобно).

Например:

и т.п.

Дополнения

Примечания

Примечание 1

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

<select>
  <option>1</option>
  <option>2</option>
  <option>3</option>
</select>

(выпадающий список с 3-мя элементами) “на самом деле” преобразуется вот в такой:

<select>
  <caption></caption>
  <popup type="select">
    <option>1</option>
    <option>2</option>
    <option>3</option>
  </popup>
</select>

В некоторых случаях этот нюанс оказывается важным.

Примечание 2

Элементы DOM HTMLayout — это объекты со счетчиками ссылок, они удаляются, когда счетчик ссылок равен 0. Пользователь может контролировать счетчик ссылок функциями HTMLayout_UseElement, HTMLayout_UnuseElement. Пока элемент находится в DOM, счетчик ссылок у него > 0. Если пользователь удалил элемент из DOM (HTMLayoutDetachElement), то его можно продолжать использовать дальше, пока счетчик ссылок > 0.

Внимание, важный нюанс! Если элемент, который удаляется из DOM, еще нужен (вы собираетесь его куда-то вставить), то правильная последовательность действий такая:

  1. увеличить счетчик ссылок объекта на 1 (HTMLayout_UseElement)
  2. удалить элемент из DOM (HTMLayoutDetachElement) - на этом этапе счетчик уменьшится на единицу (дереву объект уже “не нужен”), и если бы мы не выполнили шаг 1, счетчик ссылок здесь стал бы равен 0, и объект был бы собран сборщиком мусора
  3. вставить объект, куда собирались (HTMLayoutInsertElement) - счетчик опять увеличится
  4. сделать HTMLayout_UnuseElement.

Чтобы во всем этом не запутаться, существенно предпочтительнее использовать какую-нибудь обертку вокруг HELEMENT с автоматическим подсчетом ссылок. Для C++ такая обертка входит в поставку HTMLayout и находится в файле htmlayout_dom.hpp

Примечание 3

Некоторые элементы DOM требуют специального количества дочерних элементов. Главным образом, это относится к строкам таблиц - в каждой строке таблицы должно быть одинаковое количество ячеек; поэтому, если создать “кривую” таблицу (например, с тремя строками длиной 3, 2, и 4 ячейки), HTMLayout добавляет недостающие ячейки автоматически (то есть, в первую строку будет добавлена одна, а во вторую - 2 ячейки). Касательно этих “авто-добавленных” ячеек следует знать:

  1. “исправление” будет выполнено только после обновления-перерисовки элемента (перерисовки всего окна или вызова HTMLayoutUpdateElement), до тех пор можно заниматься конструированием безбоязненно (если, например, ваш юз-кейс требует создать таблицу с кучей строк разной длины, а затем пробежаться по ней и отрезать лишние ячейки).
  2. добавленные ячейки имеют установленный флаг состояния STATE_SYNTHETIC, по которому их можно отловить для каких-либо целей.