/* Copyright (c) 2006-2007 Christopher J. W. Lloyd 2009-2010 Markus Hitter 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: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 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. */ #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import NSString * const NSViewFrameDidChangeNotification=@"NSViewFrameDidChangeNotification"; NSString * const NSViewBoundsDidChangeNotification=@"NSViewBoundsDidChangeNotification"; NSString * const NSViewFocusDidChangeNotification=@"NSViewFocusDidChangeNotification"; @interface NSView(NSView_forward) -(CGAffineTransform)transformFromWindow; -(CGAffineTransform)transformToWindow; -(CGAffineTransform)transformToLayer; -(void)_trackingAreasChanged; @end @implementation NSView static BOOL NSViewLayersEnabled=NO; +(void)initialize { NSViewLayersEnabled=[[NSUserDefaults standardUserDefaults] boolForKey:@"NSViewLayersEnabled"]; } +(NSView *)focusView { return [NSCurrentFocusStack() lastObject]; } +(NSMenu *)defaultMenu { return nil; } +(NSFocusRingType)defaultFocusRingType { NSUnimplementedMethod(); return nil; } -(void)encodeWithCoder:(NSCoder *)coder { NSUnimplementedMethod(); } -initWithCoder:(NSCoder *)coder { [super initWithCoder:coder]; if([coder allowsKeyedCoding]){ NSKeyedUnarchiver *keyed=(NSKeyedUnarchiver *)coder; unsigned vFlags=[keyed decodeIntForKey:@"NSvFlags"]; _frame=NSZeroRect; if([keyed containsValueForKey:@"NSFrame"]) _frame=[keyed decodeRectForKey:@"NSFrame"]; else if([keyed containsValueForKey:@"NSFrameSize"]) _frame.size=[keyed decodeSizeForKey:@"NSFrameSize"]; _bounds.origin=NSMakePoint(0,0); _bounds.size=_frame.size; _window=nil; _superview=nil; _subviews=[NSMutableArray new]; _postsNotificationOnFrameChange=YES; _postsNotificationOnBoundsChange=YES; _autoresizingMask=vFlags&0x3F; if([keyed containsValueForKey:@"NSvFlags"]) _autoresizesSubviews=(vFlags&0x100)?YES:NO; // Despite the fact it appears _autoresizesSubviews is encoded in the flags, it should always be ON // *** Do not turn off or base on the flags unless you have an alternative for enabling it when it // should be. _autoresizesSubviews=YES; _isHidden=(vFlags&0x80000000)?YES:NO; _tag=-1; if([keyed containsValueForKey:@"NSTag"]) _tag=[keyed decodeIntForKey:@"NSTag"]; [_subviews addObjectsFromArray:[keyed decodeObjectForKey:@"NSSubviews"]]; [_subviews makeObjectsPerformSelector:@selector(_setSuperview:) withObject:self]; _needsDisplay=YES; _invalidRectCount=0; _invalidRects=NULL; _trackingAreas=[[NSMutableArray alloc] init]; [self setWantsLayer:[keyed decodeBoolForKey:@"NSViewIsLayerTreeHost"]]; _layerContentsRedrawPolicy=[keyed decodeIntegerForKey:@"NSViewLayerContentsRedrawPolicy"]; _contentFilters=[[keyed decodeObjectForKey:@"NSViewContentFilters"] retain]; } else { [NSException raise:NSInvalidArgumentException format:@"%@ can not initWithCoder:%@",isa,[coder class]]; } return self; } -init { return [self initWithFrame:NSMakeRect(0,0,1,1)]; } -initWithFrame:(NSRect)frame { _frame=frame; _bounds.origin=NSMakePoint(0,0); _bounds.size=frame.size; _window=nil; _menu=nil; _superview=nil; _subviews=[NSMutableArray new]; _postsNotificationOnFrameChange=YES; _postsNotificationOnBoundsChange=YES; _autoresizesSubviews=YES; _autoresizingMask=NSViewNotSizable; _tag=-1; _needsDisplay=YES; _invalidRectCount=0; _invalidRects=NULL; _trackingAreas=[[NSMutableArray alloc] init]; _validTransforms=NO; _transformFromWindow=CGAffineTransformIdentity; _transformToWindow=CGAffineTransformIdentity; _transformToLayer=CGAffineTransformIdentity; return self; } -(void)dealloc { _window=nil; [_menu release]; _superview=nil; [_subviews makeObjectsPerformSelector:@selector(_setSuperview:) withObject:nil]; [_subviews release]; [_draggedTypes release]; [_trackingAreas release]; [self _unbindAllBindings]; [_contentFilters release]; if(_invalidRects!=NULL) NSZoneFree(NULL,_invalidRects); [_layer release]; [_layerContext invalidate]; [_layerContext release]; [_overlay release]; [super dealloc]; } static void invalidateTransform(NSView *self){ self->_validTransforms=NO; self->_validTrackingAreas=NO; for(NSView *check in self->_subviews) invalidateTransform(check); } static CGAffineTransform concatViewTransform(CGAffineTransform result,NSView *view,NSView *superview,BOOL doFrame,BOOL flip){ NSRect bounds=[view bounds]; NSRect frame=[view frame]; if(doFrame) result=CGAffineTransformTranslate(result,frame.origin.x,frame.origin.y); if(flip){ CGAffineTransform flip=CGAffineTransformMake(1,0,0,-1,0,bounds.size.height); result=CGAffineTransformConcat(flip,result); } result=CGAffineTransformTranslate(result,-bounds.origin.x,-bounds.origin.y); return result; } -(CGAffineTransform)createTransformToWindow { CGAffineTransform result; NSView *superview=[self superview]; BOOL doFrame=YES; BOOL flip; if(superview==nil){ result=CGAffineTransformIdentity; flip=[self isFlipped]; } else { result=[superview transformToWindow]; flip=([self isFlipped]!=[superview isFlipped]); } result=concatViewTransform(result,self,superview,doFrame,flip); return result; } -(CGAffineTransform)createTransformToLayer { CGAffineTransform result=CGAffineTransformIdentity; NSRect bounds=[self bounds]; if([self isFlipped]){ CGAffineTransform flip=CGAffineTransformMake(1,0,0,-1,0,bounds.size.height); result=CGAffineTransformConcat(flip,result); } result=CGAffineTransformTranslate(result,-bounds.origin.x,-bounds.origin.y); return result; } -(NSRect)calculateVisibleRect { if([self isHiddenOrHasHiddenAncestor]) return NSZeroRect; if([self superview]==nil) return [self bounds]; else { NSRect result=[[self superview] visibleRect]; result=[self convertRect:result fromView:[self superview]]; result=NSIntersectionRect(result,[self bounds]); return result; } } static inline void configureLayerGeometry(NSView *self){ CALayer *layer=self->_layer; if(layer==nil) return; [CATransaction begin]; [CATransaction setDisableActions:YES]; [layer setAnchorPoint:CGPointMake(0,0)]; if([layer superlayer]==nil) [layer setPosition:CGPointMake(0,0)]; else [layer setPosition:self->_frame.origin]; [layer setBounds:self->_bounds]; [CATransaction commit]; } static inline void buildTransformsIfNeeded(NSView *self) { if(!self->_validTransforms){ self->_transformToWindow=[self createTransformToWindow]; self->_transformFromWindow=CGAffineTransformInvert(self->_transformToWindow); self->_transformToLayer=[self createTransformToLayer]; self->_validTransforms=YES; self->_visibleRect=[self calculateVisibleRect]; configureLayerGeometry(self); } } -(CGAffineTransform)transformFromWindow { buildTransformsIfNeeded(self); return _transformFromWindow; } -(CGAffineTransform)transformToWindow { buildTransformsIfNeeded(self); return _transformToWindow; } -(CGAffineTransform)transformToLayer { buildTransformsIfNeeded(self); return _transformToLayer; } -(NSRect)frame { return _frame; } -(CGFloat)frameRotation { return _frameRotation; } -(CGFloat)frameCenterRotation { NSUnimplementedMethod(); return 0.; } -(NSRect)bounds { return _bounds; } -(CGFloat)boundsRotation { return _boundsRotation; } -(BOOL)isRotatedFromBase { NSUnimplementedMethod(); return NO; } -(BOOL)isRotatedOrScaledFromBase { NSUnimplementedMethod(); return NO; } -(void)translateOriginToPoint:(NSPoint)point { NSUnimplementedMethod(); } -(void)rotateByAngle:(CGFloat)angle { [self setBoundsRotation:[self boundsRotation]+angle]; } -(BOOL)postsFrameChangedNotifications { return _postsNotificationOnFrameChange; } -(BOOL)postsBoundsChangedNotifications { return _postsNotificationOnBoundsChange; } -(void)scaleUnitSquareToSize:(NSSize)size { NSUnimplementedMethod(); } -(NSWindow *)window { return _window; } -(NSView *)superview { return _superview; } -(BOOL)isDescendantOf:(NSView *)other { NSView *check=self; do { if(check==other) return YES; check=[check superview]; }while(check!=nil); return NO; } -(NSView *)ancestorSharedWithView:(NSView *)view { NSUnimplementedMethod(); return nil; } -(NSScrollView *)enclosingScrollView { id result=[self superview]; for(;result!=nil;result=[result superview]) if([result isKindOfClass:[NSScrollView class]]) return result; return nil; } -(NSRect)adjustScroll:(NSRect)toRect { NSUnimplementedMethod(); return NSZeroRect; } -(NSArray *)subviews { return _subviews; } -(BOOL)autoresizesSubviews { return _autoresizesSubviews; } -(unsigned)autoresizingMask { return _autoresizingMask; } -(NSFocusRingType)focusRingType { return _focusRingType; } -(int)tag { return _tag; } -(BOOL)isFlipped { return NO; } -(BOOL)isOpaque { return NO; } -(CGFloat)alphaValue { NSUnimplementedMethod(); return 0.; } -(void)setAlphaValue:(CGFloat)alpha { NSUnimplementedMethod(); } -(int)gState { return 0; } -(NSRect)visibleRect { buildTransformsIfNeeded(self); return _visibleRect; } -(BOOL)wantsDefaultClipping { NSUnimplementedMethod(); return NO; } -(NSBitmapImageRep *)bitmapImageRepForCachingDisplayInRect:(NSRect)rect { NSUnimplementedMethod(); return nil; } -(void)cacheDisplayInRect:(NSRect)rect toBitmapImageRep:(NSBitmapImageRep *)imageRep { NSUnimplementedMethod(); } -(BOOL)isHidden { return _isHidden; } -(BOOL)isHiddenOrHasHiddenAncestor { return _isHidden || [_superview isHiddenOrHasHiddenAncestor]; } -(void)setHidden:(BOOL)flag { flag=flag?YES:NO; if (_isHidden != flag) { invalidateTransform(self); if ((_isHidden = flag)) { id view=[_window firstResponder]; if ([view isKindOfClass:[NSView class]]) for (; view; view = [view superview]) { if (self==view) { [_window makeFirstResponder:[self nextValidKeyView]]; break; } } } [[self superview] setNeedsDisplay:YES]; } } -(void)viewDidHide { NSUnimplementedMethod(); } -(void)viewDidUnhide { NSUnimplementedMethod(); } -(BOOL)canBecomeKeyView { return [self acceptsFirstResponder] && ![self isHiddenOrHasHiddenAncestor]; } -(BOOL)needsPanelToBecomeKey { return NO; } -(NSView *)nextKeyView { return _nextKeyView; } -(NSView *)nextValidKeyView { NSView *result=[self nextKeyView]; while(result!=nil && ![result canBecomeKeyView]) result=[result nextKeyView]; return result; } -(NSView *)previousKeyView { return _previousKeyView; } -(NSView *)previousValidKeyView { NSView *result=[self previousKeyView]; while(result!=nil && ![result canBecomeKeyView]) result=[result previousKeyView]; return result; } -(NSMenu *)menu { return _menu; } -(NSMenu *)menuForEvent:(NSEvent *)event { NSMenu *result=[self menu]; if(result==nil) { result=[isa defaultMenu]; if(result) { NSArray *itemArray=[result itemArray]; int i,count=[itemArray count]; for(i=0;i=0){ // front to back NSView *check=[subviews objectAtIndex:count]; NSView *hit=[check hitTest:point]; if(hit!=nil){ return hit; } } return self; } } -(NSPoint)convertPoint:(NSPoint)point fromView:(NSView *)viewOrNil { NSView *fromView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView]; CGAffineTransform toWindow=[fromView transformToWindow]; CGAffineTransform fromWindow=[self transformFromWindow]; return CGPointApplyAffineTransform(CGPointApplyAffineTransform(point,toWindow),fromWindow); } -(NSPoint)convertPoint:(NSPoint)point toView:(NSView *)viewOrNil { NSView *toView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView]; CGAffineTransform toWindow=[self transformToWindow]; CGAffineTransform fromWindow=[toView transformFromWindow]; return CGPointApplyAffineTransform(CGPointApplyAffineTransform(point,toWindow),fromWindow); } -(NSSize)convertSize:(NSSize)size fromView:(NSView *)viewOrNil { NSView *fromView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView]; CGAffineTransform toWindow=[fromView transformToWindow]; CGAffineTransform fromWindow=[self transformFromWindow]; return CGSizeApplyAffineTransform(CGSizeApplyAffineTransform(size,toWindow),fromWindow); } -(NSSize)convertSize:(NSSize)size toView:(NSView *)viewOrNil { NSView *toView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView]; CGAffineTransform toWindow=[self transformToWindow]; CGAffineTransform fromWindow=[toView transformFromWindow]; return CGSizeApplyAffineTransform(CGSizeApplyAffineTransform(size,toWindow),fromWindow); } -(NSRect)convertRect:(NSRect)rect fromView:(NSView *)viewOrNil { NSView *fromView=(viewOrNil!=nil)?viewOrNil:[[self window] _backgroundView]; CGAffineTransform toWindow=[fromView transformToWindow]; CGAffineTransform fromWindow=[self transformFromWindow]; NSPoint point1=rect.origin; NSPoint point2=NSMakePoint(NSMaxX(rect),NSMaxY(rect)); point1= CGPointApplyAffineTransform(CGPointApplyAffineTransform(point1,toWindow),fromWindow); point2= CGPointApplyAffineTransform(CGPointApplyAffineTransform(point2,toWindow),fromWindow); if(point2.y=0){ if([[_trackingAreas objectAtIndex:count] _isToolTip]==YES) [_trackingAreas removeObjectAtIndex:count]; } [self _trackingAreasChanged]; } -(void)addCursorRect:(NSRect)rect cursor:(NSCursor *)cursor { NSCursorRect *cursorRect=[[NSCursorRect alloc] initWithCursor:cursor]; NSTrackingArea *area=nil; area=[[NSTrackingArea alloc] _initWithRect:rect options:NSTrackingCursorUpdate|NSTrackingActiveInKeyWindow owner:cursorRect userData:NULL retainUserData:NO isToolTip:NO isLegacy:YES]; [_trackingAreas addObject:area]; [area release]; [cursorRect release]; [self _trackingAreasChanged]; } -(void)removeCursorRect:(NSRect)rect cursor:(NSCursor *)cursor { NSInteger count=[_trackingAreas count]; while(--count>=0){ NSTrackingArea *area=[_trackingAreas objectAtIndex:count]; NSObject *candidate=[area owner]; if([area _isLegacy]==YES && [candidate isKindOfClass:[NSCursorRect class]]==YES && [(NSCursorRect *)candidate cursor]==cursor){ [_trackingAreas removeObjectAtIndex:count]; break; } } [self _trackingAreasChanged]; } -(void)discardCursorRects { NSInteger count=[_trackingAreas count]; while(--count>=0){ NSTrackingArea *area=[_trackingAreas objectAtIndex:count]; if([area _isLegacy]==YES && ([area options]&NSTrackingCursorUpdate)){ [_trackingAreas removeObjectAtIndex:count]; } } [[self subviews] makeObjectsPerformSelector:_cmd]; [self _trackingAreasChanged]; } -(void)resetCursorRects { // do nothing } -(void)_collectTrackingAreasForWindowInto:(NSMutableArray *)collector { if(_isHidden==NO){ NSUInteger i,count; if(!_validTrackingAreas){ /* We don't clear the tracking areas, they are managed by the view with add/remove */ [self updateTrackingAreas]; _validTrackingAreas=YES; } count=[_trackingAreas count]; for(i=0;i0. && rectOfInterest.size.height>0.){ [area _setView:self]; [area _setRectInWindow:[self convertRect:rectOfInterest toView:nil]]; [collector addObject:[_trackingAreas objectAtIndex:i]]; } } NSArray *subviews=[self subviews]; // Collect subviews' areas _after_ collecting our own. count=[subviews count]; for(i=0;iNSMaxX(vRect)) sPoint.x=NSMinX(vRect)+(NSMaxX(rect)-NSMaxX(vRect)); else sPoint.x=NSMinX(vRect); if(NSMinY(rect)<=NSMinY(vRect)) sPoint.y=NSMinY(rect); else if(NSMaxY(rect)>NSMaxY(vRect)) sPoint.y=NSMinY(vRect)+(NSMaxY(rect)-NSMaxY(vRect)); else sPoint.y=NSMinY(vRect); if(sPoint.x!=NSMinX(vRect) || sPoint.y!=NSMinY(vRect)){ [clipView scrollToPoint:[self convertPoint:sPoint toView:clipView]]; return YES; } } return NO; } -(void)scrollClipView:(NSClipView *)clipView toPoint:(NSPoint)newOrigin { NSUnimplementedMethod(); } -(BOOL)mouse:(NSPoint)point inRect:(NSRect)rect { return NSMouseInRect(point, rect, [self isFlipped]); } -(void)reflectScrolledClipView:(NSClipView *)view { NSUnimplementedMethod(); } -(void)allocateGState { // unimplemented } -(void)releaseGState { // unimplemented } -(void)setUpGState { // do nothing } -(void)renewGState { // do nothing } -(BOOL)wantsLayer { return _wantsLayer; } -(CALayer *)layer { return _layer; } -(CALayer *)makeBackingLayer { return [NSViewBackingLayer layer]; } -(void)_removeLayerFromSuperlayer { [_layer removeFromSuperlayer]; [self _setOverlay:nil]; [_layerContext invalidate]; [_layerContext release]; _layerContext=nil; } -(void)_createLayerContextIfNeeded { if([_superview layer]==nil){ _layerContext=[[CALayerContext alloc] initWithFrame:[self frame]]; [_layerContext setLayer:_layer]; [self _setOverlay:[_layerContext pixelSurface]]; } } -(void)_addLayerToSuperlayer { [[_superview layer] addSublayer:_layer]; [self _createLayerContextIfNeeded]; } /* When turning off layering, we only turn off layers below us which did not want a layer Layers which did want a layer are not touched, nor are their children. */ -(void)_removeLayerBackedViewsFromTree { if(_wantsLayer) [self _createLayerContextIfNeeded]; else { [self _removeLayerFromSuperlayer]; // A backing layer is removed regardless of whether it was set implicitly or explicitly // The distinction appears to be based on the layers class, not how it was set (host vs. backing) if([_layer isKindOfClass:[NSViewBackingLayer class]]){ [_layer release]; _layer=nil; } [_subviews makeObjectsPerformSelector:_cmd]; } } -(void)_createLayersInTreeIfNeeded { if(!NSViewLayersEnabled) return; if(_layer==nil){ _layer=[[self makeBackingLayer] retain]; configureLayerGeometry(self); } [self _addLayerToSuperlayer]; [_subviews makeObjectsPerformSelector:_cmd]; } -(void)setWantsLayer:(BOOL)value { if(!value){ if(_wantsLayer){ _wantsLayer=NO; [self _removeLayerBackedViewsFromTree]; } } else { if(!_wantsLayer){ _wantsLayer=YES; [self _createLayersInTreeIfNeeded]; } } } -(void)setLayer:(CALayer *)value { if(!NSViewLayersEnabled) return; if(value!=_layer){ [_subviews makeObjectsPerformSelector:@selector(_removeLayerFromSuperlayer)]; value=[value retain]; if(_layer==nil){ if(value!=nil){ _layer=value; [self _addLayerToSuperlayer]; } } else if(value==nil){ [self _removeLayerFromSuperlayer]; [_layer release]; _layer=nil; } else { [[_superview layer] replaceSublayer:_layer with:value]; [_layer release]; _layer=value; } [_subviews makeObjectsPerformSelector:@selector(_addLayerToSuperlayer)]; } } -(NSViewLayerContentsPlacement)layerContentsPlacement { return _layerContentsPlacement; } -(void)setLayerContentsPlacement:(NSViewLayerContentsPlacement)value { _layerContentsPlacement=value; } -(NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy { return _layerContentsRedrawPolicy; } -(void)setLayerContentsRedrawPolicy:(NSViewLayerContentsRedrawPolicy)value { _layerContentsRedrawPolicy=value; } -(NSArray *)backgroundFilters { NSUnimplementedMethod(); return nil; } -(void)setBackgroundFilters:(NSArray *)filters { // FIXME: implement but dont warn // NSUnimplementedMethod(); } -(NSArray *)contentFilters { return _contentFilters; } -(void)setContentFilters:(NSArray *)filters { filters=[filters copy]; [_contentFilters release]; _contentFilters=filters; } -(CIFilter *)compositingFilter { return _compositingFilter; } -(void)setCompositingFilter:(CIFilter *)filter { filter=[filter copy]; [_compositingFilter release]; _compositingFilter=filter; } -(NSShadow *)shadow { return _shadow; } -(void)setShadow:(NSShadow *)shadow { shadow=[shadow copy]; [_shadow release]; _shadow=shadow; } -(BOOL)needsDisplay { return _needsDisplay; } /* If _needsDisplay is YES and there are no _invalidRects, invalid rect is bounds If _needsDisplay is YES and there are _invalidRects, invalid rect is union You can't just keep a running invalid rect because setting YES then changing the bounds should redraw the new bounds, but changing the bounds should not alter the invalidated rects. */ static NSRect unionOfInvalidRects(NSView *self){ NSRect result; if(self->_invalidRectCount==0) result=[self visibleRect]; else { int i; result=self->_invalidRects[0]; for(i=1;i_invalidRectCount;i++) result=NSUnionRect(result,self->_invalidRects[i]); } return result; } static void removeRectFromInvalidInVisibleRect(NSView *self,NSRect rect,NSRect visibleRect) { int count=self->_invalidRectCount; while(--count>=0){ self->_invalidRects[count]=NSIntersectionRect(self->_invalidRects[count],visibleRect); if(NSContainsRect(rect,self->_invalidRects[count])){ int i; self->_invalidRectCount--; for(i=count;i_invalidRectCount;i++) self->_invalidRects[i]=self->_invalidRects[i+1]; } } if(self->_invalidRectCount==0){ if(self->_invalidRects!=NULL) NSZoneFree(NULL,self->_invalidRects); self->_invalidRects=NULL; } if((self->_invalidRectCount==0) && NSEqualRects(visibleRect,rect)){ self->_needsDisplay=NO; } } static void clearInvalidRects(NSView *self){ if(self->_invalidRects!=NULL) NSZoneFree(NULL,self->_invalidRects); self->_invalidRects=NULL; self->_invalidRectCount=0; } static void clearNeedsDisplay(NSView *self){ clearInvalidRects(self); self->_needsDisplay=NO; } -(void)setNeedsDisplay:(BOOL)flag { _needsDisplay=flag; // We removed them for YES to indicate entire view, and NO for obvious reasons clearInvalidRects(self); if(_needsDisplay) [[self window] setViewsNeedDisplay:YES]; } -(void)setNeedsDisplayInRect:(NSRect)rect { // We only add rects if its not the entire view if(!_needsDisplay || _invalidRects!=NULL){ _invalidRectCount++; _invalidRects=NSZoneRealloc(NULL,_invalidRects,sizeof(NSRect)*_invalidRectCount); _invalidRects[_invalidRectCount-1]=rect; } _needsDisplay=YES; [[self window] setViewsNeedDisplay:YES]; } -(void)setKeyboardFocusRingNeedsDisplayInRect:(NSRect)rect { NSUnimplementedMethod(); } -(void)translateRectsNeedingDisplayInRect:(NSRect)rect by:(NSSize)delta { NSUnimplementedMethod(); } -(BOOL)canDraw { return _window!=nil && ![self isHiddenOrHasHiddenAncestor]; } -(BOOL)canDrawConcurrently { NSUnimplementedMethod(); return NO; } -(void)viewWillDraw { [_subviews makeObjectsPerformSelector:_cmd]; } -(void)setCanDrawConcurrently:(BOOL)canDraw { NSUnimplementedMethod(); } static NSGraphicsContext *graphicsContextForView(NSView *view){ if(view->_layer!=nil){ NSRect frame=[view frame]; size_t width=frame.size.width; size_t height=frame.size.height; CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB(); CGContextRef context=CGBitmapContextCreate(NULL,width,height,8,0,colorSpace,kCGImageAlphaPremultipliedFirst|kCGBitmapByteOrder32Host); NSGraphicsContext *result=[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]; CGColorSpaceRelease(colorSpace); CGContextRelease(context); return result; } return [[view window] graphicsContext]; } -(void)_lockFocusInContext:(NSGraphicsContext *)context { CGContextRef graphicsPort=[context graphicsPort]; [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:context]; [[context focusStack] addObject:self]; CGContextSaveGState(graphicsPort); CGContextResetClip(graphicsPort); if(_layer!=nil) CGContextSetCTM(graphicsPort,[self transformToLayer]); else CGContextSetCTM(graphicsPort,[self transformToWindow]); CGContextClipToRect(graphicsPort,[self visibleRect]); [self setUpGState]; } -(void)lockFocus { [self _lockFocusInContext:graphicsContextForView(self)]; } -(BOOL)lockFocusIfCanDraw { if([self canDraw]){ [self lockFocus]; return YES; } return NO; } -(BOOL)lockFocusIfCanDrawInContext:(NSGraphicsContext *)context { if(context!=nil){ [self _lockFocusInContext:context]; return YES; } return NO; } -(void)unlockFocus { NSGraphicsContext *graphicsContext=[NSGraphicsContext currentContext]; CGContextRef context=[graphicsContext graphicsPort]; if(_layer!=nil){ CGImageRef image=CGBitmapContextCreateImage(context); [_layer setContents:image]; } CGContextRestoreGState(context); [[graphicsContext focusStack] removeLastObject]; [NSGraphicsContext restoreGraphicsState]; } -(BOOL)needsToDrawRect:(NSRect)rect { NSUnimplementedMethod(); return YES; } -(void)getRectsBeingDrawn:(const NSRect **)rects count:(NSInteger *)count { NSUnimplementedMethod(); } -(void)getRectsExposedDuringLiveResize:(NSRect)rects count:(NSInteger *)count { NSUnimplementedMethod(); } -(BOOL)shouldDrawColor { NSUnimplementedMethod(); return YES; } -(NSView *)opaqueAncestor { if([self isOpaque]) return self; return [[self superview] opaqueAncestor]; } -(void)display { [self displayRect:[self visibleRect]]; } -(void)_displayIfNeededWithoutViewWillDraw { if([self needsDisplay]){ [self displayRect:unionOfInvalidRects(self)]; clearNeedsDisplay(self); } int i,count=[_subviews count]; for(i=0;iNSMaxY(bounds)) visible.origin.y=NSMaxY(bounds)-visible.size.height; [self scrollRectToVisible:visible]; } } -(BOOL)performKeyEquivalent:(NSEvent *)event { int i,count=[_subviews count]; for(i=0;i)sender { return NSDragOperationNone; } -(NSDragOperation)draggingUpdated:(id )sender { return [sender draggingSourceOperationMask]; } -(void)draggingExited:(id )sender { // do nothing } -(BOOL)prepareForDragOperation:(id )sender { return NO; } -(BOOL)performDragOperation:(id )sender { return NO; } -(void)concludeDragOperation:(id )sender { // do nothing } -(NSArray *)_draggedTypes { return _draggedTypes; } - (BOOL)dragPromisedFilesOfTypes:(NSArray *)types fromRect:(NSRect)rect source:(id)source slideBack:(BOOL)slideBack event:(NSEvent *)event { NSUnimplementedMethod(); return NO; } -(NSPoint)convertPointFromBase:(NSPoint)aPoint; { return aPoint; } -(NSPoint)convertPointToBase:(NSPoint)aPoint; { return aPoint; } -(NSSize)convertSizeFromBase:(NSSize)aSize { return aSize; } -(NSSize)convertSizeToBase:(NSSize)aSize { return aSize; } -(NSRect)convertRectFromBase:(NSRect)aRect { return aRect; } -(NSRect)convertRectToBase:(NSRect)aRect { return aRect; } -(void)showDefinitionForAttributedString:(NSAttributedString *)string atPoint:(NSPoint)origin { NSUnimplementedMethod(); } +defaultAnimationForKey:(NSString *)key { NSUnimplementedMethod(); return nil; } -animator { NSUnimplementedMethod(); // should return animating proxy. returning self does not animate. return self; } -(NSDictionary *)animations { return _animations; } -animationForKey:(NSString *)key { return [_animations objectForKey:key]; } -(void)setAnimations:(NSDictionary *)dictionary { dictionary=[dictionary copy]; [_animations release]; _animations=dictionary; } // Blocks aren't supported by the compiler yet. //-(void)showDefinitionForAttributedString:(NSAttributedString *)string range:(NSRange)range options:(NSDictionary *)options baselineOriginProvider:(NSPoint (^)(NSRange adjustedRange))originProvider { // NSUnimplementedMethod(); //} -(NSString *)description { return [NSString stringWithFormat:@"<%@[0x%lx] frame: %@>", [self class], self, NSStringFromRect(_frame)]; } @end