Views
Представление основной объект для отображения информации и приема событий от клавиатуры и мыши. Реальные представления являются подклассами NSView.
Представления можно разделить на:
- Контролы (кпопки, текстовые поля и т.п.), с которыми пользователь может совершать действия. Обычно идут вместе с ячейками, которые не являются производными от NSView.
- Контейнеры. Содержат (более удобно оформляют) более примитивные представления. NSTextView, NSImageView, NSBox, NSSplitView, and NSTabView.
- Составные представления. Объединяют несколько представлений.
- Оболочки. Дают доступ к некоторым системным возможностям (NSOpenGLView and NSMovieView).
The View Hierarchy
Представления объединены в иерархию. У каждого есть родитель (superview). Базовый родитель - Content View. У него есть только закрытый superview.
Система координат к каждого представления своя.
Каждое предсталение знает о
- окне
- superview
- дочерних представлениях
View Geometry and Coordinates
The Frame
Ограничивающий представление прямоугольник. Видимая область представления зависит от расположения родительских представлений.
Представления могут быть перемещены и повернуты относительно начала координат родительского представления.
The Bounds
В то время как frame задает размеры представления и его положение относительно родительского представления, bounds определяют область представления, в котором происходит отрисовка содержимого и обработка событий. По умолчанию frame и bounds совпадают. Т.о. совпадают и начала координат в левом нижнем углу. Однако, начало координат локальной системы координат представления можно перенести в левый верхний угол, что удобно при отображении текста сверху-вниз слева-направо. В этом случае получим flipped coordinates.
Возможно преобразование системы координат представления:
- начало координат bounds может быть перенесено из точки начала координат frame
- для bounds может быть свой масштаб по осям
- система коорнинат bounds может быть повернута относительно системы координат frame.
How Views Get Drawn
Хоть представление и отрисовывает себя само, но делает оно это не когда захочет, а когда будет помечено как требующее обновления. Оно может быть обновлено немедленно или в конце главного цикла событий.
Для немедленного обновления представлении вызываются display методы. При этом
- блокируется представление, требующее обновления
- вызывается метод представления drawRect:
- обновляется буфер окна
Хотя рекомендуется использовать auto-display mechanism. В этом случае все представления будут обновлены совместно с учетом их взаимного расположения.
Для обновления отдельного представления (целиком и по частям) существуют методы:
display, displayRect:, displayRectIgnoringOpacity:.
Для указания необходимости обновления при использовании auto-display mechanism:
setNeedsDisplay:, setNeedsDisplayInRect:
Т.е. этими методами представления помечаются для обновления.
Можно немедленно обновить помеченные представления:
displayIfNeeded, displayIfNeededInRect:, displayIfNeededIgnoringOpacity, эdisplayIfNeededInRectIgnoringOpacity:.
Этот способ промежуточный (в т.ч. по эффективности) между немедленным обновлением одного представления и автоматическим обновлением всех представлений.
Locking Focus
Для отрисовки на представление фиксируется фокус (lockFocus..., unlockFocus). При этом происходит:
- система координат представления становится текущей для всего приложения
- вычисляется прямоугольная область, за пределами которой отрисовка невозможна
- настривается среда для отрисовки
В каждый момент у окна фокус зафиксирован на одном или нескольких представлениях, которые отрисовываются в данный момент. У окна есть графический контекст, который содержит состояния, определяющие операции по отрисовке для представления, на котором стоит фокус отрисовки.
В состоянии находится:
матрица преобразований координат точек из одной системы координат в другую, а также ряд параметров
The current color for fill and stroke operations
Alpha value (transparency)
Line attributes, including width, join, cap, dash, and miter limit
Anti-aliasing value
Current color space
Text attributes: font, font size, character spacing
Blend mode
Может быть несколько представлений с зафиксированными фокусами. Это происходит в случае отрисовки группы связанных представлений. Фокусировка начинается с superview и идет далее к дочерним представлениям. При переходе к фокусировке на следующем представлении предыдущий фокус помещается в состояние, а состояние помещается в стек.
Текущим становится очередное состояние из стека.
What Happens in drawRect:
Как только на представлении фиксируется фокус, ему посылается сообщение drawRect:. Представление реализует этот метод. В метод передается прямоугольник, который будет отрисован. Он может не совпасть с bounds, т.к. является пересечением нескольких прямоугольников.
Основным правилом оптимизации отрисовки является отрисовка только нужных в данный момент областей как можно меньшего размера. Обращение к оконному серверу, координирующему отрисовку - дорогая операция и ее нужно выполнять только по необходимости. Поэтому отрисовка всего представления - наименее эффективный вариант. Лучше запросить у NSView список областей, требующих обновления с помощью getRectsBeingDrawn:count:
Методы, используемые в drawRect:
Drawing functions (declared in NSGraphics.h) to draw, fill, erase, and perform other operations with rectangles
Methods to construct lines and shapes with bezier paths (NSBezierPath class)
Methods to create and apply affine transforms, involving translation, scaling, and rotation operations (NSAffineTransform class)
Color and color-space methods (NSColor and NSColorSpace)
Methods for creating and compositing images (NSImage and various image-representation classes)
Methods for drawing text (NSString and NSAttributedString)
Эти методы напрямую обращаются к оконному серверу за реализациями из Core Graphics (Quartz). К реализациям можно обратиться и напрямую.
Threads and Drawing
Отрисовка необязательно может идти только из главной нити, однако изменения свойств NSView, например, прямоугольника для Frame, должно происходить только из главной нити. Кроме того, только одна нить может рисовать в данном представлении в данный момент времени.
Views and Events
Представления в первую очередь обрабатывают события от пользователя. Для этого представление реализует протокол NSResponder, в котором объявлены такие методы, как mouseDown:, mouseMoved:, and keyUp:. В эти методы как параметр передается объект NSEvent. Если представление не содержит подходящего обработчика, то он ищется у superview и далее по responder chain.
Responders and the Responder Chain
NSResponder определяет поведение NSApplication, NSWindow, and NSView с точки зрения обработки событий.
Сообщения о событиях делятся на
- события (event messages),
- действия (action messages), которые перенаправляются target-ам.
Также NSResponder задает механизм для управления responder chain, т.е. передачей событий по цепочке обработчиков.
У каждого окна есть своя цепочка responder chain. Основные объекты в ней - это NSWindow и семейство представлений. Чем ниже представление в иерархии, тем больше шансов, что именно оно обработает событие. У окна NSWindow есть первый обработчик (first responder), обычно выбранное представление в окне.
Для событийных сообщений цепочка обычно заканчивается на NSWindow, но есть возможность добавить и другие объекты после окна.
Для действий длина цепочки определяется следующими правилами:
- если в приложении есть главное окно и ключевое окно, то сначала действие пытается обработать цепочка ключевого окна, класс ключевого окна, его делегат, затем цепочка главного окна, класс главного окна, его делегат и наконец NSApp и его делегат.
- для каждого типа приложения simple, document-based, или приложение с window controller структура цепочки отличается.
Комментариев нет:
Отправить комментарий