1 /* Copyright (c) 2006-2007 Christopher J. W. Lloyd
2 2009-2010 Markus Hitter <mah@jump-ing.de>
4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
10 #import <AppKit/NSView.h>
11 #import <AppKit/NSApplication.h>
12 #import <AppKit/NSEvent.h>
13 #import <AppKit/NSWindow-Private.h>
14 #import <AppKit/NSCursor.h>
15 #import <AppKit/NSCursorRect.h>
16 #import <AppKit/NSTrackingArea.h>
17 #import <AppKit/NSMenu.h>
18 #import <AppKit/NSScrollView.h>
19 #import <AppKit/NSClipView.h>
20 #import <AppKit/NSColor.h>
21 #import <AppKit/NSGraphics.h>
22 #import <AppKit/NSGraphicsContextFunctions.h>
23 #import <AppKit/NSDraggingManager.h>
24 #import <AppKit/NSDragging.h>
25 #import <AppKit/NSPrintOperation.h>
26 #import <AppKit/NSPrintInfo.h>
27 #import <Foundation/NSKeyedArchiver.h>
28 #import <AppKit/NSPasteboard.h>
29 #import <AppKit/NSObject+BindingSupport.h>
30 #import <Onyx2D/O2Context.h>
31 #import <AppKit/NSRaise.h>
32 #import <AppKit/NSViewBackingLayer.h>
33 #import <CoreGraphics/CGWindow.h>
34 #import <QuartzCore/CALayerContext.h>
35 #import <QuartzCore/CATransaction.h>
37 NSString * const NSViewFrameDidChangeNotification=@"NSViewFrameDidChangeNotification";
38 NSString * const NSViewBoundsDidChangeNotification=@"NSViewBoundsDidChangeNotification";
39 NSString * const NSViewFocusDidChangeNotification=@"NSViewFocusDidChangeNotification";
41 @interface NSView(NSView_forward)
42 -(CGAffineTransform)transformFromWindow;
43 -(CGAffineTransform)transformToWindow;
44 -(CGAffineTransform)transformToLayer;
45 -(void)_trackingAreasChanged;
48 @implementation NSView
50 static BOOL NSViewLayersEnabled=NO;
53 NSViewLayersEnabled=[[NSUserDefaults standardUserDefaults] boolForKey:@"NSViewLayersEnabled"];
56 +(NSView *)focusView {
57 return [NSCurrentFocusStack() lastObject];
60 +(NSMenu *)defaultMenu {
64 +(NSFocusRingType)defaultFocusRingType {
65 NSUnimplementedMethod();
69 -(void)encodeWithCoder:(NSCoder *)coder {
70 NSUnimplementedMethod();
73 -initWithCoder:(NSCoder *)coder {
74 [super initWithCoder:coder];
76 if([coder allowsKeyedCoding]){
77 NSKeyedUnarchiver *keyed=(NSKeyedUnarchiver *)coder;
78 unsigned vFlags=[keyed decodeIntForKey:@"NSvFlags"];
81 if([keyed containsValueForKey:@"NSFrame"])
82 _frame=[keyed decodeRectForKey:@"NSFrame"];
83 else if([keyed containsValueForKey:@"NSFrameSize"])
84 _frame.size=[keyed decodeSizeForKey:@"NSFrameSize"];
86 _bounds.origin=NSMakePoint(0,0);
87 _bounds.size=_frame.size;
90 _subviews=[NSMutableArray new];
91 _postsNotificationOnFrameChange=YES;
92 _postsNotificationOnBoundsChange=YES;
93 _autoresizingMask=vFlags&0x3F;
94 if([keyed containsValueForKey:@"NSvFlags"])
95 _autoresizesSubviews=(vFlags&0x100)?YES:NO;
96 // Despite the fact it appears _autoresizesSubviews is encoded in the flags, it should always be ON
97 // *** Do not turn off or base on the flags unless you have an alternative for enabling it when it
99 _autoresizesSubviews=YES;
100 _isHidden=(vFlags&0x80000000)?YES:NO;
101 _tag= 0; // IB assigns a default tag id of 0 - which is different from the default in the docs.
102 if([keyed containsValueForKey:@"NSTag"])
103 _tag=[keyed decodeIntForKey:@"NSTag"];
105 // Subviews come in from the nib in back to front order
106 [_subviews addObjectsFromArray:[keyed decodeObjectForKey:@"NSSubviews"]];
107 [_subviews makeObjectsPerformSelector:@selector(viewWillMoveToSuperview:) withObject:self];
108 [_subviews makeObjectsPerformSelector:@selector(_setSuperview:) withObject:self];
109 [_subviews makeObjectsPerformSelector:@selector(viewDidMoveToSuperview)];
114 _trackingAreas=[[NSMutableArray alloc] init];
115 [self setWantsLayer:[keyed decodeBoolForKey:@"NSViewIsLayerTreeHost"]];
117 _layerContentsRedrawPolicy=[keyed decodeIntegerForKey:@"NSViewLayerContentsRedrawPolicy"];
119 _contentFilters=[[keyed decodeObjectForKey:@"NSViewContentFilters"] retain];
122 [NSException raise:NSInvalidArgumentException format:@"%@ can not initWithCoder:%@",isa,[coder class]];
129 return [self initWithFrame:NSMakeRect(0,0,1,1)];
132 -initWithFrame:(NSRect)frame {
134 _bounds.origin=NSMakePoint(0,0);
135 _bounds.size=frame.size;
139 _subviews=[NSMutableArray new];
140 _postsNotificationOnFrameChange=YES;
141 _postsNotificationOnBoundsChange=YES;
142 _autoresizesSubviews=YES;
143 _autoresizingMask=NSViewNotSizable;
144 _tag=-1; // according to the docs - loading from a nib gets a default of 0.
148 _trackingAreas=[[NSMutableArray alloc] init];
151 _transformFromWindow=CGAffineTransformIdentity;
152 _transformToWindow=CGAffineTransformIdentity;
153 _transformToLayer=CGAffineTransformIdentity;
161 [self _unbindAllBindings];
167 [_subviews makeObjectsPerformSelector:@selector(_setSuperview:) withObject:nil];
170 [_draggedTypes release];
171 [_trackingAreas release];
172 [_contentFilters release];
174 if(_invalidRects!=NULL)
175 NSZoneFree(NULL,_invalidRects);
177 if (_rectsBeingRedrawn!=NULL) {
178 NSZoneFree(NULL, _rectsBeingRedrawn);
182 [_layerContext invalidate];
183 [_layerContext release];
188 static void invalidateTransform(NSView *self){
189 self->_validTransforms=NO;
190 self->_validTrackingAreas=NO;
192 for(NSView *check in self->_subviews)
193 invalidateTransform(check);
197 static CGAffineTransform concatViewTransform(CGAffineTransform result,NSView *view,NSView *superview,BOOL doFrame,BOOL flip){
198 NSRect bounds=[view bounds];
199 NSRect frame=[view frame];
202 result=CGAffineTransformTranslate(result,frame.origin.x,frame.origin.y);
204 // Apply bounds scaling to fit in the frame
205 CGAffineTransform scale = CGAffineTransformMakeScale(NSWidth(frame)/NSWidth(bounds), NSHeight(frame)/NSHeight(bounds));
206 result=CGAffineTransformConcat(scale,result);
209 CGAffineTransform flip=CGAffineTransformMake(1,0,0,-1,0,bounds.size.height);
211 result=CGAffineTransformConcat(flip,result);
213 result=CGAffineTransformTranslate(result,-bounds.origin.x,-bounds.origin.y);
218 -(CGAffineTransform)createTransformToWindow {
219 CGAffineTransform result;
220 NSView *superview=[self superview];
225 result=CGAffineTransformIdentity;
226 flip=[self isFlipped];
229 result=[superview transformToWindow];
230 flip=([self isFlipped]!=[superview isFlipped]);
233 result=concatViewTransform(result,self,superview,doFrame,flip);
238 -(CGAffineTransform)createTransformToLayer {
239 CGAffineTransform result=CGAffineTransformIdentity;
240 NSRect bounds=[self bounds];
242 if([self isFlipped]){
243 CGAffineTransform flip=CGAffineTransformMake(1,0,0,-1,0,bounds.size.height);
245 result=CGAffineTransformConcat(flip,result);
247 result=CGAffineTransformTranslate(result,-bounds.origin.x,-bounds.origin.y);
252 -(NSRect)calculateVisibleRect {
253 if([self isHiddenOrHasHiddenAncestor])
256 if([self superview]==nil)
257 return [self bounds];
259 NSRect result=[[self superview] visibleRect];
261 result=[self convertRect:result fromView:[self superview]];
263 result=NSIntersectionRect(result,[self bounds]);
269 static inline void configureLayerGeometry(NSView *self){
270 CALayer *layer=self->_layer;
275 [CATransaction begin];
276 [CATransaction setDisableActions:YES];
278 [layer setAnchorPoint:CGPointMake(0,0)];
280 if([layer superlayer]==nil)
281 [layer setPosition:CGPointMake(0,0)];
283 [layer setPosition:self->_frame.origin];
285 [layer setBounds:self->_bounds];
286 [CATransaction commit];
289 static inline void buildTransformsIfNeeded(NSView *self) {
290 if(!self->_validTransforms){
291 self->_transformToWindow=[self createTransformToWindow];
292 self->_transformFromWindow=CGAffineTransformInvert(self->_transformToWindow);
293 self->_transformToLayer=[self createTransformToLayer];
294 self->_validTransforms=YES;
296 self->_visibleRect=[self calculateVisibleRect];
297 configureLayerGeometry(self);
301 -(CGAffineTransform)transformFromWindow {
302 buildTransformsIfNeeded(self);
304 return _transformFromWindow;
307 -(CGAffineTransform)transformToWindow {
308 buildTransformsIfNeeded(self);
310 return _transformToWindow;
314 -(CGAffineTransform)transformToLayer {
315 buildTransformsIfNeeded(self);
317 return _transformToLayer;
324 -(CGFloat)frameRotation {
325 return _frameRotation;
328 -(CGFloat)frameCenterRotation {
329 NSUnimplementedMethod();
337 -(CGFloat)boundsRotation {
338 return _boundsRotation;
341 -(BOOL)isRotatedFromBase {
342 NSUnimplementedMethod();
346 -(BOOL)isRotatedOrScaledFromBase {
347 NSUnimplementedMethod();
351 -(void)translateOriginToPoint:(NSPoint)point {
352 NSUnimplementedMethod();
355 -(void)rotateByAngle:(CGFloat)angle {
356 [self setBoundsRotation:[self boundsRotation]+angle];
359 -(BOOL)postsFrameChangedNotifications {
360 return _postsNotificationOnFrameChange;
363 -(BOOL)postsBoundsChangedNotifications {
364 return _postsNotificationOnBoundsChange;
367 -(void)scaleUnitSquareToSize:(NSSize)size {
368 NSUnimplementedMethod();
371 -(NSWindow *)window {
375 -(NSView *)superview {
379 -(BOOL)isDescendantOf:(NSView *)other {
386 check=[check superview];
392 -(NSView *)ancestorSharedWithView:(NSView *)view {
393 NSUnimplementedMethod();
397 -(NSScrollView *)enclosingScrollView {
398 id result=[self superview];
400 for(;result!=nil;result=[result superview])
401 if([result isKindOfClass:[NSScrollView class]])
407 -(NSRect)adjustScroll:(NSRect)toRect {
408 NSUnimplementedMethod();
412 -(NSArray *)subviews {
416 -(BOOL)autoresizesSubviews {
417 return _autoresizesSubviews;
420 -(unsigned)autoresizingMask {
421 return _autoresizingMask;
424 -(NSFocusRingType)focusRingType {
425 return _focusRingType;
440 -(CGFloat)alphaValue {
441 NSUnimplementedMethod();
445 -(void)setAlphaValue:(CGFloat)alpha {
446 NSUnimplementedMethod();
453 -(NSRect)visibleRect {
454 buildTransformsIfNeeded(self);
459 -(BOOL)wantsDefaultClipping {
460 NSUnimplementedMethod();
464 -(NSBitmapImageRep *)bitmapImageRepForCachingDisplayInRect:(NSRect)rect {
465 NSUnimplementedMethod();
469 -(void)cacheDisplayInRect:(NSRect)rect toBitmapImageRep:(NSBitmapImageRep *)imageRep {
470 NSUnimplementedMethod();
477 -(BOOL)isHiddenOrHasHiddenAncestor {
478 return _isHidden || [_superview isHiddenOrHasHiddenAncestor];
481 -(void)setHidden:(BOOL)flag {
484 if (_isHidden != flag) {
485 invalidateTransform(self);
486 if ((_isHidden = flag)) {
487 id view=[_window firstResponder];
489 if ([view isKindOfClass:[NSView class]])
490 for (; view; view = [view superview]) {
492 [_window makeFirstResponder:[self nextValidKeyView]];
498 [[self superview] setNeedsDisplay:YES];
503 [self viewDidUnhide];
511 -(void)viewDidUnhide {
515 -(BOOL)canBecomeKeyView {
516 return [self acceptsFirstResponder] && ![self isHiddenOrHasHiddenAncestor];
519 // Cocoa does that for views, despite the "The default implementation returns NO" from the documentation
520 -(BOOL)needsPanelToBecomeKey {
521 return [self acceptsFirstResponder];
524 -(NSView *)nextKeyView {
528 -(NSView *)nextValidKeyView {
529 NSView *result=[self nextKeyView];
531 while(result!=nil && ![result canBecomeKeyView]) {
532 // prevent an infinite loop
536 result=[result nextKeyView];
543 -(NSView *)previousKeyView {
544 return _previousKeyView;
547 -(NSView *)previousValidKeyView {
548 NSView *result=[self previousKeyView];
550 while(result!=nil && ![result canBecomeKeyView]) {
551 // prevent an infinite loop
554 result=[result previousKeyView];
564 -(NSMenu *)menuForEvent:(NSEvent *)event {
565 NSMenu *result=[self menu];
568 result=[isa defaultMenu];
571 NSArray *itemArray=[result itemArray];
572 int i,count=[itemArray count];
573 for(i=0;i<count;i++) {
574 NSMenuItem *item = [itemArray objectAtIndex:i];
575 [item setTarget:self];
583 -(NSMenuItem *)enclosingMenuItem {
584 NSUnimplementedMethod();
588 -(NSString *)toolTip {
589 NSUInteger i,count=[_trackingAreas count];
590 NSString *toolTip=nil;
592 // In case there's more than one ToolTip the behavior
593 // is undocumented. Return the first one.
594 for(i=0;i<count;i++){
595 NSTrackingArea *area=[_trackingAreas objectAtIndex:i];
597 if([area _isToolTip]==YES){
598 toolTip=[area owner];
606 -viewWithTag:(int)tag {
607 int i,count=[_subviews count];
612 for(i=0;i<count;i++){
613 NSView *view=[[_subviews objectAtIndex:i] viewWithTag:tag];
622 -(NSView *)hitTest:(NSPoint)point
628 point = [self convertPoint:point fromView:[self superview]];
630 if(NSMouseInRect(point, [self visibleRect], [self isFlipped]) == NO){
633 // Subviews are ordered back to front so we need to go
634 // front to back in order to hit test correctly.
635 NSArray *subviews = [self subviews];
636 int count = [subviews count];
638 while (--count >= 0) {
639 NSView *check = [subviews objectAtIndex: count];
640 NSView *hit = [check hitTest: point];
650 -(NSPoint)convertPoint:(NSPoint)point fromView:(NSView *)viewOrNil {
651 NSView *fromView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView];
652 CGAffineTransform toWindow=[fromView transformToWindow];
653 CGAffineTransform fromWindow=[self transformFromWindow];
655 return CGPointApplyAffineTransform(CGPointApplyAffineTransform(point,toWindow),fromWindow);
658 -(NSPoint)convertPoint:(NSPoint)point toView:(NSView *)viewOrNil {
659 NSView *toView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView];
660 CGAffineTransform toWindow=[self transformToWindow];
661 CGAffineTransform fromWindow=[toView transformFromWindow];
663 return CGPointApplyAffineTransform(CGPointApplyAffineTransform(point,toWindow),fromWindow);
666 -(NSSize)convertSize:(NSSize)size fromView:(NSView *)viewOrNil {
667 NSView *fromView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView];
668 CGAffineTransform toWindow=[fromView transformToWindow];
669 CGAffineTransform fromWindow=[self transformFromWindow];
671 return CGSizeApplyAffineTransform(CGSizeApplyAffineTransform(size,toWindow),fromWindow);
674 -(NSSize)convertSize:(NSSize)size toView:(NSView *)viewOrNil {
675 NSView *toView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView];
676 CGAffineTransform toWindow=[self transformToWindow];
677 CGAffineTransform fromWindow=[toView transformFromWindow];
679 return CGSizeApplyAffineTransform(CGSizeApplyAffineTransform(size,toWindow),fromWindow);
682 -(NSRect)convertRect:(NSRect)rect fromView:(NSView *)viewOrNil {
683 NSView *fromView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView];
684 CGAffineTransform toWindow=[fromView transformToWindow];
685 CGAffineTransform fromWindow=[self transformFromWindow];
686 NSPoint point1=rect.origin;
687 NSPoint point2=NSMakePoint(NSMaxX(rect),NSMaxY(rect));
689 point1= CGPointApplyAffineTransform(CGPointApplyAffineTransform(point1,toWindow),fromWindow);
690 point2= CGPointApplyAffineTransform(CGPointApplyAffineTransform(point2,toWindow),fromWindow);
691 if(point2.y<point1.y){
697 return NSMakeRect(point1.x,point1.y,point2.x-point1.x,point2.y-point1.y);
700 -(NSRect)convertRect:(NSRect)rect toView:(NSView *)viewOrNil {
701 NSView *toView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView];
702 CGAffineTransform toWindow=[self transformToWindow];
703 CGAffineTransform fromWindow=[toView transformFromWindow];
704 NSPoint point1=rect.origin;
705 NSPoint point2=NSMakePoint(NSMaxX(rect),NSMaxY(rect));
707 point1= CGPointApplyAffineTransform(CGPointApplyAffineTransform(point1,toWindow),fromWindow);
708 point2= CGPointApplyAffineTransform(CGPointApplyAffineTransform(point2,toWindow),fromWindow);
709 if(point2.y<point1.y){
715 return NSMakeRect(point1.x,point1.y,point2.x-point1.x,point2.y-point1.y);
718 -(NSRect)centerScanRect:(NSRect)rect {
719 float minx=floor(NSMinX(rect)+0.5);
720 float miny=floor(NSMinY(rect)+0.5);
721 float maxx=floor(NSMaxX(rect)+0.5);
722 float maxy=floor(NSMaxY(rect)+0.5);
724 return NSMakeRect(minx,miny,maxx-minx,maxy-miny);
727 -(void)setFrame:(NSRect)frame {
728 // Cocoa does not post the notification if the frames are equal
729 // Possible that resizeSubviewsWithOldSize is not called if the sizes are equal
730 if(NSEqualRects(_frame,frame))
733 NSSize oldSize=_bounds.size;
735 if (_bounds.size.width == 0 || _bounds.size.height == 0) {
736 // No valid current bounds value - just update it to use the frame size
737 _bounds.size=frame.size;
739 // Get the bounds->frame transform
740 CGAffineTransform transform=concatViewTransform(CGAffineTransformIdentity,self,nil,YES,NO);
741 // ... and invert it so we can get the new bounds size from the new frame size
742 transform = CGAffineTransformInvert(transform);
744 _bounds.size=CGSizeApplyAffineTransform(frame.size, transform);
748 [_window invalidateCursorRectsForView:self]; // this also invalidates tracking areas
750 if(_autoresizesSubviews){
751 [self resizeSubviewsWithOldSize:oldSize];
754 NSRect layerFrame=_frame;
757 layerFrame=[_superview convertRect:layerFrame toView:nil];
759 [_layerContext setFrame:layerFrame];
761 invalidateTransform(self);
763 if(_postsNotificationOnFrameChange)
764 [[NSNotificationCenter defaultCenter] postNotificationName:NSViewFrameDidChangeNotification object:self];
767 -(void)setFrameSize:(NSSize)size {
771 [self setFrame:frame];
774 -(void)setFrameOrigin:(NSPoint)origin {
775 NSRect frame=[self frame];
778 [self setFrame:frame];
781 -(void)setFrameRotation:(CGFloat)angle {
782 NSUnimplementedMethod();
785 -(void)setFrameCenterRotation:(CGFloat)angle {
786 NSUnimplementedMethod();
789 -(void)setBounds:(NSRect)bounds {
790 if (!NSEqualRects(bounds, _bounds)) {
792 invalidateTransform(self);
794 [_window invalidateCursorRectsForView:self]; // this also invalidates tracking areas
796 if(_postsNotificationOnBoundsChange)
797 [[NSNotificationCenter defaultCenter] postNotificationName:NSViewBoundsDidChangeNotification object:self];
801 -(void)setBoundsSize:(NSSize)size {
802 NSRect bounds=[self bounds];
806 [self setBounds:bounds];
809 -(void)setBoundsOrigin:(NSPoint)origin {
810 NSRect bounds=[self bounds];
812 bounds.origin=origin;
814 [self setBounds:bounds];
817 -(void)setBoundsRotation:(CGFloat)angle {
818 NSUnimplementedMethod();
821 -(void)setPostsFrameChangedNotifications:(BOOL)flag {
822 _postsNotificationOnFrameChange=flag;
825 -(void)setPostsBoundsChangedNotifications:(BOOL)flag {
826 _postsNotificationOnBoundsChange=flag;
829 -(void)_setWindow:(NSWindow *)window {
830 if (_window != window) {
831 BOOL windowRecalulatesKeyViewLoop = [window autorecalculatesKeyViewLoop];
832 if (windowRecalulatesKeyViewLoop)
833 [self setNextKeyView:nil];
835 [self viewWillMoveToWindow:window];
839 [_subviews makeObjectsPerformSelector:_cmd withObject:window];
840 _validTrackingAreas=NO;
841 [_window invalidateCursorRectsForView:self]; // this also invalidates tracking areas
843 if (windowRecalulatesKeyViewLoop)
844 [_window recalculateKeyViewLoop];
846 [self viewDidMoveToWindow];
850 -(void)_setSuperview:superview {
851 _superview=superview;
853 [_window invalidateCursorRectsForView:self]; // this also invalidates tracking areas
855 [self setNextResponder:superview];
858 -(void)_insertSubview:(NSView *)view atIndex:(unsigned)index {
861 if([view superview]==self)
862 [_subviews removeObjectIdenticalTo:view];
864 [view removeFromSuperview];
866 [view _setWindow:_window];
868 [view viewWillMoveToSuperview:self];
869 [view _setSuperview:self];
872 if(index==NSNotFound)
873 [_subviews addObject:view];
875 [_subviews insertObject:view atIndex:index];
878 invalidateTransform(view);
880 [self setNeedsDisplayInRect:[view frame]];
882 [view viewDidMoveToSuperview];
885 [view setWantsLayer:YES];
888 -(void)addSubview:(NSView *)view {
889 if(view==nil) // yes, this is silently ignored
892 [self _insertSubview:view atIndex:NSNotFound];
895 -(void)addSubview:(NSView *)view positioned:(NSWindowOrderingMode)ordering relativeTo:(NSView *)relativeTo {
896 unsigned index=[_subviews indexOfObjectIdenticalTo:relativeTo];
898 if(index==NSNotFound)
899 index=(ordering==NSWindowBelow)?0:NSNotFound;
901 index=(ordering==NSWindowBelow)?index:((index+1==[_subviews count])?NSNotFound:index+1);
903 [self _insertSubview:view atIndex:index];
906 -(void)replaceSubview:(NSView *)oldView with:(NSView *)newView {
907 unsigned index=[_subviews indexOfObjectIdenticalTo:oldView];
910 [oldView removeFromSuperview];
911 [self _insertSubview:newView atIndex:index];
915 -(void)setSubviews:(NSArray *)array {
916 // This method marks as needing display per doc.s
918 while([_subviews count])
919 [[_subviews lastObject] removeFromSuperview];
921 for(NSView *view in array){
922 [self addSubview:view];
923 [view setNeedsDisplay:YES];
927 -(void)sortSubviewsUsingFunction:(NSComparisonResult (*)(id, id, void *))compareFunction context:(void *)context {
928 NSUnimplementedMethod();
931 -(void)didAddSubview:(NSView *)subview {
932 NSUnimplementedMethod();
935 -(void)willRemoveSubview:(NSView *)subview {
936 NSUnimplementedMethod();
939 -(void)setAutoresizesSubviews:(BOOL)flag {
940 _autoresizesSubviews=flag;
943 -(void)setAutoresizingMask:(unsigned int)mask {
944 _autoresizingMask=mask;
947 -(void)setFocusRingType:(NSFocusRingType)value {
948 _focusRingType=value;
949 [self setNeedsDisplay:YES];
952 -(void)setTag:(int)tag {
956 -(void)_setPreviousKeyView:(NSView *)previous {
957 _previousKeyView = previous;
960 -(void)setNextKeyView:(NSView *)next {
962 [next _setPreviousKeyView:self];
964 [_nextKeyView _setPreviousKeyView:nil];
969 -(BOOL)acceptsFirstMouse:(NSEvent *)event {
970 NSUnimplementedMethod();
974 -(BOOL)acceptsTouchEvents {
975 NSUnimplementedMethod();
979 -(void)setAcceptsTouchEvents:(BOOL)accepts {
980 NSUnimplementedMethod();
983 -(BOOL)wantsRestingTouches {
984 NSUnimplementedMethod();
988 -(void)setWantsRestingTouches:(BOOL)wants {
989 NSUnimplementedMethod();
992 -(void)setToolTip:(NSString *)string {
993 [self removeAllToolTips];
994 if(string!=nil && ![string isEqualToString:@""])
995 [self addToolTipRect:[self bounds] owner:string userData:NULL];
998 -(NSToolTipTag)addToolTipRect:(NSRect)rect owner:object userData:(void *)userData {
999 NSTrackingArea *area=nil;
1001 area=[[NSTrackingArea alloc] _initWithRect:rect options:0 owner:object userData:userData retainUserData:NO isToolTip:YES isLegacy:NO];
1002 [_trackingAreas addObject:area];
1005 [self _trackingAreasChanged];
1010 -(void)removeToolTip:(NSToolTipTag)tag {
1011 [self removeTrackingArea:tag];
1014 -(void)removeAllToolTips {
1015 NSInteger count=[_trackingAreas count];
1018 if([[_trackingAreas objectAtIndex:count] _isToolTip]==YES)
1019 [_trackingAreas removeObjectAtIndex:count];
1022 [self _trackingAreasChanged];
1025 -(void)addCursorRect:(NSRect)rect cursor:(NSCursor *)cursor {
1026 NSCursorRect *cursorRect=[[NSCursorRect alloc] initWithCursor:cursor];
1027 NSTrackingArea *area=nil;
1029 area=[[NSTrackingArea alloc] _initWithRect:rect options:NSTrackingCursorUpdate|NSTrackingActiveInKeyWindow owner:cursorRect userData:NULL retainUserData:NO isToolTip:NO isLegacy:YES];
1030 [_trackingAreas addObject:area];
1032 [cursorRect release];
1034 [self _trackingAreasChanged];
1037 -(void)removeCursorRect:(NSRect)rect cursor:(NSCursor *)cursor {
1038 NSInteger count=[_trackingAreas count];
1041 NSTrackingArea *area=[_trackingAreas objectAtIndex:count];
1042 NSObject *candidate=[area owner];
1044 if([area _isLegacy]==YES &&
1045 [candidate isKindOfClass:[NSCursorRect class]]==YES &&
1046 [(NSCursorRect *)candidate cursor]==cursor){
1047 [_trackingAreas removeObjectAtIndex:count];
1052 [self _trackingAreasChanged];
1055 -(void)discardCursorRects {
1056 NSInteger count=[_trackingAreas count];
1059 NSTrackingArea *area=[_trackingAreas objectAtIndex:count];
1061 if([area _isLegacy]==YES && ([area options]&NSTrackingCursorUpdate)){
1062 [_trackingAreas removeObjectAtIndex:count];
1066 [[self subviews] makeObjectsPerformSelector:_cmd];
1068 [self _trackingAreasChanged];
1071 -(void)resetCursorRects {
1075 -(void)_collectTrackingAreasForWindowInto:(NSMutableArray *)collector {
1079 if(!_validTrackingAreas){
1080 /* We don't clear the tracking areas, they are managed by the view with add/remove
1082 [self updateTrackingAreas];
1083 _validTrackingAreas=YES;
1086 count=[_trackingAreas count];
1087 for(i=0;i<count;i++){
1088 NSTrackingArea *area=[_trackingAreas objectAtIndex:i];
1089 NSRect rectOfInterest;
1091 rectOfInterest=NSIntersectionRect([area rect], [self bounds]);
1093 if(rectOfInterest.size.width>0. && rectOfInterest.size.height>0.){
1094 [area _setView:self];
1096 [area _setRectInWindow:[self convertRect:rectOfInterest toView:nil]];
1098 [collector addObject:[_trackingAreas objectAtIndex:i]];
1102 NSArray *subviews=[self subviews];
1103 // Collect subviews' areas _after_ collecting our own.
1104 count=[subviews count];
1105 for(i=0;i<count;i++)
1106 [(NSView *)[subviews objectAtIndex:i] _collectTrackingAreasForWindowInto:collector];
1110 -(NSArray *)trackingAreas {
1111 return _trackingAreas;
1114 -(void)_trackingAreasChanged {
1115 [[self window] _invalidateTrackingAreas];
1118 -(void)addTrackingArea:(NSTrackingArea *)trackingArea {
1119 [_trackingAreas addObject:trackingArea];
1120 [self _trackingAreasChanged];
1123 -(void)removeTrackingArea:(NSTrackingArea *)trackingArea {
1124 [_trackingAreas removeObjectIdenticalTo:trackingArea];
1125 [self _trackingAreasChanged];
1128 -(void)updateTrackingAreas {
1129 [self _trackingAreasChanged];
1132 -(NSTrackingRectTag)addTrackingRect:(NSRect)rect owner:owner userData:(void *)userData assumeInside:(BOOL)assumeInside {
1133 NSTrackingAreaOptions options=NSTrackingMouseEnteredAndExited|NSTrackingActiveAlways;
1134 NSTrackingArea *area=nil;
1136 if(assumeInside==YES)
1137 options|=NSTrackingAssumeInside;
1139 area=[[NSTrackingArea alloc] _initWithRect:rect options:options owner:owner userData:NULL retainUserData:NO isToolTip:NO isLegacy:NO];
1140 [_trackingAreas addObject:area];
1143 [self _trackingAreasChanged];
1148 -(void)removeTrackingRect:(NSTrackingRectTag)tag {
1149 [self removeTrackingArea:tag];
1152 -(NSTextInputContext *)inputContext {
1153 NSUnimplementedMethod();
1157 -(void)registerForDraggedTypes:(NSArray *)types {
1159 [_draggedTypes release];
1160 _draggedTypes=types;
1163 -(void)unregisterDraggedTypes {
1164 [_draggedTypes release];
1168 -(NSArray *)registeredDraggedTypes {
1169 return _draggedTypes;
1172 -(void)_deepResignFirstResponder {
1173 if([_window firstResponder]==self)
1174 [_window makeFirstResponder:nil];
1176 [[self subviews] makeObjectsPerformSelector:_cmd];
1179 -(void)removeFromSuperview {
1180 [_superview setNeedsDisplayInRect:[self frame]];
1181 [self removeFromSuperviewWithoutNeedingDisplay];
1184 -(void)_removeViewWithoutDisplay:(NSView *)view {
1185 [_subviews removeObjectIdenticalTo:view];
1188 -(void)removeFromSuperviewWithoutNeedingDisplay {
1189 NSView *removeFrom=_superview;
1190 NSWindow *window=[self window];
1192 [self _deepResignFirstResponder];
1193 [self _setSuperview:nil];
1194 [self _setWindow:nil];
1196 [removeFrom _removeViewWithoutDisplay:self];
1197 [window _invalidateTrackingAreas];
1200 -(void)viewWillMoveToSuperview:(NSView *)view {
1201 // Intentionally empty.
1204 -(void)viewDidMoveToSuperview {
1205 // Intentionally empty.
1208 -(void)viewWillMoveToWindow:(NSWindow *)window {
1209 // Intentionally empty.
1212 -(void)viewDidMoveToWindow {
1213 // Default implementation does nothing
1216 -(BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)event {
1217 NSUnimplementedMethod();
1221 -(void)resizeSubviewsWithOldSize:(NSSize)oldSize {
1222 int i,count=[_subviews count];
1224 for(i=0;i<count;i++)
1225 [[_subviews objectAtIndex:i] resizeWithOldSuperviewSize:oldSize];
1228 -(void)resizeWithOldSuperviewSize:(NSSize)oldSize {
1229 NSRect superFrame=[_superview frame];
1230 NSRect frame=[self frame];
1231 BOOL originChanged=NO,sizeChanged=NO;
1233 if(_autoresizingMask&NSViewMinXMargin){
1234 if(_autoresizingMask&NSViewWidthSizable){
1235 if(_autoresizingMask&NSViewMaxXMargin){
1236 frame.origin.x+=((superFrame.size.width-oldSize.width)/3);
1237 frame.size.width+=((superFrame.size.width-oldSize.width)/3);
1240 frame.origin.x+=((superFrame.size.width-oldSize.width)/2);
1241 frame.size.width+=((superFrame.size.width-oldSize.width)/2);
1246 else if(_autoresizingMask&NSViewMaxXMargin){
1247 frame.origin.x+=((superFrame.size.width-oldSize.width)/2);
1251 frame.origin.x+=superFrame.size.width-oldSize.width;
1255 else if(_autoresizingMask&NSViewWidthSizable){
1256 if(_autoresizingMask&NSViewMaxXMargin)
1257 frame.size.width+=((superFrame.size.width-oldSize.width)/2);
1259 frame.size.width+=superFrame.size.width-oldSize.width;
1262 else if(_autoresizingMask&NSViewMaxXMargin){
1263 // don't move or resize
1267 if(_autoresizingMask& NSViewMinYMargin){
1268 if(_autoresizingMask& NSViewHeightSizable){
1269 if(_autoresizingMask& NSViewMaxYMargin){
1270 frame.origin.y+=((superFrame.size.height-oldSize.height)/3);
1271 frame.size.height+=((superFrame.size.height-oldSize.height)/3);
1274 frame.origin.y+=((superFrame.size.height-oldSize.height)/2);
1275 frame.size.height+=((superFrame.size.height-oldSize.height)/2);
1280 else if(_autoresizingMask& NSViewMaxYMargin){
1281 frame.origin.y+=((superFrame.size.height-oldSize.height)/2);
1285 frame.origin.y+=superFrame.size.height-oldSize.height;
1289 else if(_autoresizingMask&NSViewHeightSizable){
1290 if(_autoresizingMask& NSViewMaxYMargin)
1291 frame.size.height+=((superFrame.size.height-oldSize.height)/2);
1293 frame.size.height+=superFrame.size.height-oldSize.height;
1297 if(originChanged || sizeChanged)
1298 [self setFrame:frame];
1301 -(BOOL)inLiveResize {
1302 return _inLiveResize;
1305 -(BOOL)preservesContentDuringLiveResize {
1306 NSUnimplementedMethod();
1310 -(NSRect)rectPreservedDuringLiveResize {
1311 NSUnimplementedMethod();
1315 -(void)viewWillStartLiveResize {
1317 [_subviews makeObjectsPerformSelector:_cmd];
1320 -(void)viewDidEndLiveResize {
1322 [_subviews makeObjectsPerformSelector:_cmd];
1325 -(BOOL)enterFullScreenMode:(NSScreen *)screen withOptions:(NSDictionary *)options {
1326 NSUnimplementedMethod();
1330 -(BOOL)isInFullScreenMode {
1331 // dont issue warning
1335 -(void)exitFullScreenModeWithOptions:(NSDictionary *)options {
1336 NSUnimplementedMethod();
1339 -(NSClipView *)_enclosingClipView {
1340 id result=[self superview];
1342 for(;result!=nil;result=[result superview])
1343 if([result isKindOfClass:[NSClipView class]])
1349 -(void)scrollPoint:(NSPoint)point {
1350 NSClipView *clipView=[self _enclosingClipView];
1353 NSPoint origin=[self convertPoint:point toView:clipView];
1355 [clipView scrollToPoint:origin];
1359 -(BOOL)scrollRectToVisible:(NSRect)rect {
1360 NSClipView *clipView = [self _enclosingClipView];
1361 NSView *documentView = [clipView documentView];
1362 // Current the document view visible rect in document view space
1363 NSRect vRect = [clipView documentVisibleRect];
1364 // Convert what we want in the document view space
1365 rect = [documentView convertRect:rect fromView:self];
1367 // Do the minimal amount of scrolling to show the rect
1369 // Missing amount on the four directions
1370 float missingLeft = NSMinX(vRect) - NSMinX(rect);
1371 float missingRight = NSMaxX(rect) - NSMaxX(vRect);
1373 float missingTop = NSMinY(vRect) - NSMinY(rect);
1374 float missingBottom = NSMaxY(rect) - NSMaxY(vRect);
1379 if (missingLeft * missingRight < 0) {
1380 // We need to scroll in one direction - no need to scroll if we're missing bits both ways or
1381 // if everything is visible
1383 // Let's do the minimal amount of scrolling
1384 if (fabs(missingLeft) < fabs(missingRight)) {
1391 if (missingTop * missingBottom < 0) {
1392 // We need to scroll in one direction - no need to scroll if we're missing bits both ways or
1393 // if everything is visible
1395 // Let's do the minimal amount of scrolling
1396 if (fabs(missingTop) < fabs(missingBottom)) {
1402 if (dx != 0 || dy != 0) {
1403 NSPoint pt = vRect.origin;
1406 pt = [documentView convertPoint:pt toView:clipView];
1407 [clipView scrollToPoint:pt];
1413 -(void)scrollClipView:(NSClipView *)clipView toPoint:(NSPoint)newOrigin {
1414 NSUnimplementedMethod();
1417 -(BOOL)mouse:(NSPoint)point inRect:(NSRect)rect {
1418 return NSMouseInRect(point, rect, [self isFlipped]);
1421 -(void)reflectScrolledClipView:(NSClipView *)view {
1422 NSUnimplementedMethod();
1425 -(void)allocateGState {
1429 -(void)releaseGState {
1433 -(void)setUpGState {
1437 -(void)renewGState {
1449 -(CALayer *)makeBackingLayer {
1450 return [NSViewBackingLayer layer];
1453 -(void)_removeLayerFromSuperlayer {
1454 [_layer removeFromSuperlayer];
1455 [_layerContext invalidate];
1456 [_layerContext release];
1460 -(void)_createLayerContextIfNeeded {
1461 if([_superview layer]==nil){
1462 _layerContext=[[CALayerContext alloc] initWithFrame:[self frame]];
1463 [_layerContext setLayer:_layer];
1467 -(void)_addLayerToSuperlayer {
1468 [[_superview layer] addSublayer:_layer];
1469 [self _createLayerContextIfNeeded];
1473 When turning off layering, we only turn off layers below us which did not want a layer
1474 Layers which did want a layer are not touched, nor are their children.
1476 -(void)_removeLayerBackedViewsFromTree {
1478 [self _createLayerContextIfNeeded];
1480 [self _removeLayerFromSuperlayer];
1482 // A backing layer is removed regardless of whether it was set implicitly or explicitly
1483 // The distinction appears to be based on the layers class, not how it was set (host vs. backing)
1484 if([_layer isKindOfClass:[NSViewBackingLayer class]]){
1489 [_subviews makeObjectsPerformSelector:_cmd];
1493 -(void)_createLayersInTreeIfNeeded {
1494 if(!NSViewLayersEnabled)
1498 _layer=[[self makeBackingLayer] retain];
1499 configureLayerGeometry(self);
1502 [self _addLayerToSuperlayer];
1504 [_subviews makeObjectsPerformSelector:_cmd];
1507 -(void)setWantsLayer:(BOOL)value {
1511 [self _removeLayerBackedViewsFromTree];
1517 [self _createLayersInTreeIfNeeded];
1522 -(void)setLayer:(CALayer *)value {
1523 if(!NSViewLayersEnabled)
1527 [_subviews makeObjectsPerformSelector:@selector(_removeLayerFromSuperlayer)];
1529 value=[value retain];
1534 [self _addLayerToSuperlayer];
1537 else if(value==nil){
1538 [self _removeLayerFromSuperlayer];
1543 [[_superview layer] replaceSublayer:_layer with:value];
1548 [_subviews makeObjectsPerformSelector:@selector(_addLayerToSuperlayer)];
1552 -(NSViewLayerContentsPlacement)layerContentsPlacement {
1553 return _layerContentsPlacement;
1556 -(void)setLayerContentsPlacement:(NSViewLayerContentsPlacement)value {
1557 _layerContentsPlacement=value;
1560 -(NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy {
1561 return _layerContentsRedrawPolicy;
1564 -(void)setLayerContentsRedrawPolicy:(NSViewLayerContentsRedrawPolicy)value {
1565 _layerContentsRedrawPolicy=value;
1569 -(NSArray *)backgroundFilters {
1570 NSUnimplementedMethod();
1574 -(void)setBackgroundFilters:(NSArray *)filters {
1575 // FIXME: implement but dont warn
1576 // NSUnimplementedMethod();
1579 -(NSArray *)contentFilters {
1580 return _contentFilters;
1583 -(void)setContentFilters:(NSArray *)filters {
1584 filters=[filters copy];
1585 [_contentFilters release];
1586 _contentFilters=filters;
1589 -(CIFilter *)compositingFilter {
1590 return _compositingFilter;
1593 -(void)setCompositingFilter:(CIFilter *)filter {
1594 filter=[filter copy];
1595 [_compositingFilter release];
1596 _compositingFilter=filter;
1599 -(NSShadow *)shadow {
1603 -(void)setShadow:(NSShadow *)shadow {
1604 shadow=[shadow copy];
1609 -(BOOL)needsDisplay {
1610 return _needsDisplay;
1614 If _needsDisplay is YES and there are no _invalidRects, invalid rect is bounds
1615 If _needsDisplay is YES and there are _invalidRects, invalid rect is union
1616 You can't just keep a running invalid rect because setting YES then changing the
1617 bounds should redraw the new bounds, but changing the bounds should not alter the
1621 static NSRect unionOfInvalidRects(NSView *self){
1624 if(self->_invalidRectCount==0)
1625 result=[self visibleRect];
1629 result=self->_invalidRects[0];
1631 for(i=1;i<self->_invalidRectCount;i++)
1632 result=NSUnionRect(result,self->_invalidRects[i]);
1638 static void removeRectFromInvalidInVisibleRect(NSView *self,NSRect rect,NSRect visibleRect) {
1639 int count=self->_invalidRectCount;
1642 self->_invalidRects[count]=NSIntersectionRect(self->_invalidRects[count],visibleRect);
1644 if(NSContainsRect(rect,self->_invalidRects[count])){
1647 self->_invalidRectCount--;
1648 for(i=count;i<self->_invalidRectCount;i++)
1649 self->_invalidRects[i]=self->_invalidRects[i+1];
1652 if(self->_invalidRectCount==0){
1653 if(self->_invalidRects!=NULL) {
1654 NSZoneFree(NULL,self->_invalidRects);
1655 self->_invalidRects=NULL;
1656 // We killed the last invalidRect - we're clean now
1657 self->_needsDisplay=NO;
1658 } else if (NSContainsRect(rect, visibleRect)) {
1659 // We had no invalidRect, which means the full visibleRect was dirty
1661 self->_needsDisplay=NO;
1666 static void clearRectsBeingRedrawn(NSView *self){
1667 if (self->_rectsBeingRedrawn) {
1668 NSZoneFree(NULL, self->_rectsBeingRedrawn);
1669 self->_rectsBeingRedrawn = NULL;
1670 self->_rectsBeingRedrawnCount = 0;
1674 static void clearInvalidRects(NSView *self){
1675 if(self->_invalidRects!=NULL)
1676 NSZoneFree(NULL,self->_invalidRects);
1677 self->_invalidRects=NULL;
1678 self->_invalidRectCount=0;
1679 clearRectsBeingRedrawn(self);
1683 static void clearNeedsDisplay(NSView *self){
1684 if ([NSGraphicsContext inQuartzDebugMode]) {
1687 clearInvalidRects(self);
1688 self->_needsDisplay=NO;
1691 -(void)setNeedsDisplay:(BOOL)flag {
1694 // We removed them for YES to indicate entire view, and NO for obvious reasons
1695 clearInvalidRects(self);
1698 [[self window] setViewsNeedDisplay:YES];
1701 -(void)setNeedsDisplayInRect:(NSRect)rect {
1702 // We only add rects if its not the entire view
1703 if(!_needsDisplay || _invalidRects!=NULL){
1704 NSRect visibleRect = [self visibleRect];
1705 rect = NSIntersectionRect(visibleRect, rect);
1706 if (NSContainsRect(rect, visibleRect)) {
1707 clearInvalidRects(self); // Everything is dirty
1709 // All of our clipping done by the context is rounded - so we need to do the same
1710 // here else we might get some artifact on clipping borders
1711 rect = [self convertRect:rect toView:nil];
1712 rect = NSIntegralRect(rect);
1713 rect = [self convertRect:rect fromView:nil];
1714 _invalidRectCount++;
1715 _invalidRects=NSZoneRealloc(NULL,_invalidRects,sizeof(NSRect)*_invalidRectCount);
1716 _invalidRects[_invalidRectCount-1]=rect;
1718 clearRectsBeingRedrawn(self);
1720 // We also needs to be sure all of our superviews will properly redraw this area,
1721 // even if they are smart about what to redraw (using needsDisplayInRect:)
1722 NSView *opaqueAncestor = [self opaqueAncestor];
1723 if (opaqueAncestor != self) {
1724 NSRect dirtyRect = [self convertRect:rect toView:opaqueAncestor];
1725 [opaqueAncestor setNeedsDisplayInRect:dirtyRect];
1730 [[self window] setViewsNeedDisplay:YES];
1733 -(void)setKeyboardFocusRingNeedsDisplayInRect:(NSRect)rect {
1734 NSUnimplementedMethod();
1737 -(void)translateRectsNeedingDisplayInRect:(NSRect)rect by:(NSSize)delta {
1738 NSUnimplementedMethod();
1742 return _window!=nil && ![self isHiddenOrHasHiddenAncestor];
1745 -(BOOL)canDrawConcurrently {
1746 NSUnimplementedMethod();
1750 -(void)viewWillDraw {
1751 [_subviews makeObjectsPerformSelector:_cmd];
1754 -(void)setCanDrawConcurrently:(BOOL)canDraw {
1755 NSUnimplementedMethod();
1758 static NSGraphicsContext *graphicsContextForView(NSView *view){
1759 if(view->_layer!=nil){
1760 NSRect frame=[view frame];
1761 size_t width=frame.size.width;
1762 size_t height=frame.size.height;
1763 CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
1764 CGContextRef context=CGBitmapContextCreate(NULL,width,height,8,0,colorSpace,kCGImageAlphaPremultipliedFirst|kCGBitmapByteOrder32Host);
1765 NSGraphicsContext *result=[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO];
1767 CGColorSpaceRelease(colorSpace);
1768 CGContextRelease(context);
1773 return [[view window] graphicsContext];
1776 -(void)_lockFocusInContext:(NSGraphicsContext *)context {
1777 CGContextRef graphicsPort=[context graphicsPort];
1779 [NSGraphicsContext saveGraphicsState];
1780 [NSGraphicsContext setCurrentContext:context];
1782 [[context focusStack] addObject:self];
1784 CGContextSaveGState(graphicsPort);
1785 CGContextResetClip(graphicsPort);
1788 CGContextSetCTM(graphicsPort,[self transformToLayer]);
1790 CGContextSetCTM(graphicsPort,[self transformToWindow]);
1792 CGContextClipToRect(graphicsPort,[self visibleRect]);
1798 [self _lockFocusInContext:graphicsContextForView(self)];
1801 -(BOOL)lockFocusIfCanDraw {
1809 -(BOOL)lockFocusIfCanDrawInContext:(NSGraphicsContext *)context {
1811 [self _lockFocusInContext:context];
1818 -(void)unlockFocus {
1819 NSGraphicsContext *graphicsContext=[NSGraphicsContext currentContext];
1820 CGContextRef context=[graphicsContext graphicsPort];
1823 CGImageRef image=CGBitmapContextCreateImage(context);
1825 [_layer setContents:image];
1828 CGContextRestoreGState(context);
1830 [[graphicsContext focusStack] removeLastObject];
1831 [NSGraphicsContext restoreGraphicsState];
1834 -(BOOL)needsToDrawRect:(NSRect)rect {
1835 BOOL needsToDrawRect = NO;
1837 if (NSIntersectsRect(rect, _visibleRect)) {
1838 const NSRect *rects;
1840 [self getRectsBeingDrawn:&rects count:&count];
1842 for(int i=0; i<count && needsToDrawRect == NO;i++) {
1843 needsToDrawRect = NSIntersectsRect(rect, rects[i]);
1847 return needsToDrawRect;
1850 -(void)getRectsBeingDrawn:(const NSRect **)rects count:(NSInteger *)count {
1851 // This method returns all the rects being drawn concerning the view
1852 // That's all of the dirty rects from the view, but also all the ones
1853 // from the superview that might have caused the redraw.
1854 // Since invalidating a rect also invalidates the first opaque superview,
1855 // only the opaque views need to be checked
1856 *rects = _rectsBeingRedrawn;
1857 *count = _rectsBeingRedrawnCount;
1859 if (_rectsBeingRedrawn == NULL) {
1860 NSView *opaqueAncestor = [self opaqueAncestor];
1861 if (opaqueAncestor != self) {
1862 // Ask our opaque ancestor what to draw
1863 const NSRect *ancestorRects;
1864 [opaqueAncestor getRectsBeingDrawn:&ancestorRects count:&_rectsBeingRedrawnCount];
1865 if (_rectsBeingRedrawnCount) {
1866 _rectsBeingRedrawn = NSZoneCalloc(NULL, _rectsBeingRedrawnCount, sizeof(NSRect));
1868 for (int i = 0; i < _rectsBeingRedrawnCount; ++i) {
1869 NSRect r = [opaqueAncestor convertRect:ancestorRects[i] toView:self];
1870 // No need for the rects that are outside of the visibleRect
1871 if (NSIntersectsRect(r, _visibleRect)) {
1872 _rectsBeingRedrawn[rectsCount++] = r;
1875 *rects = _rectsBeingRedrawn;
1876 *count = rectsCount;
1879 // We're opaque - concatenate our invalid rect with the one from the previous opaque view
1880 NSView *view = [self superview];
1882 NSView *opaqueAncestor = [view opaqueAncestor];
1883 const NSRect *ancestorRects;
1884 NSUInteger ancestorRectsCount;
1885 [opaqueAncestor getRectsBeingDrawn:&ancestorRects count:&ancestorRectsCount];
1886 if (ancestorRectsCount || _invalidRectCount) {
1887 _rectsBeingRedrawn = NSZoneCalloc(NULL, _invalidRectCount + ancestorRectsCount, sizeof(NSRect));
1889 for (int i = 0; i < ancestorRectsCount; ++i) {
1890 NSRect r = [opaqueAncestor convertRect:ancestorRects[i] toView:self];
1891 // No need for the rects that are outside of the visibleRect
1892 if (NSIntersectsRect(r, _visibleRect)) {
1893 _rectsBeingRedrawn[rectsCount++] = r;
1896 for (int i = 0; i < _invalidRectCount; ++i) {
1897 _rectsBeingRedrawn[rectsCount++] = _invalidRects[i];
1899 _rectsBeingRedrawnCount = rectsCount;
1900 *rects = _rectsBeingRedrawn;
1901 *count = _rectsBeingRedrawnCount;
1906 // We had no info and no opaque ancestor gave us any useful rect - just use our invalid rects
1907 if (*rects == NULL) {
1908 if (_invalidRects == NULL) {
1909 if (_needsDisplay) {
1910 *rects = &_visibleRect;
1914 *rects = _invalidRects;
1915 *count = _invalidRectCount;
1920 -(void)getRectsExposedDuringLiveResize:(NSRect)rects count:(NSInteger *)count {
1921 NSUnimplementedMethod();
1924 -(BOOL)shouldDrawColor {
1925 NSUnimplementedMethod();
1929 -(NSView *)opaqueAncestor {
1933 return [[self superview] opaqueAncestor];
1937 [self displayRect:[self visibleRect]];
1940 - (NSEnumerator*)_subviewsInDisplayOrderEnumerator
1942 // Subviews are ordered back to front -
1943 return [_subviews objectEnumerator];
1946 -(void)_displayIfNeededWithoutViewWillDraw {
1947 if([self needsDisplay]){
1948 [self displayRect:unionOfInvalidRects(self)];
1949 clearNeedsDisplay(self);
1952 NSEnumerator* viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
1954 NSView* subView = nil;
1955 while ((subView = [viewEnumerator nextObject])) {
1956 [subView _displayIfNeededWithoutViewWillDraw];
1960 -(void)displayIfNeeded {
1961 [self viewWillDraw];
1962 [self _displayIfNeededWithoutViewWillDraw];
1965 -(void)displayIfNeededInRect:(NSRect)rect {
1967 rect=NSIntersectionRect(unionOfInvalidRects(self), rect);
1969 if([self needsDisplay])
1970 [self displayRect:rect];
1972 NSEnumerator* viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
1974 NSView* child = nil;
1975 while ((child = [viewEnumerator nextObject])) {
1976 NSRect converted=NSIntersectionRect([self convertRect:rect toView:child],[child bounds]);
1977 if(!NSIsEmptyRect(converted)) {
1978 [child displayIfNeededInRect:converted];
1983 -(void)displayIfNeededInRectIgnoringOpacity:(NSRect)rect {
1985 rect=NSIntersectionRect(unionOfInvalidRects(self), rect);
1987 if([self needsDisplay])
1988 [self displayRectIgnoringOpacity:rect];
1990 NSEnumerator* viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
1992 NSView* child = nil;
1993 while ((child = [viewEnumerator nextObject])) {
1994 NSRect converted=NSIntersectionRect([self convertRect:rect toView:child],[child bounds]);
1996 if(!NSIsEmptyRect(converted)) {
1997 [child displayIfNeededInRectIgnoringOpacity:converted];
2002 -(void)displayIfNeededIgnoringOpacity {
2004 if([self needsDisplay])
2005 [self displayRectIgnoringOpacity:unionOfInvalidRects(self)];
2007 NSEnumerator* viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
2009 NSView* child = nil;
2010 while ((child = [viewEnumerator nextObject])) {
2011 [child displayIfNeededIgnoringOpacity];
2015 -(void)displayRect:(NSRect)rect {
2016 NSView *opaque=[self opaqueAncestor];
2019 rect=[self convertRect:rect toView:opaque];
2020 [opaque displayRectIgnoringOpacity:rect];
2023 -(void)displayRectIgnoringOpacity:(NSRect)rect {
2024 NSRect visibleRect=[self visibleRect];
2026 rect=NSIntersectionRect(rect,visibleRect);
2028 if(NSIsEmptyRect(rect))
2031 if ([self canDraw]) {
2032 // This view must be locked/unlocked prior to drawing subviews otherwise gState changes may affect subviews.
2035 NSGraphicsContext *context=[NSGraphicsContext currentContext];
2036 CGContextRef graphicsPort=[context graphicsPort];
2038 CGContextClipToRect(graphicsPort,rect);
2040 const NSRect *rects;
2041 NSUInteger rectsCount;
2042 [self getRectsBeingDrawn:&rects count:&rectsCount];
2043 // If there is only one rect, it's the visible rect - it's already clipped
2045 CGContextClipToRects(graphicsPort, rects, rectsCount);
2047 // [_window dirtyRect:[self convertRect:rect toView:nil]];
2048 if ([NSGraphicsContext inQuartzDebugMode]) {
2049 [[NSColor yellowColor] set];
2053 [self drawRect:rect];
2057 NSEnumerator *viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
2059 NSView *child = nil;
2060 while ((child = [viewEnumerator nextObject])) {
2061 NSRect check=[self convertRect:rect toView:child];
2063 check=NSIntersectionRect(check,[child bounds]);
2065 if(!NSIsEmptyRect(check))
2066 [child displayRectIgnoringOpacity:check];
2070 [_layerContext render];
2072 // Don't do anything to interfere with what will be drawn in non-debug mode
2073 if ([NSGraphicsContext inQuartzDebugMode] == NO) {
2074 removeRectFromInvalidInVisibleRect(self,rect,visibleRect);
2076 // Rects being drawn are only valid while we redraw
2077 clearRectsBeingRedrawn(self);
2080 // We do the flushWindow here. If any of the display* methods are being used, you want it to update on screen immediately.
2081 // If the view hierarchy is being displayed as needed at the end of an event, flushing will be disabled and this will just
2082 // mark the window as needing flushing which will happen when all the views have finished being displayed
2083 [[self window] flushWindow];
2086 -(void)displayRectIgnoringOpacity:(NSRect)rect inContext:(NSGraphicsContext *)context {
2087 NSUnimplementedMethod();
2090 -(void)drawRect:(NSRect)rect {
2094 -(BOOL)autoscroll:(NSEvent *)event {
2095 return [[self superview] autoscroll:event];
2098 -(void)scrollRect:(NSRect)rect by:(NSSize)delta {
2099 NSPoint point=rect.origin;
2101 point.x+=delta.width;
2102 point.y+=delta.height;
2104 if([self lockFocusIfCanDraw]){
2105 NSCopyBits([self gState],rect,point);
2110 -(BOOL)mouseDownCanMoveWindow {
2111 NSUnimplementedMethod();
2115 -(void)print:sender {
2116 [[NSPrintOperation printOperationWithView:self] runOperation];
2119 -(void)beginDocument {
2122 -(void)endDocument {
2125 -(void)beginPageInRect:(NSRect)rect atPlacement:(NSPoint)placement {
2126 CGContextRef graphicsPort=NSCurrentGraphicsPort();
2127 CGRect mediaBox=NSMakeRect(0,0,rect.size.width,rect.size.height);
2128 NSPrintInfo *printInfo=[[NSPrintOperation currentOperation] printInfo];
2129 NSRect imageableRect=[printInfo imageablePageBounds];
2130 CGAffineTransform transform=CGAffineTransformIdentity;
2132 [NSCurrentFocusStack() addObject:self];
2134 CGContextBeginPage(graphicsPort,&mediaBox);
2135 CGContextSaveGState(graphicsPort);
2137 transform=CGAffineTransformIdentity;
2138 if([self isFlipped]){
2139 transform=CGAffineTransformMake(1,0,0,-1,0,[printInfo paperSize].height);
2142 transform=CGAffineTransformTranslate(transform,-rect.origin.x,-rect.origin.y);
2144 CGContextConcatCTM(graphicsPort,transform);
2150 CGContextRef graphicsPort=NSCurrentGraphicsPort();
2152 CGContextRestoreGState(graphicsPort);
2153 CGContextEndPage(graphicsPort);
2154 [NSCurrentFocusStack() removeLastObject];
2157 -(NSAttributedString *)pageHeader {
2158 NSUnimplementedMethod();
2162 -(NSAttributedString *)pageFooter {
2163 NSUnimplementedMethod();
2167 -(NSString *)printJobTitle {
2168 NSUnimplementedMethod();
2172 -(void)drawSheetBorderWithSize:(NSSize)size {
2173 NSUnimplementedMethod();
2176 -(void)drawPageBorderWithSize:(NSSize)size {
2177 NSUnimplementedMethod();
2181 -(float)widthAdjustLimit {
2185 -(float)heightAdjustLimit {
2189 -(void)adjustPageWidthNew:(float *)adjusted left:(float)left right:(float)right limit:(float)limit {
2190 // FIX, give subviews a chance
2193 -(void)adjustPageHeightNew:(float *)adjust top:(float)top bottom:(float)bottom limit:(float)limit {
2194 // FIX, give subviews a chance
2197 -(BOOL)knowsPageRange:(NSRange *)range {
2201 -(NSPoint)locationOfPrintRect:(NSRect)rect {
2205 -(NSRect)rectForPage:(int)page {
2209 -(NSData *)dataWithEPSInsideRect:(NSRect)rect {
2210 NSMutableData *result=[NSMutableData data];
2211 NSPrintOperation *operation=[NSPrintOperation EPSOperationWithView:self insideRect:rect toData:result];
2213 [operation runOperation];
2218 -(NSData *)dataWithPDFInsideRect:(NSRect)rect {
2219 NSMutableData *result=[NSMutableData data];
2220 NSPrintOperation *operation=[NSPrintOperation PDFOperationWithView:self insideRect:rect toData:result];
2222 [operation runOperation];
2227 -(void)writeEPSInsideRect:(NSRect)rect toPasteboard:(NSPasteboard *)pasteboard {
2228 NSData *data=[self dataWithEPSInsideRect:rect];
2230 [pasteboard declareTypes:[NSArray arrayWithObject:NSPostScriptPboardType] owner:nil];
2231 [pasteboard setData:data forType:NSPostScriptPboardType];
2234 -(void)writePDFInsideRect:(NSRect)rect toPasteboard:(NSPasteboard *)pasteboard {
2235 NSData *data=[self dataWithPDFInsideRect:rect];
2237 [pasteboard declareTypes:[NSArray arrayWithObject:NSPDFPboardType] owner:nil];
2238 [pasteboard setData:data forType:NSPDFPboardType];
2241 -(void)dragImage:(NSImage *)image at:(NSPoint)location offset:(NSSize)offset event:(NSEvent *)event pasteboard:(NSPasteboard *)pasteboard source:source slideBack:(BOOL)slideBack {
2242 location = [self convertPoint:location toView:nil];
2243 [[NSDraggingManager draggingManager] dragImage:image at:location offset:offset event:event pasteboard:pasteboard source:source slideBack:slideBack];
2246 -(BOOL)dragFile:(NSString *)path fromRect:(NSRect)rect slideBack:(BOOL)slideBack event:(NSEvent *)event {
2247 NSUnimplementedMethod();
2251 -(BOOL)acceptsFirstResponder {
2255 -(void)scrollWheel:(NSEvent *)event {
2256 NSScrollView *scrollView=[self enclosingScrollView];
2258 if(scrollView==nil) {
2259 /* If we can't handle it, pass up responder chain, yep, it does this. */
2260 [super scrollWheel:event];
2263 NSView *documentView=[scrollView documentView];
2264 NSRect bounds=[documentView bounds];
2265 NSRect visible=[documentView visibleRect];
2266 float direction=[documentView isFlipped]?-1:1;
2268 visible.origin.x+=[event deltaX]*[scrollView horizontalLineScroll]*3;
2269 visible.origin.y+=[event deltaY]*direction*[scrollView verticalLineScroll]*3;
2271 // Something equivalent to this should be in scrollRectToVisible:
2272 if(visible.origin.y<bounds.origin.y)
2273 visible.origin.y=bounds.origin.y;
2274 if(visible.origin.x<bounds.origin.x)
2275 visible.origin.x=bounds.origin.x;
2276 if(NSMaxY(visible)>NSMaxY(bounds))
2277 visible.origin.y=NSMaxY(bounds)-visible.size.height;
2278 if(NSMaxX(visible)>NSMaxX(bounds))
2279 visible.origin.x=NSMaxX(bounds)-visible.size.width;
2281 [documentView scrollRectToVisible:visible];
2285 -(BOOL)performKeyEquivalent:(NSEvent *)event {
2286 int i,count=[_subviews count];
2288 for(i=0;i<count;i++){
2289 NSView *check=[_subviews objectAtIndex:i];
2291 if([check performKeyEquivalent:event])
2297 -(BOOL)performMnemonic:(NSString *)string {
2298 NSUnimplementedMethod();
2302 -(void)setMenu:(NSMenu *)menu {
2308 -(void)rightMouseDown:(NSEvent *)event {
2309 [NSMenu popUpContextMenu:[self menuForEvent:event] withEvent:event forView:self];
2313 // default NSDraggingDestination
2314 -(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
2315 return NSDragOperationNone;
2318 -(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender {
2319 return [sender draggingSourceOperationMask];
2322 -(void)draggingExited:(id <NSDraggingInfo>)sender {
2326 -(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender {
2330 -(BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
2334 -(void)concludeDragOperation:(id <NSDraggingInfo>)sender {
2338 -(NSArray *)_draggedTypes {
2339 return _draggedTypes;
2342 - (BOOL)dragPromisedFilesOfTypes:(NSArray *)types fromRect:(NSRect)rect source:(id)source slideBack:(BOOL)slideBack event:(NSEvent *)event {
2343 NSUnimplementedMethod();
2347 -(NSPoint)convertPointFromBase:(NSPoint)aPoint; {
2351 -(NSPoint)convertPointToBase:(NSPoint)aPoint; {
2355 -(NSSize)convertSizeFromBase:(NSSize)aSize {
2359 -(NSSize)convertSizeToBase:(NSSize)aSize {
2363 -(NSRect)convertRectFromBase:(NSRect)aRect {
2367 -(NSRect)convertRectToBase:(NSRect)aRect {
2371 -(void)showDefinitionForAttributedString:(NSAttributedString *)string atPoint:(NSPoint)origin {
2372 NSUnimplementedMethod();
2375 +defaultAnimationForKey:(NSString *)key {
2376 NSUnimplementedMethod();
2381 NSUnimplementedMethod();
2382 // should return animating proxy. returning self does not animate.
2386 -(NSDictionary *)animations {
2390 -animationForKey:(NSString *)key {
2391 return [_animations objectForKey:key];
2394 -(void)setAnimations:(NSDictionary *)dictionary {
2395 dictionary=[dictionary copy];
2396 [_animations release];
2397 _animations=dictionary;
2400 // Blocks aren't supported by the compiler yet.
2401 //-(void)showDefinitionForAttributedString:(NSAttributedString *)string range:(NSRange)range options:(NSDictionary *)options baselineOriginProvider:(NSPoint (^)(NSRange adjustedRange))originProvider {
2402 // NSUnimplementedMethod();
2405 -(NSString *)description {
2406 return [NSString stringWithFormat:@"<%@[0x%lx] frame: %@>", [self class], self, NSStringFromRect(_frame)];