mirror of
https://github.com/darlinghq/darling-cocotron.git
synced 2024-11-26 21:40:44 +00:00
2810 lines
79 KiB
Objective-C
2810 lines
79 KiB
Objective-C
/* Copyright (c) 2006-2007 Christopher J. W. Lloyd
|
|
2009-2010 Markus Hitter <mah@jump-ing.de>
|
|
2020 Lubos Dolezel
|
|
|
|
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 <AppKit/NSApplication.h>
|
|
#import <AppKit/NSClipView.h>
|
|
#import <AppKit/NSColor.h>
|
|
#import <AppKit/NSCursor.h>
|
|
#import <AppKit/NSCursorRect.h>
|
|
#import <AppKit/NSDragging.h>
|
|
#import <AppKit/NSDraggingManager.h>
|
|
#import <AppKit/NSEvent.h>
|
|
#import <AppKit/NSGraphics.h>
|
|
#import <AppKit/NSGraphicsContextFunctions.h>
|
|
#import <AppKit/NSMenu.h>
|
|
#import <AppKit/NSObject+BindingSupport.h>
|
|
#import <AppKit/NSPasteboard.h>
|
|
#import <AppKit/NSPrintInfo.h>
|
|
#import <AppKit/NSPrintOperation.h>
|
|
#import <AppKit/NSRaise.h>
|
|
#import <AppKit/NSScrollView.h>
|
|
#import <AppKit/NSTrackingArea.h>
|
|
#import <AppKit/NSView.h>
|
|
#import <AppKit/NSViewBackingLayer.h>
|
|
#import <AppKit/NSWindow-Private.h>
|
|
#import <CoreGraphics/CGWindow.h>
|
|
#import <Foundation/NSKeyedArchiver.h>
|
|
#import <Onyx2D/O2Context.h>
|
|
#import <QuartzCore/CALayerContext.h>
|
|
#import <QuartzCore/CATransaction.h>
|
|
|
|
NSString *const NSViewFrameDidChangeNotification =
|
|
@"NSViewFrameDidChangeNotification";
|
|
NSString *const NSViewBoundsDidChangeNotification =
|
|
@"NSViewBoundsDidChangeNotification";
|
|
NSString *const NSViewFocusDidChangeNotification =
|
|
@"NSViewFocusDidChangeNotification";
|
|
const NSNotificationName NSViewGlobalFrameDidChangeNotification =
|
|
@"NSViewGlobalFrameDidChangeNotification";
|
|
|
|
@interface NSView (NSView_forward)
|
|
- (CGAffineTransform) transformFromWindow;
|
|
- (CGAffineTransform) transformToWindow;
|
|
- (CGAffineTransform) transformToLayer;
|
|
- (void) _trackingAreasChanged;
|
|
@end
|
|
|
|
@implementation NSView
|
|
|
|
static BOOL NSViewLayersEnabled = NO;
|
|
static BOOL NSShowAllViews = NO;
|
|
|
|
+ (void) initialize {
|
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
NSViewLayersEnabled = [defaults boolForKey: @"NSViewLayersEnabled"];
|
|
NSShowAllViews = [defaults boolForKey: @"NSShowAllViews"];
|
|
}
|
|
|
|
- (NSColor *) _borderColorForNSShowAllViews {
|
|
return [NSColor orangeColor];
|
|
}
|
|
|
|
+ (NSView *) focusView {
|
|
return [NSCurrentFocusStack() lastObject];
|
|
}
|
|
|
|
+ (NSMenu *) defaultMenu {
|
|
return nil;
|
|
}
|
|
|
|
+ (NSFocusRingType) defaultFocusRingType {
|
|
NSUnimplementedMethod();
|
|
return 0;
|
|
}
|
|
|
|
- (void) encodeWithCoder: (NSCoder *) coder {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
typedef struct __VFlags {
|
|
#ifdef __BIG_ENDIAN__
|
|
unsigned int rotatedFromBase : 1;
|
|
unsigned int rotatedOrScaledFromBase : 1;
|
|
unsigned int autosizing : 6;
|
|
unsigned int autoresizeSubviews : 1;
|
|
unsigned int wantsGState : 1;
|
|
unsigned int needsDisplay : 1;
|
|
unsigned int validGState : 1;
|
|
unsigned int newGState : 1;
|
|
unsigned int noVerticalAutosizing : 1;
|
|
unsigned int frameChangeNotesSuspended : 1;
|
|
unsigned int needsFrameChangeNote : 1;
|
|
unsigned int focusChangeNotesSuspended : 1;
|
|
unsigned int boundsChangeNotesSuspended : 1;
|
|
unsigned int needsBoundsChangeNote : 1;
|
|
unsigned int removingWithoutInvalidation : 1;
|
|
unsigned int interfaceStyle0 : 1;
|
|
unsigned int needsDisplayForBounds : 1;
|
|
unsigned int specialArchiving : 1;
|
|
unsigned int interfaceStyle1 : 1;
|
|
unsigned int retainCount : 6;
|
|
unsigned int retainCountOverMax : 1;
|
|
unsigned int aboutToResize : 1;
|
|
#else
|
|
unsigned int aboutToResize : 1;
|
|
unsigned int retainCountOverMax : 1;
|
|
unsigned int retainCount : 6;
|
|
unsigned int interfaceStyle1 : 1;
|
|
unsigned int specialArchiving : 1;
|
|
unsigned int needsDisplayForBounds : 1;
|
|
unsigned int interfaceStyle0 : 1;
|
|
unsigned int removingWithoutInvalidation : 1;
|
|
unsigned int needsBoundsChangeNote : 1;
|
|
unsigned int boundsChangeNotesSuspended : 1;
|
|
unsigned int focusChangeNotesSuspended : 1;
|
|
unsigned int needsFrameChangeNote : 1;
|
|
unsigned int frameChangeNotesSuspended : 1;
|
|
unsigned int noVerticalAutosizing : 1;
|
|
unsigned int newGState : 1;
|
|
unsigned int validGState : 1;
|
|
unsigned int needsDisplay : 1;
|
|
unsigned int wantsGState : 1;
|
|
unsigned int autoresizeSubviews : 1;
|
|
unsigned int autosizing : 6;
|
|
unsigned int rotatedOrScaledFromBase : 1;
|
|
unsigned int rotatedFromBase : 1;
|
|
#endif
|
|
} _VFlags;
|
|
|
|
- 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"];
|
|
|
|
if ([keyed containsValueForKey: @"NSBounds"]) {
|
|
_bounds = [keyed decodeRectForKey: @"NSBounds"];
|
|
} else {
|
|
_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 = 0; // IB assigns a default tag id of 0 - which is different from
|
|
// the default in the docs.
|
|
if ([keyed containsValueForKey: @"NSTag"])
|
|
_tag = [keyed decodeIntForKey: @"NSTag"];
|
|
|
|
// Subviews come in from the nib in back to front order
|
|
[_subviews
|
|
addObjectsFromArray: [keyed decodeObjectForKey: @"NSSubviews"]];
|
|
[_subviews
|
|
makeObjectsPerformSelector: @selector(viewWillMoveToSuperview:)
|
|
withObject: self];
|
|
[_subviews makeObjectsPerformSelector: @selector(_setSuperview:)
|
|
withObject: self];
|
|
[_subviews
|
|
makeObjectsPerformSelector: @selector(viewDidMoveToSuperview)];
|
|
|
|
_window = [keyed decodeObjectForKey: @"NSWindow"];
|
|
_superview = [keyed decodeObjectForKey: @"NSSuperview"];
|
|
[self setNextKeyView: [keyed decodeObjectForKey: @"NSNextKeyView"]];
|
|
|
|
if ([keyed containsValueForKey: @"NSViewShadow"])
|
|
[self setShadow: [keyed decodeObjectForKey: @"NSViewShadow"]];
|
|
|
|
if ([keyed containsValueForKey: @"NSViewCompositeFilter"])
|
|
[self setCompositingFilter:
|
|
[keyed decodeObjectForKey:
|
|
@"NSViewCompositeFilter"]];
|
|
|
|
if ([keyed containsValueForKey: @"NSViewBackgroundFilters"])
|
|
[self setBackgroundFilters:
|
|
[keyed decodeObjectForKey:
|
|
@"NSViewBackgroundFilters"]];
|
|
|
|
if ([keyed containsValueForKey: @"NSViewAnimations"])
|
|
[self setAnimations:
|
|
[keyed decodeObjectForKey: @"NSViewAnimations"]];
|
|
|
|
[self setCanDrawConcurrently:
|
|
[keyed decodeBoolForKey: @"NSViewCanDrawConcurrently"]];
|
|
|
|
// TODO: NSViewConstraints, NSViewLayoutGuides, ...
|
|
|
|
_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 {
|
|
NSInteger version = [coder versionForClassName: @"NSView"];
|
|
if (version == 0)
|
|
[NSException raise: NSInvalidArgumentException
|
|
format: @"%@ can not initWithCoder:%@", [self class],
|
|
[coder class]];
|
|
|
|
NSLog(@"NSView version is %d\n", version);
|
|
|
|
union {
|
|
_VFlags vf;
|
|
uint32_t value;
|
|
} vflags;
|
|
|
|
vflags.value = 0;
|
|
NSLog(@"NSView version is %d\n", version);
|
|
|
|
if (version <= 16) {
|
|
float dummy;
|
|
[coder decodeValuesOfObjCTypes: "f", &dummy];
|
|
|
|
_frame = [coder decodeRect];
|
|
_bounds = [coder decodeRect];
|
|
_superview = [coder decodeObject];
|
|
_window = [coder decodeObject];
|
|
|
|
unsigned short flags1, flags2;
|
|
id obj;
|
|
|
|
[coder decodeValuesOfObjCTypes: "@ss@", &_subviews, &flags1,
|
|
&flags2, &obj];
|
|
|
|
vflags.vf.rotatedFromBase = (flags1 & 0x400) != 0;
|
|
vflags.vf.rotatedOrScaledFromBase = vflags.vf.validGState =
|
|
(flags1 & 0x200) != 0;
|
|
vflags.vf.autosizing = (flags2 & 0xFC00) >> 10;
|
|
vflags.vf.autoresizeSubviews = (flags2 & 0x200) != 0;
|
|
vflags.vf.wantsGState = (flags2 & 0x10) != 0;
|
|
} else if (version <= 40) {
|
|
NSUnarchiver *una = (NSUnarchiver *) coder;
|
|
_frame = [coder decodeRect];
|
|
_bounds = [coder decodeRect];
|
|
|
|
_superview = [coder decodeObject];
|
|
_window = [coder decodeObject];
|
|
|
|
id dummy, frameMatrix;
|
|
[coder decodeValuesOfObjCTypes: "@@@@", &_subviews, &dummy,
|
|
&frameMatrix, &_draggedTypes];
|
|
|
|
uint8_t flags1, flags2;
|
|
flags1 = [una decodeByte];
|
|
flags2 = [una decodeByte];
|
|
|
|
union {
|
|
_VFlags vf;
|
|
uint32_t value;
|
|
} vflags;
|
|
|
|
vflags.value = 0;
|
|
vflags.vf.rotatedFromBase = flags1 & 1;
|
|
vflags.vf.rotatedOrScaledFromBase = flags2 & 1;
|
|
|
|
uint8_t flags3, flags4, flags5;
|
|
flags3 = [una decodeByte];
|
|
flags4 = [una decodeByte];
|
|
flags5 = [una decodeByte];
|
|
[una decodeByte];
|
|
|
|
vflags.vf.autosizing = flags3 & 0x3F;
|
|
vflags.vf.autoresizeSubviews = flags4 & 1;
|
|
vflags.vf.wantsGState = flags5 & 1;
|
|
|
|
if (version >= 25) {
|
|
[self setNextKeyView: [coder decodeObject]];
|
|
[una decodeByte];
|
|
}
|
|
} else {
|
|
int flags;
|
|
[coder decodeValuesOfObjCTypes: "i", &flags];
|
|
|
|
vflags.value = flags & 0xFFC00000;
|
|
|
|
id dummy, frameMatrix;
|
|
|
|
float fx, fy, fw, fh;
|
|
float bx, by, bw, bh;
|
|
[coder decodeValuesOfObjCTypes: "@@@@ffffffff", &_draggedTypes,
|
|
&_subviews, &dummy, &frameMatrix,
|
|
&fx, &fy, &fw, &fh, &bx, &by, &bx,
|
|
&bh];
|
|
|
|
_frame = NSMakeRect(fx, fy, fw, fh);
|
|
_bounds = NSMakeRect(bx, by, bw, bh);
|
|
|
|
_superview = [coder decodeObject];
|
|
_window = [coder decodeObject];
|
|
[self setNextKeyView: [coder decodeObject]];
|
|
dummy = [coder decodeObject];
|
|
}
|
|
|
|
_autoresizingMask = vflags.vf.autosizing;
|
|
_autoresizesSubviews = vflags.vf.autoresizeSubviews;
|
|
}
|
|
|
|
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; // according to the docs - loading from a nib gets a default of
|
|
// 0.
|
|
_needsDisplay = YES;
|
|
_invalidRectCount = 0;
|
|
_invalidRects = NULL;
|
|
_trackingAreas = [[NSMutableArray alloc] init];
|
|
|
|
_validTransforms = NO;
|
|
_transformFromWindow = CGAffineTransformIdentity;
|
|
_transformToWindow = CGAffineTransformIdentity;
|
|
_transformToLayer = CGAffineTransformIdentity;
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void) dealloc {
|
|
|
|
// Do this first?
|
|
[self _unbindAllBindings];
|
|
|
|
_window = nil;
|
|
[_menu release];
|
|
|
|
_superview = nil;
|
|
[_subviews makeObjectsPerformSelector: @selector(_setSuperview:)
|
|
withObject: nil];
|
|
|
|
[_subviews release];
|
|
[_draggedTypes release];
|
|
[_trackingAreas release];
|
|
[_contentFilters release];
|
|
|
|
if (_invalidRects != NULL)
|
|
NSZoneFree(NULL, _invalidRects);
|
|
|
|
if (_rectsBeingRedrawn != NULL) {
|
|
NSZoneFree(NULL, _rectsBeingRedrawn);
|
|
}
|
|
[_layer release];
|
|
|
|
[_layerContext invalidate];
|
|
[_layerContext 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);
|
|
|
|
// Apply bounds scaling to fit in the frame
|
|
CGAffineTransform scale =
|
|
CGAffineTransformMakeScale(NSWidth(frame) / NSWidth(bounds),
|
|
NSHeight(frame) / NSHeight(bounds));
|
|
result = CGAffineTransformConcat(scale, result);
|
|
|
|
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;
|
|
}
|
|
|
|
- (NSAutoresizingMaskOptions) autoresizingMask {
|
|
return _autoresizingMask;
|
|
}
|
|
|
|
- (NSFocusRingType) focusRingType {
|
|
return _focusRingType;
|
|
}
|
|
|
|
- (NSInteger) 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];
|
|
|
|
if (_isHidden)
|
|
[self viewDidHide];
|
|
else
|
|
[self viewDidUnhide];
|
|
}
|
|
}
|
|
|
|
- (void) viewDidHide {
|
|
// do nothing?
|
|
}
|
|
|
|
- (void) viewDidUnhide {
|
|
// do nothing?
|
|
}
|
|
|
|
- (BOOL) canBecomeKeyView {
|
|
return [self acceptsFirstResponder] && ![self isHiddenOrHasHiddenAncestor];
|
|
}
|
|
|
|
// Cocoa does that for views, despite the "The default implementation returns
|
|
// NO" from the documentation
|
|
- (BOOL) needsPanelToBecomeKey {
|
|
return [self acceptsFirstResponder];
|
|
}
|
|
|
|
- (NSView *) nextKeyView {
|
|
return _nextKeyView;
|
|
}
|
|
|
|
- (NSView *) nextValidKeyView {
|
|
NSView *result = [self nextKeyView];
|
|
|
|
while (result != nil && ![result canBecomeKeyView]) {
|
|
// prevent an infinite loop
|
|
if (result == self)
|
|
return nil;
|
|
|
|
result = [result nextKeyView];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
- (NSView *) previousKeyView {
|
|
return _previousKeyView;
|
|
}
|
|
|
|
- (NSView *) previousValidKeyView {
|
|
NSView *result = [self previousKeyView];
|
|
|
|
while (result != nil && ![result canBecomeKeyView]) {
|
|
// prevent an infinite loop
|
|
if (result == self)
|
|
return nil;
|
|
result = [result previousKeyView];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
- (NSMenu *) menu {
|
|
return _menu;
|
|
}
|
|
|
|
- (NSMenu *) menuForEvent: (NSEvent *) event {
|
|
NSMenu *result = [self menu];
|
|
|
|
if (result == nil) {
|
|
result = [[self class] defaultMenu];
|
|
|
|
if (result) {
|
|
NSArray *itemArray = [result itemArray];
|
|
int i, count = [itemArray count];
|
|
for (i = 0; i < count; i++) {
|
|
NSMenuItem *item = [itemArray objectAtIndex: i];
|
|
[item setTarget: self];
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
- (NSMenuItem *) enclosingMenuItem {
|
|
NSUnimplementedMethod();
|
|
return nil;
|
|
}
|
|
|
|
- (NSString *) toolTip {
|
|
NSUInteger i, count = [_trackingAreas count];
|
|
NSString *toolTip = nil;
|
|
|
|
// In case there's more than one ToolTip the behavior
|
|
// is undocumented. Return the first one.
|
|
for (i = 0; i < count; i++) {
|
|
NSTrackingArea *area = [_trackingAreas objectAtIndex: i];
|
|
|
|
if ([area _isToolTip] == YES) {
|
|
toolTip = [area owner];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return toolTip;
|
|
}
|
|
|
|
- viewWithTag: (NSInteger) tag {
|
|
int i, count = [_subviews count];
|
|
|
|
if (_tag == tag)
|
|
return self;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
NSView *view = [[_subviews objectAtIndex: i] viewWithTag: tag];
|
|
|
|
if (view != nil)
|
|
return view;
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
- (NSView *) hitTest: (NSPoint) point {
|
|
if (_isHidden) {
|
|
return nil;
|
|
}
|
|
|
|
point = [self convertPoint: point fromView: [self superview]];
|
|
|
|
if (NSMouseInRect(point, [self visibleRect], [self isFlipped]) == NO) {
|
|
return nil;
|
|
} else {
|
|
// Subviews are ordered back to front so we need to go
|
|
// front to back in order to hit test correctly.
|
|
NSArray *subviews = [self subviews];
|
|
int count = [subviews count];
|
|
|
|
while (--count >= 0) {
|
|
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 < point1.y) {
|
|
CGFloat temp = point2.y;
|
|
point2.y = point1.y;
|
|
point1.y = temp;
|
|
}
|
|
|
|
return NSMakeRect(point1.x, point1.y, point2.x - point1.x,
|
|
point2.y - point1.y);
|
|
}
|
|
|
|
- (NSRect) convertRect: (NSRect) rect toView: (NSView *) viewOrNil {
|
|
NSView *toView =
|
|
(viewOrNil != nil) ? viewOrNil : [[self window] _backgroundView];
|
|
CGAffineTransform toWindow = [self transformToWindow];
|
|
CGAffineTransform fromWindow = [toView 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 < point1.y) {
|
|
CGFloat temp = point2.y;
|
|
point2.y = point1.y;
|
|
point1.y = temp;
|
|
}
|
|
|
|
return NSMakeRect(point1.x, point1.y, point2.x - point1.x,
|
|
point2.y - point1.y);
|
|
}
|
|
|
|
- (NSRect) centerScanRect: (NSRect) rect {
|
|
CGFloat minx = floor(NSMinX(rect) + 0.5);
|
|
CGFloat miny = floor(NSMinY(rect) + 0.5);
|
|
CGFloat maxx = floor(NSMaxX(rect) + 0.5);
|
|
CGFloat maxy = floor(NSMaxY(rect) + 0.5);
|
|
|
|
return NSMakeRect(minx, miny, maxx - minx, maxy - miny);
|
|
}
|
|
|
|
- (void) setFrame: (NSRect) frame {
|
|
// Cocoa does not post the notification if the frames are equal
|
|
// Possible that resizeSubviewsWithOldSize is not called if the sizes are
|
|
// equal
|
|
if (NSEqualRects(_frame, frame))
|
|
return;
|
|
|
|
NSSize oldSize = _bounds.size;
|
|
|
|
if (_bounds.size.width == 0 || _bounds.size.height == 0) {
|
|
// No valid current bounds value - just update it to use the frame size
|
|
_bounds.size = frame.size;
|
|
} else {
|
|
// Get the bounds->frame transform
|
|
CGAffineTransform transform = concatViewTransform(
|
|
CGAffineTransformIdentity, self, nil, YES, NO);
|
|
// ... and invert it so we can get the new bounds size from the new
|
|
// frame size
|
|
transform = CGAffineTransformInvert(transform);
|
|
|
|
_bounds.size = CGSizeApplyAffineTransform(frame.size, transform);
|
|
}
|
|
_frame = frame;
|
|
|
|
[_window invalidateCursorRectsForView: self]; // this also invalidates
|
|
// tracking areas
|
|
|
|
if (_autoresizesSubviews) {
|
|
[self resizeSubviewsWithOldSize: oldSize];
|
|
}
|
|
|
|
NSRect layerFrame = _frame;
|
|
|
|
if (_superview != nil)
|
|
layerFrame = [_superview convertRect: layerFrame toView: nil];
|
|
|
|
[_layerContext setFrame: layerFrame];
|
|
|
|
invalidateTransform(self);
|
|
|
|
if (_postsNotificationOnFrameChange)
|
|
[[NSNotificationCenter defaultCenter]
|
|
postNotificationName: NSViewFrameDidChangeNotification
|
|
object: self];
|
|
}
|
|
|
|
- (void) setFrameSize: (NSSize) size {
|
|
NSRect frame = _frame;
|
|
|
|
frame.size = size;
|
|
[self setFrame: frame];
|
|
}
|
|
|
|
- (void) setFrameOrigin: (NSPoint) origin {
|
|
NSRect frame = [self frame];
|
|
|
|
frame.origin = origin;
|
|
[self setFrame: frame];
|
|
}
|
|
|
|
- (void) setFrameRotation: (CGFloat) angle {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) setFrameCenterRotation: (CGFloat) angle {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) setBounds: (NSRect) bounds {
|
|
if (!NSEqualRects(bounds, _bounds)) {
|
|
_bounds = bounds;
|
|
invalidateTransform(self);
|
|
|
|
[_window invalidateCursorRectsForView: self]; // this also invalidates
|
|
// tracking areas
|
|
|
|
if (_postsNotificationOnBoundsChange)
|
|
[[NSNotificationCenter defaultCenter]
|
|
postNotificationName: NSViewBoundsDidChangeNotification
|
|
object: self];
|
|
}
|
|
}
|
|
|
|
- (void) setBoundsSize: (NSSize) size {
|
|
NSRect bounds = [self bounds];
|
|
|
|
bounds.size = size;
|
|
|
|
[self setBounds: bounds];
|
|
}
|
|
|
|
- (void) setBoundsOrigin: (NSPoint) origin {
|
|
NSRect bounds = [self bounds];
|
|
|
|
bounds.origin = origin;
|
|
|
|
[self setBounds: bounds];
|
|
}
|
|
|
|
- (void) setBoundsRotation: (CGFloat) angle {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) setPostsFrameChangedNotifications: (BOOL) flag {
|
|
_postsNotificationOnFrameChange = flag;
|
|
}
|
|
|
|
- (void) setPostsBoundsChangedNotifications: (BOOL) flag {
|
|
_postsNotificationOnBoundsChange = flag;
|
|
}
|
|
|
|
- (void) _setWindow: (NSWindow *) window {
|
|
if (_window != window) {
|
|
BOOL windowRecalulatesKeyViewLoop =
|
|
[window autorecalculatesKeyViewLoop];
|
|
if (windowRecalulatesKeyViewLoop)
|
|
[self setNextKeyView: nil];
|
|
|
|
[self viewWillMoveToWindow: window];
|
|
|
|
_window = window;
|
|
|
|
[_subviews makeObjectsPerformSelector: _cmd withObject: window];
|
|
_validTrackingAreas = NO;
|
|
[_window invalidateCursorRectsForView: self]; // this also invalidates
|
|
// tracking areas
|
|
|
|
if (windowRecalulatesKeyViewLoop)
|
|
[_window recalculateKeyViewLoop];
|
|
|
|
[self viewDidMoveToWindow];
|
|
}
|
|
}
|
|
|
|
- (void) _setSuperview: superview {
|
|
_superview = superview;
|
|
|
|
[_window invalidateCursorRectsForView: self]; // this also invalidates
|
|
// tracking areas
|
|
|
|
[self setNextResponder: superview];
|
|
}
|
|
|
|
- (void) _insertSubview: (NSView *) view atIndex: (NSInteger) index {
|
|
|
|
[view retain];
|
|
if ([view superview] == self)
|
|
[_subviews removeObjectIdenticalTo: view];
|
|
else {
|
|
[view removeFromSuperview];
|
|
|
|
[view _setWindow: _window];
|
|
|
|
[view viewWillMoveToSuperview: self];
|
|
[view _setSuperview: self];
|
|
}
|
|
|
|
if (index == NSNotFound)
|
|
[_subviews addObject: view];
|
|
else
|
|
[_subviews insertObject: view atIndex: index];
|
|
[view release];
|
|
|
|
invalidateTransform(view);
|
|
|
|
[self setNeedsDisplayInRect: [view frame]];
|
|
|
|
[view viewDidMoveToSuperview];
|
|
|
|
if (_wantsLayer)
|
|
[view setWantsLayer: YES];
|
|
}
|
|
|
|
- (void) addSubview: (NSView *) view {
|
|
if (view == nil) // yes, this is silently ignored
|
|
return;
|
|
|
|
[self _insertSubview: view atIndex: NSNotFound];
|
|
}
|
|
|
|
- (void) addSubview: (NSView *) view
|
|
positioned: (NSWindowOrderingMode) ordering
|
|
relativeTo: (NSView *) relativeTo
|
|
{
|
|
NSUInteger index = [_subviews indexOfObjectIdenticalTo: relativeTo];
|
|
|
|
if (index == NSNotFound)
|
|
index = (ordering == NSWindowBelow) ? 0 : NSNotFound;
|
|
else
|
|
index = (ordering == NSWindowBelow)
|
|
? index
|
|
: ((index + 1 == [_subviews count]) ? NSNotFound
|
|
: index + 1);
|
|
|
|
[self _insertSubview: view atIndex: index];
|
|
}
|
|
|
|
- (void) replaceSubview: (NSView *) oldView with: (NSView *) newView {
|
|
NSUInteger index = [_subviews indexOfObjectIdenticalTo: oldView];
|
|
|
|
[oldView retain];
|
|
[oldView removeFromSuperview];
|
|
[self _insertSubview: newView atIndex: index];
|
|
[oldView release];
|
|
}
|
|
|
|
- (void) setSubviews: (NSArray *) array {
|
|
// This method marks as needing display per doc.s
|
|
|
|
while ([_subviews count])
|
|
[[_subviews lastObject] removeFromSuperview];
|
|
|
|
for (NSView *view in array) {
|
|
[self addSubview: view];
|
|
[view setNeedsDisplay: YES];
|
|
}
|
|
}
|
|
|
|
- (void) sortSubviewsUsingFunction:
|
|
(NSComparisonResult (*)(id, id, void *)) compareFunction
|
|
context: (void *) context
|
|
{
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) didAddSubview: (NSView *) subview {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) willRemoveSubview: (NSView *) subview {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) setAutoresizesSubviews: (BOOL) flag {
|
|
_autoresizesSubviews = flag;
|
|
}
|
|
|
|
- (void) setAutoresizingMask: (NSAutoresizingMaskOptions) mask {
|
|
_autoresizingMask = mask;
|
|
}
|
|
|
|
- (void) setFocusRingType: (NSFocusRingType) value {
|
|
_focusRingType = value;
|
|
[self setNeedsDisplay: YES];
|
|
}
|
|
|
|
- (void) setTag: (NSInteger) tag {
|
|
_tag = tag;
|
|
}
|
|
|
|
- (void) _setPreviousKeyView: (NSView *) previous {
|
|
_previousKeyView = previous;
|
|
}
|
|
|
|
- (void) setNextKeyView: (NSView *) next {
|
|
if (next)
|
|
[next _setPreviousKeyView: self];
|
|
else
|
|
[_nextKeyView _setPreviousKeyView: nil];
|
|
|
|
_nextKeyView = next;
|
|
}
|
|
|
|
- (BOOL) acceptsFirstMouse: (NSEvent *) event {
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL) acceptsTouchEvents {
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (void) setAcceptsTouchEvents: (BOOL) accepts {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (BOOL) wantsRestingTouches {
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (void) setWantsRestingTouches: (BOOL) wants {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) setToolTip: (NSString *) string {
|
|
[self removeAllToolTips];
|
|
if (string != nil && ![string isEqualToString: @""])
|
|
[self addToolTipRect: [self bounds] owner: string userData: NULL];
|
|
}
|
|
|
|
- (NSToolTipTag) addToolTipRect: (NSRect) rect
|
|
owner: object
|
|
userData: (void *) userData
|
|
{
|
|
NSTrackingArea *area = nil;
|
|
|
|
area = [[NSTrackingArea alloc] _initWithRect: rect
|
|
options: 0
|
|
owner: object
|
|
userData: userData
|
|
retainUserData: NO
|
|
isToolTip: YES
|
|
isLegacy: NO];
|
|
[_trackingAreas addObject: area];
|
|
[area release];
|
|
|
|
[self _trackingAreasChanged];
|
|
|
|
return area;
|
|
}
|
|
|
|
- (void) removeToolTip: (NSToolTipTag) tag {
|
|
[self removeTrackingArea: tag];
|
|
}
|
|
|
|
- (void) removeAllToolTips {
|
|
NSInteger count = [_trackingAreas count];
|
|
|
|
while (--count >= 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; i < count; i++) {
|
|
NSTrackingArea *area = [_trackingAreas objectAtIndex: i];
|
|
NSRect rectOfInterest;
|
|
|
|
rectOfInterest = NSIntersectionRect([area rect], [self bounds]);
|
|
|
|
if (rectOfInterest.size.width > 0. &&
|
|
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; i < count; i++)
|
|
[(NSView *) [subviews objectAtIndex: i]
|
|
_collectTrackingAreasForWindowInto: collector];
|
|
}
|
|
}
|
|
|
|
- (NSArray *) trackingAreas {
|
|
return _trackingAreas;
|
|
}
|
|
|
|
- (void) _trackingAreasChanged {
|
|
[[self window] _invalidateTrackingAreas];
|
|
}
|
|
|
|
- (void) addTrackingArea: (NSTrackingArea *) trackingArea {
|
|
[_trackingAreas addObject: trackingArea];
|
|
[self _trackingAreasChanged];
|
|
}
|
|
|
|
- (void) removeTrackingArea: (NSTrackingArea *) trackingArea {
|
|
[_trackingAreas removeObjectIdenticalTo: trackingArea];
|
|
[self _trackingAreasChanged];
|
|
}
|
|
|
|
- (void) updateTrackingAreas {
|
|
[self _trackingAreasChanged];
|
|
}
|
|
|
|
- (NSTrackingRectTag) addTrackingRect: (NSRect) rect
|
|
owner: owner
|
|
userData: (void *) userData
|
|
assumeInside: (BOOL) assumeInside
|
|
{
|
|
NSTrackingAreaOptions options =
|
|
NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways;
|
|
NSTrackingArea *area = nil;
|
|
|
|
if (assumeInside == YES)
|
|
options |= NSTrackingAssumeInside;
|
|
|
|
area = [[NSTrackingArea alloc] _initWithRect: rect
|
|
options: options
|
|
owner: owner
|
|
userData: NULL
|
|
retainUserData: NO
|
|
isToolTip: NO
|
|
isLegacy: NO];
|
|
[_trackingAreas addObject: area];
|
|
[area release];
|
|
|
|
[self _trackingAreasChanged];
|
|
|
|
return area;
|
|
}
|
|
|
|
- (void) removeTrackingRect: (NSTrackingRectTag) tag {
|
|
[self removeTrackingArea: tag];
|
|
}
|
|
|
|
- (NSTextInputContext *) inputContext {
|
|
NSUnimplementedMethod();
|
|
return nil;
|
|
}
|
|
|
|
- (void) registerForDraggedTypes: (NSArray *) types {
|
|
types = [types copy];
|
|
[_draggedTypes release];
|
|
_draggedTypes = types;
|
|
}
|
|
|
|
- (void) unregisterDraggedTypes {
|
|
[_draggedTypes release];
|
|
_draggedTypes = nil;
|
|
}
|
|
|
|
- (NSArray *) registeredDraggedTypes {
|
|
return _draggedTypes;
|
|
}
|
|
|
|
- (void) _deepResignFirstResponder {
|
|
if ([_window firstResponder] == self)
|
|
[_window makeFirstResponder: nil];
|
|
|
|
[[self subviews] makeObjectsPerformSelector: _cmd];
|
|
}
|
|
|
|
- (void) removeFromSuperview {
|
|
[_superview setNeedsDisplayInRect: [self frame]];
|
|
[self removeFromSuperviewWithoutNeedingDisplay];
|
|
}
|
|
|
|
- (void) _removeViewWithoutDisplay: (NSView *) view {
|
|
[_subviews removeObjectIdenticalTo: view];
|
|
}
|
|
|
|
- (void) removeFromSuperviewWithoutNeedingDisplay {
|
|
NSView *removeFrom = _superview;
|
|
NSWindow *window = [self window];
|
|
|
|
[self _deepResignFirstResponder];
|
|
[self _setSuperview: nil];
|
|
[self _setWindow: nil];
|
|
|
|
[removeFrom _removeViewWithoutDisplay: self];
|
|
[window _invalidateTrackingAreas];
|
|
}
|
|
|
|
- (void) viewWillMoveToSuperview: (NSView *) view {
|
|
// Intentionally empty.
|
|
}
|
|
|
|
- (void) viewDidMoveToSuperview {
|
|
// Intentionally empty.
|
|
}
|
|
|
|
- (void) viewWillMoveToWindow: (NSWindow *) window {
|
|
// Intentionally empty.
|
|
}
|
|
|
|
- (void) viewDidMoveToWindow {
|
|
// Default implementation does nothing
|
|
}
|
|
|
|
- (BOOL) shouldDelayWindowOrderingForEvent: (NSEvent *) event {
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (void) resizeSubviewsWithOldSize: (NSSize) oldSize {
|
|
int i, count = [_subviews count];
|
|
|
|
for (i = 0; i < count; i++)
|
|
[[_subviews objectAtIndex: i] resizeWithOldSuperviewSize: oldSize];
|
|
}
|
|
|
|
- (void) resizeWithOldSuperviewSize: (NSSize) oldSize {
|
|
NSRect superFrame = [_superview frame];
|
|
NSRect frame = [self frame];
|
|
BOOL originChanged = NO, sizeChanged = NO;
|
|
|
|
if (_autoresizingMask & NSViewMinXMargin) {
|
|
if (_autoresizingMask & NSViewWidthSizable) {
|
|
if (_autoresizingMask & NSViewMaxXMargin) {
|
|
frame.origin.x += ((superFrame.size.width - oldSize.width) / 3);
|
|
frame.size.width +=
|
|
((superFrame.size.width - oldSize.width) / 3);
|
|
} else {
|
|
frame.origin.x += ((superFrame.size.width - oldSize.width) / 2);
|
|
frame.size.width +=
|
|
((superFrame.size.width - oldSize.width) / 2);
|
|
}
|
|
originChanged = YES;
|
|
sizeChanged = YES;
|
|
} else if (_autoresizingMask & NSViewMaxXMargin) {
|
|
frame.origin.x += ((superFrame.size.width - oldSize.width) / 2);
|
|
originChanged = YES;
|
|
} else {
|
|
frame.origin.x += superFrame.size.width - oldSize.width;
|
|
originChanged = YES;
|
|
}
|
|
} else if (_autoresizingMask & NSViewWidthSizable) {
|
|
if (_autoresizingMask & NSViewMaxXMargin)
|
|
frame.size.width += ((superFrame.size.width - oldSize.width) / 2);
|
|
else
|
|
frame.size.width += superFrame.size.width - oldSize.width;
|
|
sizeChanged = YES;
|
|
} else if (_autoresizingMask & NSViewMaxXMargin) {
|
|
// don't move or resize
|
|
}
|
|
|
|
if (_autoresizingMask & NSViewMinYMargin) {
|
|
if (_autoresizingMask & NSViewHeightSizable) {
|
|
if (_autoresizingMask & NSViewMaxYMargin) {
|
|
frame.origin.y +=
|
|
((superFrame.size.height - oldSize.height) / 3);
|
|
frame.size.height +=
|
|
((superFrame.size.height - oldSize.height) / 3);
|
|
} else {
|
|
frame.origin.y +=
|
|
((superFrame.size.height - oldSize.height) / 2);
|
|
frame.size.height +=
|
|
((superFrame.size.height - oldSize.height) / 2);
|
|
}
|
|
originChanged = YES;
|
|
sizeChanged = YES;
|
|
} else if (_autoresizingMask & NSViewMaxYMargin) {
|
|
frame.origin.y += ((superFrame.size.height - oldSize.height) / 2);
|
|
originChanged = YES;
|
|
} else {
|
|
frame.origin.y += superFrame.size.height - oldSize.height;
|
|
originChanged = YES;
|
|
}
|
|
} else if (_autoresizingMask & NSViewHeightSizable) {
|
|
if (_autoresizingMask & NSViewMaxYMargin)
|
|
frame.size.height +=
|
|
((superFrame.size.height - oldSize.height) / 2);
|
|
else
|
|
frame.size.height += superFrame.size.height - oldSize.height;
|
|
sizeChanged = YES;
|
|
}
|
|
|
|
if (originChanged || sizeChanged)
|
|
[self setFrame: frame];
|
|
}
|
|
|
|
- (BOOL) inLiveResize {
|
|
return _inLiveResize;
|
|
}
|
|
|
|
- (BOOL) preservesContentDuringLiveResize {
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (NSRect) rectPreservedDuringLiveResize {
|
|
NSUnimplementedMethod();
|
|
return NSZeroRect;
|
|
}
|
|
|
|
- (void) viewWillStartLiveResize {
|
|
_inLiveResize = YES;
|
|
[_subviews makeObjectsPerformSelector: _cmd];
|
|
}
|
|
|
|
- (void) viewDidEndLiveResize {
|
|
_inLiveResize = NO;
|
|
[_subviews makeObjectsPerformSelector: _cmd];
|
|
}
|
|
|
|
- (BOOL) enterFullScreenMode: (NSScreen *) screen
|
|
withOptions: (NSDictionary *) options
|
|
{
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL) isInFullScreenMode {
|
|
// dont issue warning
|
|
return NO;
|
|
}
|
|
|
|
- (void) exitFullScreenModeWithOptions: (NSDictionary *) options {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (NSClipView *) _enclosingClipView {
|
|
id result = [self superview];
|
|
|
|
for (; result != nil; result = [result superview])
|
|
if ([result isKindOfClass: [NSClipView class]])
|
|
return result;
|
|
|
|
return nil;
|
|
}
|
|
|
|
- (void) scrollPoint: (NSPoint) point {
|
|
NSClipView *clipView = [self _enclosingClipView];
|
|
|
|
if (clipView != nil) {
|
|
NSPoint origin = [self convertPoint: point toView: clipView];
|
|
|
|
[clipView scrollToPoint: origin];
|
|
}
|
|
}
|
|
|
|
- (BOOL) scrollRectToVisible: (NSRect) rect {
|
|
NSClipView *clipView = [self _enclosingClipView];
|
|
NSView *documentView = [clipView documentView];
|
|
// Current the document view visible rect in document view space
|
|
NSRect vRect = [clipView documentVisibleRect];
|
|
// Convert what we want in the document view space
|
|
rect = [documentView convertRect: rect fromView: self];
|
|
|
|
// Do the minimal amount of scrolling to show the rect
|
|
|
|
// Missing amount on the four directions
|
|
CGFloat missingLeft = NSMinX(vRect) - NSMinX(rect);
|
|
CGFloat missingRight = NSMaxX(rect) - NSMaxX(vRect);
|
|
|
|
CGFloat missingTop = NSMinY(vRect) - NSMinY(rect);
|
|
CGFloat missingBottom = NSMaxY(rect) - NSMaxY(vRect);
|
|
|
|
CGFloat dx = 0.;
|
|
CGFloat dy = 0.;
|
|
|
|
if (missingLeft * missingRight < 0) {
|
|
// We need to scroll in one direction - no need to scroll if we're
|
|
// missing bits both ways or if everything is visible
|
|
|
|
// Let's do the minimal amount of scrolling
|
|
if (fabs(missingLeft) < fabs(missingRight)) {
|
|
dx = -missingLeft;
|
|
} else {
|
|
dx = missingRight;
|
|
}
|
|
}
|
|
|
|
if (missingTop * missingBottom < 0) {
|
|
// We need to scroll in one direction - no need to scroll if we're
|
|
// missing bits both ways or if everything is visible
|
|
|
|
// Let's do the minimal amount of scrolling
|
|
if (fabs(missingTop) < fabs(missingBottom)) {
|
|
dy = -missingTop;
|
|
} else {
|
|
dy = missingBottom;
|
|
}
|
|
}
|
|
if (dx != 0 || dy != 0) {
|
|
NSPoint pt = vRect.origin;
|
|
pt.x += dx;
|
|
pt.y += dy;
|
|
pt = [documentView convertPoint: pt toView: clipView];
|
|
[clipView scrollToPoint: pt];
|
|
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];
|
|
[_layerContext invalidate];
|
|
[_layerContext release];
|
|
_layerContext = nil;
|
|
}
|
|
|
|
- (void) _createLayerContextIfNeeded {
|
|
if ([_superview layer] == nil) {
|
|
_layerContext = [[CALayerContext alloc] initWithFrame: [self frame]];
|
|
[_layerContext setLayer: _layer];
|
|
}
|
|
}
|
|
|
|
- (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 < self->_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 < self->_invalidRectCount; i++)
|
|
self->_invalidRects[i] = self->_invalidRects[i + 1];
|
|
}
|
|
}
|
|
if (self->_invalidRectCount == 0) {
|
|
if (self->_invalidRects != NULL) {
|
|
NSZoneFree(NULL, self->_invalidRects);
|
|
self->_invalidRects = NULL;
|
|
// We killed the last invalidRect - we're clean now
|
|
self->_needsDisplay = NO;
|
|
} else if (NSContainsRect(rect, visibleRect)) {
|
|
// We had no invalidRect, which means the full visibleRect was dirty
|
|
// We're now clean
|
|
self->_needsDisplay = NO;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void clearRectsBeingRedrawn(NSView *self) {
|
|
if (self->_rectsBeingRedrawn) {
|
|
NSZoneFree(NULL, self->_rectsBeingRedrawn);
|
|
self->_rectsBeingRedrawn = NULL;
|
|
self->_rectsBeingRedrawnCount = 0;
|
|
}
|
|
}
|
|
|
|
static void clearInvalidRects(NSView *self) {
|
|
if (self->_invalidRects != NULL)
|
|
NSZoneFree(NULL, self->_invalidRects);
|
|
self->_invalidRects = NULL;
|
|
self->_invalidRectCount = 0;
|
|
clearRectsBeingRedrawn(self);
|
|
}
|
|
|
|
static void clearNeedsDisplay(NSView *self) {
|
|
if ([NSGraphicsContext inQuartzDebugMode]) {
|
|
return;
|
|
}
|
|
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) {
|
|
NSRect visibleRect = [self visibleRect];
|
|
rect = NSIntersectionRect(visibleRect, rect);
|
|
if (NSContainsRect(rect, visibleRect)) {
|
|
clearInvalidRects(self); // Everything is dirty
|
|
} else {
|
|
// All of our clipping done by the context is rounded - so we need
|
|
// to do the same here else we might get some artifact on clipping
|
|
// borders
|
|
rect = [self convertRect: rect toView: nil];
|
|
rect = NSIntegralRect(rect);
|
|
rect = [self convertRect: rect fromView: nil];
|
|
_invalidRectCount++;
|
|
_invalidRects = NSZoneRealloc(NULL, _invalidRects,
|
|
sizeof(NSRect) * _invalidRectCount);
|
|
_invalidRects[_invalidRectCount - 1] = rect;
|
|
}
|
|
clearRectsBeingRedrawn(self);
|
|
|
|
// We also needs to be sure all of our superviews will properly redraw
|
|
// this area, even if they are smart about what to redraw (using
|
|
// needsDisplayInRect:)
|
|
NSView *opaqueAncestor = [self opaqueAncestor];
|
|
if (opaqueAncestor != self) {
|
|
NSRect dirtyRect = [self convertRect: rect toView: opaqueAncestor];
|
|
[opaqueAncestor setNeedsDisplayInRect: dirtyRect];
|
|
}
|
|
}
|
|
|
|
_needsDisplay = YES;
|
|
[[self window] setViewsNeedDisplay: YES];
|
|
}
|
|
|
|
- (void) setKeyboardFocusRingNeedsDisplayInRect: (NSRect) rect {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) translateRectsNeedingDisplayInRect: (NSRect) rect by: (NSSize) delta {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
static NSView *viewBeingPrinted = nil;
|
|
|
|
- (BOOL) canDraw {
|
|
return (viewBeingPrinted != nil &&
|
|
[self isDescendantOf: viewBeingPrinted]) ||
|
|
(_window != nil && ![self isHiddenOrHasHiddenAncestor]);
|
|
}
|
|
|
|
- (BOOL) canDrawConcurrently {
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (void) viewWillDraw {
|
|
[_subviews makeObjectsPerformSelector: _cmd];
|
|
}
|
|
|
|
- (void) setCanDrawConcurrently: (BOOL) canDraw {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) _lockFocusInContext: (NSGraphicsContext *) context {
|
|
NSGraphicsContext *windowContext = [_window graphicsContext];
|
|
|
|
if (context == nil) {
|
|
if (viewBeingPrinted != nil) {
|
|
context = [[NSPrintOperation currentOperation] context];
|
|
} else if (_layer != nil) {
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
CGFloat width = _frame.size.width;
|
|
CGFloat height = _frame.size.height;
|
|
CGContextRef graphicsPort = CGBitmapContextCreate(
|
|
NULL, width, height, 8, 0, colorSpace,
|
|
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
|
|
context = [NSGraphicsContext
|
|
graphicsContextWithGraphicsPort: graphicsPort
|
|
flipped: NO];
|
|
CGColorSpaceRelease(colorSpace);
|
|
CGContextRelease(graphicsPort); // we'll re-fetch it below
|
|
} else {
|
|
context = windowContext;
|
|
}
|
|
}
|
|
CGContextRef graphicsPort = [context graphicsPort];
|
|
|
|
[NSGraphicsContext saveGraphicsState];
|
|
[NSGraphicsContext setCurrentContext: context];
|
|
|
|
[[context focusStack] addObject: self];
|
|
|
|
CGContextSaveGState(graphicsPort);
|
|
CGContextResetClip(graphicsPort);
|
|
|
|
if (context == windowContext) {
|
|
CGContextSetCTM(graphicsPort, [self transformToWindow]);
|
|
CGContextClipToRect(graphicsPort, [self visibleRect]);
|
|
} else {
|
|
CGAffineTransform transform = CGAffineTransformIdentity;
|
|
if (viewBeingPrinted != nil) {
|
|
transform = CGAffineTransformConcat(
|
|
[self transformToWindow],
|
|
[viewBeingPrinted transformFromWindow]);
|
|
}
|
|
NSView *targetView = viewBeingPrinted == nil ? self : viewBeingPrinted;
|
|
transform = CGAffineTransformConcat(transform,
|
|
[targetView transformToLayer]);
|
|
CGContextSetCTM(graphicsPort, transform);
|
|
}
|
|
|
|
[self setUpGState];
|
|
}
|
|
|
|
- (void) lockFocus {
|
|
[self _lockFocusInContext: nil];
|
|
}
|
|
|
|
- (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 (viewBeingPrinted == nil && _layer != nil) {
|
|
CGImageRef image = CGBitmapContextCreateImage(context);
|
|
[_layer setContents: image];
|
|
}
|
|
|
|
CGContextRestoreGState(context);
|
|
|
|
[[graphicsContext focusStack] removeLastObject];
|
|
[NSGraphicsContext restoreGraphicsState];
|
|
}
|
|
|
|
- (BOOL) needsToDrawRect: (NSRect) rect {
|
|
BOOL needsToDrawRect = NO;
|
|
|
|
if (NSIntersectsRect(rect, _visibleRect)) {
|
|
const NSRect *rects;
|
|
NSInteger count;
|
|
[self getRectsBeingDrawn: &rects count: &count];
|
|
if (count) {
|
|
for (int i = 0; i < count && needsToDrawRect == NO; i++) {
|
|
needsToDrawRect = NSIntersectsRect(rect, rects[i]);
|
|
}
|
|
}
|
|
}
|
|
return needsToDrawRect;
|
|
}
|
|
|
|
- (void) getRectsBeingDrawn: (const NSRect **) rects
|
|
count: (NSInteger *) count
|
|
{
|
|
// This method returns all the rects being drawn concerning the view
|
|
// That's all of the dirty rects from the view, but also all the ones
|
|
// from the superview that might have caused the redraw.
|
|
// Since invalidating a rect also invalidates the first opaque superview,
|
|
// only the opaque views need to be checked
|
|
*rects = _rectsBeingRedrawn;
|
|
*count = _rectsBeingRedrawnCount;
|
|
|
|
if (_rectsBeingRedrawn == NULL) {
|
|
NSView *opaqueAncestor = [self opaqueAncestor];
|
|
if (opaqueAncestor != self) {
|
|
// Ask our opaque ancestor what to draw
|
|
const NSRect *ancestorRects;
|
|
[opaqueAncestor getRectsBeingDrawn: &ancestorRects
|
|
count: &_rectsBeingRedrawnCount];
|
|
if (_rectsBeingRedrawnCount) {
|
|
_rectsBeingRedrawn = NSZoneCalloc(NULL, _rectsBeingRedrawnCount,
|
|
sizeof(NSRect));
|
|
int rectsCount = 0;
|
|
for (int i = 0; i < _rectsBeingRedrawnCount; ++i) {
|
|
NSRect r = [opaqueAncestor convertRect: ancestorRects[i]
|
|
toView: self];
|
|
// No need for the rects that are outside of the visibleRect
|
|
if (NSIntersectsRect(r, _visibleRect)) {
|
|
_rectsBeingRedrawn[rectsCount++] = r;
|
|
}
|
|
}
|
|
*rects = _rectsBeingRedrawn;
|
|
*count = rectsCount;
|
|
}
|
|
} else {
|
|
// We're opaque - concatenate our invalid rect with the one from the
|
|
// previous opaque view
|
|
NSView *view = [self superview];
|
|
if (view) {
|
|
NSView *opaqueAncestor = [view opaqueAncestor];
|
|
const NSRect *ancestorRects;
|
|
NSInteger ancestorRectsCount;
|
|
[opaqueAncestor getRectsBeingDrawn: &ancestorRects
|
|
count: &ancestorRectsCount];
|
|
if (ancestorRectsCount || _invalidRectCount) {
|
|
_rectsBeingRedrawn = NSZoneCalloc(
|
|
NULL, _invalidRectCount + ancestorRectsCount,
|
|
sizeof(NSRect));
|
|
NSInteger rectsCount = 0;
|
|
for (int i = 0; i < ancestorRectsCount; ++i) {
|
|
NSRect r = [opaqueAncestor convertRect: ancestorRects[i]
|
|
toView: self];
|
|
// No need for the rects that are outside of the
|
|
// visibleRect
|
|
if (NSIntersectsRect(r, _visibleRect)) {
|
|
_rectsBeingRedrawn[rectsCount++] = r;
|
|
}
|
|
}
|
|
for (int i = 0; i < _invalidRectCount; ++i) {
|
|
_rectsBeingRedrawn[rectsCount++] = _invalidRects[i];
|
|
}
|
|
_rectsBeingRedrawnCount = rectsCount;
|
|
*rects = _rectsBeingRedrawn;
|
|
*count = _rectsBeingRedrawnCount;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// We had no info and no opaque ancestor gave us any useful rect - just use
|
|
// our invalid rects
|
|
if (*rects == NULL) {
|
|
if (_invalidRects == NULL) {
|
|
if (_needsDisplay) {
|
|
*rects = &_visibleRect;
|
|
*count = 1;
|
|
}
|
|
} else {
|
|
*rects = _invalidRects;
|
|
*count = _invalidRectCount;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (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]];
|
|
}
|
|
|
|
- (NSEnumerator *) _subviewsInDisplayOrderEnumerator {
|
|
// Subviews are ordered back to front -
|
|
return [_subviews objectEnumerator];
|
|
}
|
|
|
|
- (void) _displayIfNeededWithoutViewWillDraw {
|
|
if ([self needsDisplay]) {
|
|
[self displayRect: unionOfInvalidRects(self)];
|
|
clearNeedsDisplay(self);
|
|
}
|
|
|
|
NSEnumerator *viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
|
|
|
|
NSView *subView = nil;
|
|
while ((subView = [viewEnumerator nextObject])) {
|
|
[subView _displayIfNeededWithoutViewWillDraw];
|
|
}
|
|
}
|
|
|
|
- (void) displayIfNeeded {
|
|
[self viewWillDraw];
|
|
[self _displayIfNeededWithoutViewWillDraw];
|
|
}
|
|
|
|
- (void) displayIfNeededInRect: (NSRect) rect {
|
|
|
|
rect = NSIntersectionRect(unionOfInvalidRects(self), rect);
|
|
|
|
if ([self needsDisplay])
|
|
[self displayRect: rect];
|
|
|
|
NSEnumerator *viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
|
|
|
|
NSView *child = nil;
|
|
while ((child = [viewEnumerator nextObject])) {
|
|
NSRect converted = NSIntersectionRect(
|
|
[self convertRect: rect toView: child], [child bounds]);
|
|
if (!NSIsEmptyRect(converted)) {
|
|
[child displayIfNeededInRect: converted];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) displayIfNeededInRectIgnoringOpacity: (NSRect) rect {
|
|
|
|
rect = NSIntersectionRect(unionOfInvalidRects(self), rect);
|
|
|
|
if ([self needsDisplay])
|
|
[self displayRectIgnoringOpacity: rect];
|
|
|
|
NSEnumerator *viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
|
|
|
|
NSView *child = nil;
|
|
while ((child = [viewEnumerator nextObject])) {
|
|
NSRect converted = NSIntersectionRect(
|
|
[self convertRect: rect toView: child], [child bounds]);
|
|
|
|
if (!NSIsEmptyRect(converted)) {
|
|
[child displayIfNeededInRectIgnoringOpacity: converted];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) displayIfNeededIgnoringOpacity {
|
|
|
|
if ([self needsDisplay])
|
|
[self displayRectIgnoringOpacity: unionOfInvalidRects(self)];
|
|
|
|
NSEnumerator *viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
|
|
|
|
NSView *child = nil;
|
|
while ((child = [viewEnumerator nextObject])) {
|
|
[child displayIfNeededIgnoringOpacity];
|
|
}
|
|
}
|
|
|
|
- (void) displayRect: (NSRect) rect {
|
|
NSView *opaque = [self opaqueAncestor];
|
|
|
|
if (opaque != self)
|
|
rect = [self convertRect: rect toView: opaque];
|
|
[opaque displayRectIgnoringOpacity: rect];
|
|
}
|
|
|
|
- (void) displayRectIgnoringOpacity: (NSRect) rect {
|
|
NSRect visibleRect = [self visibleRect];
|
|
|
|
rect = NSIntersectionRect(rect, visibleRect);
|
|
|
|
if (NSIsEmptyRect(rect))
|
|
return;
|
|
|
|
BOOL shouldFlush = NO;
|
|
|
|
if ([self canDraw]) {
|
|
// This view must be locked/unlocked prior to drawing subviews otherwise
|
|
// gState changes may affect subviews.
|
|
[self lockFocus];
|
|
|
|
NSGraphicsContext *context = [NSGraphicsContext currentContext];
|
|
CGContextRef graphicsPort = [context graphicsPort];
|
|
|
|
shouldFlush = [context isDrawingToScreen];
|
|
|
|
CGContextClipToRect(graphicsPort, rect);
|
|
|
|
const NSRect *rects;
|
|
NSInteger rectsCount;
|
|
[self getRectsBeingDrawn: &rects count: &rectsCount];
|
|
// If there is only one rect, it's the visible rect - it's already
|
|
// clipped
|
|
if (rectsCount > 1)
|
|
CGContextClipToRects(graphicsPort, rects, rectsCount);
|
|
|
|
// [_window dirtyRect:[self convertRect:rect toView:nil]];
|
|
if ([NSGraphicsContext inQuartzDebugMode]) {
|
|
[[NSColor yellowColor] set];
|
|
NSRectFill(rect);
|
|
} else {
|
|
[self drawRect: rect];
|
|
if (NSShowAllViews) {
|
|
[[self _borderColorForNSShowAllViews] set];
|
|
NSFrameRect(rect);
|
|
}
|
|
}
|
|
|
|
[self unlockFocus];
|
|
|
|
NSEnumerator *viewEnumerator = [self _subviewsInDisplayOrderEnumerator];
|
|
|
|
NSView *child = nil;
|
|
while ((child = [viewEnumerator nextObject])) {
|
|
NSRect check = [self convertRect: rect toView: child];
|
|
|
|
check = NSIntersectionRect(check, [child bounds]);
|
|
|
|
if (!NSIsEmptyRect(check))
|
|
[child displayRectIgnoringOpacity: check];
|
|
}
|
|
}
|
|
|
|
[_layerContext render];
|
|
|
|
// Don't do anything to interfere with what will be drawn in non-debug mode
|
|
if ([NSGraphicsContext inQuartzDebugMode] == NO) {
|
|
removeRectFromInvalidInVisibleRect(self, rect, visibleRect);
|
|
|
|
// Rects being drawn are only valid while we redraw
|
|
clearRectsBeingRedrawn(self);
|
|
}
|
|
|
|
if (shouldFlush) {
|
|
// We do the flushWindow here. If any of the display* methods are being
|
|
// used, you want it to update on screen immediately. If the view
|
|
// hierarchy is being displayed as needed at the end of an event,
|
|
// flushing will be disabled and this will just mark the window as
|
|
// needing flushing which will happen when all the views have finished
|
|
// being displayed
|
|
[[self window] flushWindow];
|
|
}
|
|
}
|
|
|
|
- (void) displayRectIgnoringOpacity: (NSRect) rect
|
|
inContext: (NSGraphicsContext *) context
|
|
{
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) drawRect: (NSRect) rect {
|
|
// do nothing
|
|
}
|
|
|
|
- (BOOL) autoscroll: (NSEvent *) event {
|
|
return [[self superview] autoscroll: event];
|
|
}
|
|
|
|
- (void) scrollRect: (NSRect) rect by: (NSSize) delta {
|
|
NSPoint point = rect.origin;
|
|
|
|
point.x += delta.width;
|
|
point.y += delta.height;
|
|
|
|
if ([self lockFocusIfCanDraw]) {
|
|
NSCopyBits([self gState], rect, point);
|
|
[self unlockFocus];
|
|
}
|
|
}
|
|
|
|
- (BOOL) mouseDownCanMoveWindow {
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (void) print: sender {
|
|
[[NSPrintOperation printOperationWithView: self] runOperation];
|
|
}
|
|
|
|
- (void) beginDocument {
|
|
viewBeingPrinted = self;
|
|
}
|
|
|
|
- (void) endDocument {
|
|
viewBeingPrinted = nil;
|
|
}
|
|
|
|
- (void) beginPageInRect: (NSRect) rect atPlacement: (NSPoint) placement {
|
|
CGContextRef graphicsPort = NSCurrentGraphicsPort();
|
|
CGRect mediaBox = NSMakeRect(0, 0, rect.size.width, rect.size.height);
|
|
NSPrintInfo *printInfo = [[NSPrintOperation currentOperation] printInfo];
|
|
NSRect imageableRect = [printInfo imageablePageBounds];
|
|
CGAffineTransform transform = CGAffineTransformIdentity;
|
|
|
|
[NSCurrentFocusStack() addObject: self];
|
|
|
|
CGContextBeginPage(graphicsPort, &mediaBox);
|
|
CGContextSaveGState(graphicsPort);
|
|
|
|
transform = CGAffineTransformIdentity;
|
|
if ([self isFlipped]) {
|
|
transform = CGAffineTransformMake(1, 0, 0, -1, 0,
|
|
[printInfo paperSize].height);
|
|
}
|
|
|
|
transform = CGAffineTransformTranslate(transform, -rect.origin.x,
|
|
-rect.origin.y);
|
|
|
|
CGContextConcatCTM(graphicsPort, transform);
|
|
|
|
[self setUpGState];
|
|
}
|
|
|
|
- (void) endPage {
|
|
CGContextRef graphicsPort = NSCurrentGraphicsPort();
|
|
|
|
CGContextRestoreGState(graphicsPort);
|
|
CGContextEndPage(graphicsPort);
|
|
[NSCurrentFocusStack() removeLastObject];
|
|
}
|
|
|
|
- (NSAttributedString *) pageHeader {
|
|
NSUnimplementedMethod();
|
|
return nil;
|
|
}
|
|
|
|
- (NSAttributedString *) pageFooter {
|
|
NSUnimplementedMethod();
|
|
return nil;
|
|
}
|
|
|
|
- (NSString *) printJobTitle {
|
|
NSUnimplementedMethod();
|
|
return nil;
|
|
}
|
|
|
|
- (void) drawSheetBorderWithSize: (NSSize) size {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (void) drawPageBorderWithSize: (NSSize) size {
|
|
NSUnimplementedMethod();
|
|
}
|
|
|
|
- (CGFloat) widthAdjustLimit {
|
|
return 0.5;
|
|
}
|
|
|
|
- (CGFloat) heightAdjustLimit {
|
|
return 0.5;
|
|
}
|
|
|
|
- (void) adjustPageWidthNew: (CGFloat *) adjusted
|
|
left: (CGFloat) left
|
|
right: (CGFloat) right
|
|
limit: (CGFloat) limit
|
|
{
|
|
// FIX, give subviews a chance
|
|
}
|
|
|
|
- (void) adjustPageHeightNew: (CGFloat *) adjust
|
|
top: (CGFloat) top
|
|
bottom: (CGFloat) bottom
|
|
limit: (CGFloat) limit
|
|
{
|
|
// FIX, give subviews a chance
|
|
}
|
|
|
|
- (BOOL) knowsPageRange: (NSRange *) range {
|
|
return NO;
|
|
}
|
|
|
|
- (NSPoint) locationOfPrintRect: (NSRect) rect {
|
|
return NSZeroPoint;
|
|
}
|
|
|
|
- (NSRect) rectForPage: (int) page {
|
|
return NSZeroRect;
|
|
}
|
|
|
|
- (NSData *) dataWithEPSInsideRect: (NSRect) rect {
|
|
NSMutableData *result = [NSMutableData data];
|
|
NSPrintOperation *operation =
|
|
[NSPrintOperation EPSOperationWithView: self
|
|
insideRect: rect
|
|
toData: result];
|
|
|
|
[operation runOperation];
|
|
|
|
return result;
|
|
}
|
|
|
|
- (NSData *) dataWithPDFInsideRect: (NSRect) rect {
|
|
NSMutableData *result = [NSMutableData data];
|
|
NSPrintOperation *operation =
|
|
[NSPrintOperation PDFOperationWithView: self
|
|
insideRect: rect
|
|
toData: result];
|
|
|
|
[operation runOperation];
|
|
|
|
return result;
|
|
}
|
|
|
|
- (void) writeEPSInsideRect: (NSRect) rect
|
|
toPasteboard: (NSPasteboard *) pasteboard
|
|
{
|
|
NSData *data = [self dataWithEPSInsideRect: rect];
|
|
|
|
[pasteboard declareTypes: [NSArray arrayWithObject: NSPostScriptPboardType]
|
|
owner: nil];
|
|
[pasteboard setData: data forType: NSPostScriptPboardType];
|
|
}
|
|
|
|
- (void) writePDFInsideRect: (NSRect) rect
|
|
toPasteboard: (NSPasteboard *) pasteboard
|
|
{
|
|
NSData *data = [self dataWithPDFInsideRect: rect];
|
|
|
|
[pasteboard declareTypes: [NSArray arrayWithObject: NSPDFPboardType]
|
|
owner: nil];
|
|
[pasteboard setData: data forType: NSPDFPboardType];
|
|
}
|
|
|
|
- (void) dragImage: (NSImage *) image
|
|
at: (NSPoint) location
|
|
offset: (NSSize) offset
|
|
event: (NSEvent *) event
|
|
pasteboard: (NSPasteboard *) pasteboard
|
|
source: source
|
|
slideBack: (BOOL) slideBack
|
|
{
|
|
location = [self convertPoint: location toView: nil];
|
|
[[NSDraggingManager draggingManager] dragImage: image
|
|
at: location
|
|
offset: offset
|
|
event: event
|
|
pasteboard: pasteboard
|
|
source: source
|
|
slideBack: slideBack];
|
|
}
|
|
|
|
- (BOOL) dragFile: (NSString *) path
|
|
fromRect: (NSRect) rect
|
|
slideBack: (BOOL) slideBack
|
|
event: (NSEvent *) event
|
|
{
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL) acceptsFirstResponder {
|
|
return NO;
|
|
}
|
|
|
|
- (void) scrollWheel: (NSEvent *) event {
|
|
NSScrollView *scrollView = [self enclosingScrollView];
|
|
|
|
if (scrollView == nil) {
|
|
/* If we can't handle it, pass up responder chain, yep, it does this. */
|
|
[super scrollWheel: event];
|
|
} else {
|
|
NSView *documentView = [scrollView documentView];
|
|
NSRect bounds = [documentView bounds];
|
|
NSRect visible = [documentView visibleRect];
|
|
CGFloat direction = [documentView isFlipped] ? -1 : 1;
|
|
|
|
visible.origin.x +=
|
|
[event deltaX] * [scrollView horizontalLineScroll] * 3;
|
|
visible.origin.y += [event deltaY] * direction *
|
|
[scrollView verticalLineScroll] * 3;
|
|
|
|
// Something equivalent to this should be in scrollRectToVisible:
|
|
if (visible.origin.y < bounds.origin.y)
|
|
visible.origin.y = bounds.origin.y;
|
|
if (visible.origin.x < bounds.origin.x)
|
|
visible.origin.x = bounds.origin.x;
|
|
if (NSMaxY(visible) > NSMaxY(bounds))
|
|
visible.origin.y = NSMaxY(bounds) - visible.size.height;
|
|
if (NSMaxX(visible) > NSMaxX(bounds))
|
|
visible.origin.x = NSMaxX(bounds) - visible.size.width;
|
|
|
|
[documentView scrollRectToVisible: visible];
|
|
}
|
|
}
|
|
|
|
- (BOOL) performKeyEquivalent: (NSEvent *) event {
|
|
int i, count = [_subviews count];
|
|
|
|
for (i = 0; i < count; i++) {
|
|
NSView *check = [_subviews objectAtIndex: i];
|
|
|
|
if ([check performKeyEquivalent: event])
|
|
return YES;
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL) performMnemonic: (NSString *) string {
|
|
NSUnimplementedMethod();
|
|
return NO;
|
|
}
|
|
|
|
- (void) setMenu: (NSMenu *) menu {
|
|
menu = [menu retain];
|
|
[_menu release];
|
|
_menu = menu;
|
|
}
|
|
|
|
- (void) rightMouseDown: (NSEvent *) event {
|
|
[NSMenu popUpContextMenu: [self menuForEvent: event]
|
|
withEvent: event
|
|
forView: self];
|
|
}
|
|
|
|
// default NSDraggingDestination
|
|
- (NSDragOperation) draggingEntered: (id<NSDraggingInfo>) sender {
|
|
return NSDragOperationNone;
|
|
}
|
|
|
|
- (NSDragOperation) draggingUpdated: (id<NSDraggingInfo>) sender {
|
|
return [sender draggingSourceOperationMask];
|
|
}
|
|
|
|
- (void) draggingExited: (id<NSDraggingInfo>) sender {
|
|
// do nothing
|
|
}
|
|
|
|
- (BOOL) prepareForDragOperation: (id<NSDraggingInfo>) sender {
|
|
return NO;
|
|
}
|
|
|
|
- (BOOL) performDragOperation: (id<NSDraggingInfo>) sender {
|
|
return NO;
|
|
}
|
|
|
|
- (void) concludeDragOperation: (id<NSDraggingInfo>) 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;
|
|
}
|
|
|
|
#ifdef __BLOCKS__
|
|
- (void) showDefinitionForAttributedString: (NSAttributedString *) string
|
|
range: (NSRange) range
|
|
options: (NSDictionary *) options
|
|
baselineOriginProvider:
|
|
(NSPoint (^)(NSRange adjustedRange)) originProvider
|
|
{
|
|
NSUnimplementedMethod();
|
|
}
|
|
#endif
|
|
|
|
- (NSString *) description {
|
|
return [NSString stringWithFormat: @"<%@[%p] frame: %@>", [self class],
|
|
self, NSStringFromRect(_frame)];
|
|
}
|
|
|
|
@end
|