Читайте также:
|
|
Рис. 2.4. Частичная иерархия класса Glyph
Глифу-родителю часто бывает нужно «знать», сколько места на экране занимает глиф-потомок, чтобы расположить его и остальные глифы в строке без перекрытий (как показано на рис. 2.2). Операция Bounds возвращает прямоугольную область, занимаемую глифом, точнее, противоположные углы наименьшего прямоугольника, содержащего глиф. В подклассах класса Glyph эта операция переопределена в соответствии с природой конкретного элемента.
Операция Intersects возвращает признак, показывающий, лежит ли заданная точка в пределах глифа. Всякий раз, когда пользователь щелкает мышью где-то в документе, Lexi вызывает эту операцию, чтобы определить, какой глиф или глифовая структура оказалась под курсором мыши. Класс Rectangle переопределяет эту операцию для вычисления пересечения точки с прямоугольником.
Поскольку у глифов могут быть потомки, то нам необходим единый интерфейс для добавления, удаления и обхода потомков. Например, потомки класса Row - это глифы, расположенные в данной строке. Операция Insert вставляет глиф в позицию, заданную целочисленным индексом.1 Операция Remove удаляет заданный глиф, если он действительно является потомком.
Возможно, целочисленный индекс - не лучший способ описания потомков глифа. Это зависит от структуры данных, используемой внутри глифа. Если потомки хранятся в связанном списке, то более эффективно было бы передавать указатель на элемент списка. Мы еще увидим более удачное решение проблемы индексации в разделе 2.8, когда будем обсуждать анализ документа.
Операция Child возвращает потомка с заданным индексом (если таковой существует). Глифы типа Row, у которых действительно есть потомки, должны пользоваться операцией Child, а не обращаться к структуре данных потомка напрямую. В таком случае при изменении структуры данных, скажем, с массива на связанный список не придется модифицировать операции вроде Draw, которые обходят всех потомков. Аналогично операция Parent предоставляет стандартный интерфейс для доступа к родителю глифа, если таковой имеется. В Lexi глифы хранят ссылку на своего родителя, a Parent просто возвращает эту ссылку.
Паттерн компоновщик
Рекурсивная композиция пригодна не только для документов. Мы можем воспользоваться ей для представления любых потенциально сложных иерархических структур. Паттерн компоновщик инкапсулирует сущность рекурсивной композиции объектно-ориентированным способом. Сейчас самое время обратиться к разделу об этом паттерне и изучить его, имея в виду, только что рассмотренный сценарий.
2.3. Форматирование
Мы решили, как представлять физическую структуру документа. Далее нужно разобраться с тем, как сконструировать конкретную физическую структуру, соответствующую правильно отформатированному документу. Представление и форматирование - это разные аспекты проектирования. Описание внутренней структуры не дает возможности добраться до определенной подструктуры. Ответственность за это лежит в основном на Lexi. Редактор разбивает текст на строки, строки - на колонки и т.д., учитывая при этом пожелания пользователя. Так, пользователь может изменить ширину полей, размер отступа и положение точек табуляции, установить одиночный или двойной междустрочный интервал, а также задать много других параметров форматирования.1 В процессе форматирования это учитывается.
Кстати говоря, мы сузим значение термина «форматирование», понимая под этим лишь разбиение на строки. Будем считать слова «форматирование» и «разбиение на строки взаимозаменяемыми. Обсуждаемая техника в равной мере применима и к разбиению строк на колонки, и к разбиению колонок на страницы.
Таблица 2.2. Базовый интерфейс класса Compositor
Дата добавления: 2015-09-11; просмотров: 102 | Поможем написать вашу работу | Нарушение авторских прав |