Работа с иерархией видов

Mac OS X

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

Что представляет из себя иерархия видов?

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

Экземпляр окна поддерживает только один верхний уровень вида, называемый - вид контента (content view). Вид контента является корневым для всех видов иерархии данного окна. Экземпляры видов, входящих в вид называются подвидами (subviews) . Каждый экземпляр вида может иметь несколько подвидов, но только один супервид (superview), который является прямым его родителем в иерархии видов. Отображение иерархии видов пользователю происходит от корневого вида до последнего видимого подвида. Рисунок ниже показывает окно е его иерархию видов.

NSView иерархия видов в окне

Приведенная иерархия сосотоит из следующих частей:

  • Окна, экземпляр класса NSWindow.
  • Вида контента, являющегося корневым в иерархии.
  • Вид контента содержит один подвид, в нашем случае экземпляр NSBox
  • Экземпляр подкласса NSBox содержит два подвида, экземпляры класов NSButton и NSTextField.
  • Супервидом для кнопки и текстового поля является экземпляр NSBox.

Преимущества иерархии видов

Управление видами как иерархией дает приемущества при дизайне приложения в нескольких случаях:

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

Положение вида в иерархии видов

Богатый выбор методов позволяет приложениям получать доступ к иерархии видов. Метод superview возвращает вид, который содержит объект-приемник, в то время как метод subviews возвращает массив, содержащий непосредственных потомков вида. Если целью является корневой вид в иерархии, он возвращает nil, когда запросят его супервид. Отправка в вид сообщения window возвращает окно, содержащее вид, или nil, если вид в настоящее время не находится в иерархии видов окна. Рисунок ниже иллюстрирует отношения объектов с точки зрения иерархии показаной на рисунке вначале страницы.

Другие методы позволяют контролировать отношения между видами: isDescendantOf: подтверждает, что содержит объект приемник; ancestorSharedWithView: находит общий контейнер, содержащий приемник и экземпляр вида, указанный в качестве параметра. Например, предположим, в целях иерархии, как показано на рисунке выше следующий запрос:

[viewC isDescendentOf: contentView];
вернет YES, а запрос:
[viewB ancestorSharedWithView: viewC];
вернет viewA.

Метод opaqueAncestor возвратит ближайшего родителя вида, гарантирующего отрисовку каждого пикселя в фрейме объекта приемника.

Удаление и добавление видов в иерархии

Создание экземпляра NSView методом initWithFrame: устанавливает фрейм вида, но не добавляет его непосредственно в иерархию видов. Вы это делаете, посылая сообщение addSubview: супервиду, в который добавляете вид, в качестве параметра передавая указатель на вид. Прямоугольник фрейма, затем интерпретируется с точки зрения супервида, правильно размещая новый вид на его место в иерархии видов и распологая в окне супервида. Существующий вид может быть заменен другим видом посылкой сообщения супервиду: replaceSubview:with:, передавая в качестве аргументов вид заменяемый и вид для замены. В добавление метод addSubview:positioned:relativeTo: устанавливает порядок в иерархии для вида.

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

Для удаления вида из иерархии видов служит метод removeFromSuperview. Вызов метода removeFromSuperviewWithoutNeedingDisplay удаляет вид из иерархии видов, без перерисовки супервида

Когда NSView объект добавляется к супервиду автоматически вызывается метод viewWillMoveToSuperview: и viewWillMoveToWindow:. Вы можете переопредилить эти методы.

Важно: Иерархию видов следует рассматривать как коллекцию объектов. При добавлении вида, в системе управления памятью вызывается retain сообщение, при удалении release.

Изменение положения и размера вида

Изменение положения и размера вида является комплексной операцией. Когда вид перемещается или изменяет размер, часть отображаемого контента может стать невидимой, из-за перекрытия фреймом супервида, или расположенные внутри подвиды вогут перекрыть или наползти друг на друга.

Перемещение и изменение размера программно

После создания вида вы можете переместить, изменить его размер с помощью методов setFrame:, setFrameOrigin: и setFrameSize:.

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

NSView *theView;        /* Предположим существует. */
NSRect newFrame;        /* Предположим существует. */

[[theView superview] setNeedsDisplayInRect:[theView frame]];
[theView setFrame:newFrame];
[theView setNeedsDisplay:YES];

Автоматическое изменение размеров подвидов

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

Interface Builder позволяет настраивать автоматическое изменение подвидов, а также настроить маску привязки вида к сторонам супервида в визуально-графической среде. Всю эту работу можно выполнитьт и программно.

Задание маски авто-изменения размеров происходит с помощью метода setAutoresizingMask: и объединения с помощью побитового оператора OR возможных опций, переданных в аргументе. Ниже приведен список возможных констант, для составления маски.

МаскаОписание
NSViewHeightSizableЕсли установлено, высота вида меняется пропорционально изменению высоты супервида. В противном случае, высота вида неизменна.
NSViewWidthSizableЕсли установлено, ширина вида меняется пропорционально изменению ширины супервида. В противном случае, ширина вида неизменна.
NSViewMinXMarginЕсли установлено, левый край вида перемещается пропорционально изменению ширины супервида. В противном случае, левый край вида остается в том же положении по отношению к левому краю супервида.
NSViewMaxXMarginЕсли установлено, правый край вида перемещается пропорционально изменению ширины супервида. В противном случае, правый край вида остается в том же положении по отношению к супервиду.
NSViewMinYMargin

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

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

NSViewMaxYMargin

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

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

Визуальное представление масок автоматического изменения размера вида

NSView маски автоизменения размеров вида

Скрытие видов

Для того, чтобы сделать вид видимым или невидимым в Cococa приложении используется метод класса NSView - setHidden:, с аргументом YES для скрытия и NO для отображения вида.

Когда вы скрываете вид используя метод setHidden:, вид остается в иерархии, даже если он исчезает из окна и не получает событий ввода. Скрытый вид остается в списке вложенных видов супервида и участвует в автоматическом изменении размеров. Если виды помечены как скрытые все их подвиды, и их потомки спрятаны также. При скрытии вида Application Kit также отключает любые курсоры, всплывающие подсказки или любые отслеживания связанные с видом.

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

Узнать статус отображения вида можно следующими методами: isHidden или isHiddenOrHasHiddenAncestor, первый метод возвращает YES если вид помечен как скрытый. Последний метод возвращает YES если вид является скрытым, по причине того, что вид, находящийся выше в иерархии помечен как скрытый.

Конвертирование координат в иерархии видов

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

Преобразовать в приемник из указанного видаПреобразование от приемника к указанному виду
convertPoint:fromView:convertPoint:toView:
convertRect:fromView:convertRect:toView:
convertSize:fromView:convertSize:toView:

Методы convert...:fromView: конвертируют значения в координатную систему объекта-приемника из координатной системы переданного вида в качестве второго аргумента. Если второй аргумент равен nil, то преобразуются координаты окна, содержащего объект-приемник. Метод convertPoint:fromView: обычно используется для преобразования событий мыши, переданных через NSEvent в окно. Ниже приведен пример обработки события мыши в окне.

-(void)mouseDown:(NSEvent *)event
{
    NSPoint clickLocation;

    //конвертирование точки нажатия в систему координат вида
    clickLocation = [self convertPoint:[event locationInWindow]
                              fromView:nil];
    // делаем, что-либо с полученными координатами
}

Методы convert..:toView: переводят координаты из объекта-приемника в систему координат переданного вида в качестве параметра. При передаче в качестве параметра вида значения nil, координаты преобразуются в координаты окна.

Для преобразования в и из координат экрана используются методы NSWindow: convertBaseToScreen: и convertScreenToBase: соответственно. Преобразование координат вида в координаты экрана, возможно только преобразовав сначала в оконные координаты и затем, только в экранные.

NSPoint pointInWindowCoordinates;
NSPoint pointInScreenCoords;

pointInWindowCoordinates=[self convertPoint:viewLocation toView:nil];
pointInScreenCoords=[[self window] convertBaseToScreen:pointInWindowCoordinates];

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

При преобразовании размера, NSView просто воспринимает его как дельту смещения (0.0, 0.0), что вам нужно конвертировать из одного вида в другой. Хотя расстояние смещения остается тем же, баланс по двум осям смещается в зависимости от вращения. Полезно отметить, что в преобразовании размеров Cocoa всегда возвращает размеры, которые состоят из положительных чисел.

Преобразование координат вида в и из базового пространства

Начиная с Mac OS X Leopard NSView предоставляет новый набор методов для преобразования выравнивания пикселей из содержимого вида. Это предоставляет возможность преобразования из и в базовое пространство координат скрытого буфера, в котором строится изображение вида:

- (NSRect)convertRectToBase:(NSRect)aRect;

- (NSPoint)convertPointToBase:(NSPoint)aPoint;

- (NSSize)convertSizeToBase:(NSSize)aSize;

- (NSRect)convertRectFromBase:(NSRect)aRect;

- (NSPoint)convertPointFromBase:(NSPoint)aPoint;

- (NSSize)convertSizeFromBase:(NSSize)aSize;

Для преобразования эти методы ведут себя аналогично выше разобранным методам, которым в качестве аргумента вида передан nil

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

 
 
homeЗаметили ошибкукарта сайта 
   Made on a Mac