В модель данных можно внести структуру дерева, например разбить документ на главы, параграфы, разделы. Каждый элемент разбиения описывается интерфейсом Element. Элемент занимает какую-то область текста с начальной позицией, возвращаемой методом getStartOffset (), и конечной позицией getEndOffset (). У элемента может быть родительский элемент, который легко получить методом getParentElement(). Область текста, занимаемая родительским элементом, полностью включает в себя область исходного элемента. У элемента могут быть дочерние элементы, чья область текста полностью лежит внутри области самого элемента. Их можно получить методом getElement(int). Число дочерних элементов возвращает метод getElementCount (), а индекс дочернего элемента — метод getElementIndex (int). Элементу можно дать имя, а затем получить его методом getName ().
Интерфейс Element частично реализован абстрактным классом AbstractElement, вложенным в класс AbstractDocument, и полностью реализован еще двумя вложенными
в AbstractDocument классами — BranchElement и LeafElement, расширяющими класс AbstractElement. Основная разница между ними в том, что у класса BranchElement могут быть дочерние элементы, а у класса LeafElement — нет.
Класс BranchElement, в свою очередь, расширяется классом SectionElement, вложенным в класс DefaultStyledElement, и классом BlockElement, вложенным в класс HTMLDocument.
Класс LeafElement расширяется классом RunElement, вложенным в класс HTMLDocument. Элементы создаются методами
Element createLeafElement(Element parent, AttributeSet attr,
int pos1, int pos2);
Element createBranchElement(Element parent, AttributeSet attr);
Для каждого структурного элемента можно задать свое множество атрибутов методом
addAttribute(Object name, Object value) или методом addAttributes(AttributeSet).
В документе допускается задание нескольких независимых структур. Их корневые элементы можно получить методом getRootElements ( ), возвращающим массив типа Element [ ]. Один из корневых элементов можно сделать корневым элементом по умолчанию и получать его методом getDefaultRootElement(), возвращающим элемент в виде объекта, реализующего интерфейс Element. Получив корневые элементы структурного дерева, легко обойти его, используя метод getElement(int) интерфейса Element или метод children (), имеющийся в его реализациях.
События в документе
При всяком изменении документа или его структуры происходит событие, описанное интерфейсом DocumentEvent. Он предлагает метод getDocument ( ), позволяющий узнать, в каком документе произошло событие, методы getOffset () и getLength (), сообщающие о начальной позиции и длине измененного текста. Вложенный интерфейс ElementChange содержит метод getElement (), позволяющий узнать элемент, в котором произошло событие, и методы, помогающие отследить добавление и удаление элемента из документа.
Реализация интерфейса DocumentEvent — класс DefaultDocumentEvent, вложенный в класс AbstractDocument, — добавляет к методам интерфейса метод undo (), отменяющий изменения, метод redo (), восстанавливающий изменения, и еще несколько информационных методов.
Если модель данных позволяет отменять и восстанавливать изменения (undo/redo), то при каждом таком действии в ней происходит событие класса UndoableEditEvent.
Реализации документа
Интерфейс Document частично реализован абстрактным классом AbstractDocument. Этот класс вносит понятие блокировки документа. Документ могут просматривать несколько подпроцессов-"читателей" и один подпроцесс-"писатель". Доступ их к документу блокируется методами readLock() и writeLock(). Блокировки снимаются методами
readUnlock() и writeUnlock().
Класс AbstractDocument обычно не расширяется непосредственно, а используются или расширяются его подклассы PlainDocument и DefaultStyledDocument.
Класс PlainDocument задает модель простого документа с "плоским" текстом, которая используется полями ввода JTextField, JPasswordField, JTextArea. Текст в этой модели имеет структуру: структурные элементы текста — это строки. Корневой элемент структуры можно получить методом getDefaultRootElement(). Метод getParagraphElement(int offset) возвращает элемент структуры — строку в виде объекта типа Element, к которому принадлежит позиция offset. Каждой строке, как любому элементу структуры, можно придать атрибуты. Отдельные символы атрибутов не имеют.
Более сложную структуру вносит в документ модель класса DefaultStyledDocument, используемая в текстовом редакторе JTextPane. В этой модели не только строке, но и каждому символу текста можно задать свой стиль.
Наконец, класс DefaultStyledDocument расширяется классом HTMLDocument. Это модель разметки языка HTML. В ней можно определить
Установка модели данных
После того как новая модель данных определена, ее надо установить в компонент методом setDocument(Document) класса JTextComponent.