Менеджер по расположению

Менеджер по расположению класс, NSLayoutManager, обеспечивает центральный объект управления для текстового дисплея в текстовой системе Какао.

NSLayoutManager объект выполняет следующие действия:

В парадигме контроллера представления модели, NSLayoutManager контроллер. NSTextStorage, подкласс NSMutableAttributedString, обеспечивает часть модели, содержа строку текстовых символов с атрибутами, такими как гарнитура, стиль, цвет и размер. NSTextContainer может также считаться частью модели, потому что это моделирует геометрическое расположение страницы, на которой размечается текст. NSTextView (или другой NSView объект), обеспечивает представление, в котором выведен на экран текст. NSLayoutManager служит контроллером для текстовой системы, потому что это направляет генератор глифа для перевода символов в текстовом объекте хранения в глифы, направляет наборное устройство для разметки их в строках согласно размерностям одного или более текстовых контейнерных объектов и координирует текстовый дисплей в одном или более текстовых объектах представления. Рисунок 1 иллюстрирует состав текстового дисплея, координирующегося менеджером по расположению.

  Состав рисунка 1 текстового дисплея
Composition of text display

Можно сконфигурировать текстовую систему для имения больше чем одного менеджера по расположению при необходимости в тексте в том же NSTextStorage объект, который будет размечен больше чем одним способом. Например, Вы могли бы хотеть, чтобы текст появился как непрерывная гранка в одном представлении и был сегментирован на страницы в другом представлении. Для получения дополнительной информации о различных расположениях текстовых объектов, обратитесь к Общим Конфигурациям.

Потокобезопасность

Вообще говоря, данный менеджер по расположению (и связанные объекты) не должен использоваться больше чем на одном потоке за один раз. Большинство менеджеров по расположению используется на основном потоке, так как это - основной поток, на котором их текстовые представления выведены на экран, и так как фоновое расположение происходит на основном потоке. Однако можно разметить и представить текст на вторичном использовании потоков NSLayoutManager пока граф объектов содержится в единственном потоке.

Если необходимо использовать менеджера по расположению на вторичном потоке, это - ответственность приложения гарантировать, что к объектам не получают доступ одновременно от других потоков. Во-первых, удостоверьтесь это NSTextView в то время как менеджер по расположению используется на вторичном потоке путем отключения фонового расположения и автодисплея, объекты, связанные с тем менеджером по расположению (если таковые имеются), не выведены на экран. Например, Вы могли отправить текстовое представление lockFocusIfCanDraw блокировать основной дисплей потока (и отправить unlockFocus по окончании). Во-вторых, выключите фоновое расположение для того менеджера по расположению, в то время как оно используется на вторичном потоке путем отправки setBackgroundLayoutEnabled: с NO.

Процесс создания макета

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

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

NSLayoutManager использование NSTypesetter объект выполнить фактическое расположение глифа. Посмотрите Наборные устройства для получения дополнительной информации. Рисунок 2 иллюстрирует взаимодействие объектов, вовлеченных в процесс создания макета.

Рисунок 2  текстовый процесс создания макета
The text layout process

Следующие шаги, пронумерованные для корреляции с числами на рисунке 2, объясняют, как менеджер по расположению управляет текстовым расположением:

  1. Текст в текстовых изменениях среды хранения, лишая законной силы глифы или их позиции макета или обоих. Аннулирование происходит, например, потому что пользователь редактирует текст в текстовом представлении, и текстовое представление вызывает изменения в содержании текстового хранения. Или другой объект может изменить текст программно.

  2. Текстовое хранение уведомляет своего связанного менеджера по расположению (или менеджеров) лишенного законной силы диапазона символов путем отправки сообщения textStorage:edited:range:changeInLength:invalidatedRange:. Сообщение указывает, влияло ли изменение на символы, атрибуты или обоих; диапазон изменившихся символов; и диапазон, затронутый после фиксации атрибута.

  3. Менеджер по расположению обновляет его внутренние структуры данных для отражения недопустимого диапазона. Изменения атрибута могут или могут не влиять на генерацию глифа и расположение. Например, изменение цвета текста не влияет, как это занимается сексом.

  4. Для уведомления его связанных текстовых представлений, что они должны восстановить изображение лишенной законной силы области менеджер по расположению отправляет сообщение setNeedsDisplayInRect:avoidAdditionalLayout:. В этой точке любая из нескольких вещей могла произойти. Если лишенная законной силы часть текстового представления видима, текстовое представление спрашивает менеджера по расположению по любым необходимым глифам и их позициям. Если лишенная законной силы область не в настоящее время видима, представление сразу не требует расположение. Однако фон (время простоя), расположение может произойти, когда приложение не имеет никаких событий для обработки. Фоновое расположение идет по умолчанию, несмотря на то, что можно выключить его для любого отдельного менеджера по расположению.

  5. Когда текстовое представление спрашивает менеджера по расположению по глифам и позициям, процесс создания макета начинается. (Другие сообщения могут также вызвать расположение. Заголовочный файл менеджера по расположению и справочная документация указывают, какие методы заставляют генерацию глифа и расположение происходить.)

  6. Менеджер по расположению генерирует поток глифов от недавно отредактированного диапазона символов и кэширует глифы. Генерация глифа является быстрым преобразованием первой передачи символов в определенном шрифте к глифам. (Без информации о шрифтах не могут быть сгенерированы глифы.) Более поздние этапы процесса создания макета могут внести изменения в поток глифа.

  7. После того, как требуемые глифы были сгенерированы, вызовы диспетчера расположения его наборное устройство для разметки глифов в один или несколько фрагментов строки, отправив layoutGlyphsInLayoutManager:startingAtGlyphIndex:maxNumberOfLineFragments:nextGlyphIndex: обменивайтесь сообщениями к наборному устройству. Во время этого процесса наборное устройство может выполнить замену глифа; например, это может заменить глифом лигатуры вместо двух или больше односимвольных глифов.

  8. Наборное устройство генерирует прямоугольники фрагмента строки в связи с текстовым контейнером и определяет размещение каждого глифа, как описано в Наборных устройствах и Генерации Фрагмента Строки.

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

Получение глифа

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

Большинство NSLayoutManager методы используют контейнерные координаты, вместо того, чтобы просмотреть координаты. Текстовая система ожидает, что координаты представления будут зеркально отражены, как те NSTextView. Если у Вас есть точка, в поле зрения координирует это, необходимо преобразовать в контейнерные координаты, вычесть текстовое представление textContainerOrigin значение для получения контейнерных координат. Расположения глифа выражены относительно их источника ограничительного прямоугольника фрагмента строки. Рисунок 3 показывает отношения среди этих систем координат.

  Представление рисунка 3, контейнер и координаты фрагмента строки
View, container, and line fragment coordinates

Атрибуты являются качествами, менеджер по расположению применяется к символам во время набора и расположения, таким как шрифт, размер и цвет. Текстовое хранение сохраняет много атрибутов в словаре, сохраненном символьной строкой, но другие атрибуты являются временными и сохраняются только менеджером по расположению во время процесса создания макета. Временные атрибуты заменяют атрибуты, связанные со шрифтом или абзацем. Когда нарисованные глифы выбраны в текстовом представлении, методы рисования также обрабатывают дополнительные атрибуты, связанные с текстовым представлением — например, различный цвет фона —. Методы рисования вызывают некоторую другую общественность NSLayoutManager методы, такой как drawUnderlineForGlyphRange:underlineType:baselineOffset:lineFragmentRect:lineFragmentGlyphRange:containerOrigin:, если Вы хотите сделать вещи по-другому, который можно переопределить. Посмотрите, что текстовый Атрибут Программирует Темы для получения дополнительной информации.

Менеджер по расположению также обрабатывает представление присоединений во время получения глифа. Текстовая система хранит присоединение как атрибут специального символа. Типичное присоединение является файлом, но это могут также быть данные в памяти. Файловое вложение обычно обрабатывается путем рисования значка. Однако присоединение может сделать намного больше, чем это при реализации различного поведения. Во время расположения присоединяемая ячейка (NSTextAttachmentCell) говорит менеджеру по расположению, каково размер это, таким образом, это может быть размечено как глиф. Соответственно, высота строки текста и символьное размещение корректируются для размещения присоединяемой ячейки. Во время получения менеджер по расположению просит, чтобы присоединяемая ячейка нарисовала себя. Посмотрите, что текстовое Присоединение Программирует Темы для получения дополнительной информации.

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

NSLayoutManager обеспечивает общедоступный API для получения глифов от символов. Процесс сложен, однако: Вы не можете просто преобразовать отдельный символ в глиф, потому что отношение между символами и глифами является many-many. Т.е. один символ в текстовом хранении может отобразиться на многократные глифы и наоборот. Поэтому Вы используете NSLayoutManager методы glyphRangeForTextContainer: получить глифы для всех символов, размеченных в текстовом контейнере или glyphRangeForCharacterRange:actualCharacterRange: для диапазона символов.