NSView中的行动蚂蚁与NSTrackingArea

时间:2014-01-14 15:24:36

标签: nsview nstrackingarea marching-ants

我将这个“墙上代码”作为(大部分)完整的方法在自定义NSView中进行区域选择,并随后展开/移动“行进蚂蚁”矩形。

希望有人认为它有用。

enter image description here

对“introThumbRect”的初始调用让球滚动。可以扩展矩形的边,鼠标光标可以适当改变。选择矩形也可以移动。初始/结果矩形位于视图的“thumbRect”属性中(相对于“fullImage”坐标系)。 “cropPt”值是显示图像“fullImage”的左上角;出于这里的目的,假设它是(0,0)。

我遇到的一个问题是,一旦发生鼠标拖动(即正在展开两侧或正在移动矩形),我正在与鼠标光标对抗以保持它这是原始的拖拽状态。它想要恢复到箭头光标,而它应该保持自己,例如,一个开放的手形光标。我相信这是因为重新计算跟踪区域而发生的,但是这样的问题几乎不可能调试,因为XCode没有“跟踪”光标状态。

如果有人可以协助修复那个小错误,那就太好了。

#import <Cocoa/Cocoa.h>

@interface ThumbNailView : NSView

@property (nonatomic, strong) NSImage *fullImage;
@property (nonatomic) CGPoint cropPt;
@property (nonatomic) CGRect thumbRect;

- (void)introThumbRect;

@end

@implementation ThumbNailView
{
    NSMutableArray *trackingAreas;

    NSCursor *dragCursor;
    NSTimer *antTimer;
    NSInteger antPhase;

    NSString *dragMode;

    CGRect origThumbRect;

    CGPoint thumbPt;
    CGPoint mouseLoc;

    BOOL thumbVisible;
    BOOL updatedTracking;
    BOOL amDragging;
}

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
        [self setThumbRect:CGRectZero];
    return self;
}

-(BOOL) isFlipped
{
    return YES;
}

- (void)setupTrackingOnRect:(CGRect)r
{

    CGRect trackRects[5];

    int d=5;
    // these are tracking rectangles for the interior + 4 sides of the rectangle
    trackRects[0] = CGRectMake(r.origin.x+d,r.origin.y+d,
                               r.size.width-d*2,r.size.height-d*2);   // main interior
    trackRects[1] = CGRectMake(r.origin.x-d,r.origin.y+d,
                               d*2,r.size.height-d*2);  // left side
    trackRects[2] = CGRectMake(r.origin.x+r.size.width-d,r.origin.y+d,
                               d*2,r.size.height-d*2);  // right side
    trackRects[3] = CGRectMake(r.origin.x+d,r.origin.y-d,
                               r.size.width-d*2,d*2);   // top side
    trackRects[4] = CGRectMake(r.origin.x+d,r.origin.y+r.size.height-d,
                               r.size.width-d*2,d*2);   // bottom inside

    NSMutableArray *dicts = [[NSMutableArray alloc] init];
    [dicts addObject:[[NSDictionary alloc] initWithObjectsAndKeys:
                      NSStringFromRect(CGRectMake(1,1,0,0)),@"moveMode",
                      [NSCursor openHandCursor],       @"cursor",nil]];
    [dicts addObject:[[NSDictionary alloc] initWithObjectsAndKeys:
                      NSStringFromRect(CGRectMake(1,0,-1,0)),@"moveMode",
                      [NSCursor resizeLeftRightCursor],@"cursor",nil]];
    [dicts addObject:[[NSDictionary alloc] initWithObjectsAndKeys:
                      NSStringFromRect(CGRectMake(0,0,1,0)),@"moveMode",
                      [NSCursor resizeLeftRightCursor],@"cursor",nil]];
    [dicts addObject:[[NSDictionary alloc] initWithObjectsAndKeys:
                      NSStringFromRect(CGRectMake(0,1,0,-1)),@"moveMode",
                      [NSCursor resizeUpDownCursor],   @"cursor",nil]];
    [dicts addObject:[[NSDictionary alloc] initWithObjectsAndKeys:
                      NSStringFromRect(CGRectMake(0,0,0,1)),@"moveMode",
                      [NSCursor resizeUpDownCursor],   @"cursor",nil]];


    NSTrackingAreaOptions myOptions = NSTrackingMouseEnteredAndExited |
                                      NSTrackingMouseMoved;

    NSMutableArray *tracks = [[NSMutableArray alloc] init];
    for (int i=0; i<5; i++)  {
        NSDictionary *dict = [dicts objectAtIndex:i];
        [tracks addObject:[[NSTrackingArea alloc] initWithRect:trackRects[i]
                                                       options:myOptions | NSTrackingActiveInKeyWindow
                                                         owner:self
                                                      userInfo:dict]];
        [self addTrackingArea:[tracks objectAtIndex:i]];
    }

    trackingAreas=tracks;
}

- (void)updateTrackingAreas
{
    if (dragCursor)
        [dragCursor set];

    [super updateTrackingAreas];

    if (dragCursor)
        [dragCursor set];

    for (NSTrackingArea *t in [self trackingAreas])
        [self removeTrackingArea:t];
    trackingAreas=nil;

    if (thumbVisible) {
        CGRect tRect = CGRectOffset([self thumbRect],
                                    thumbPt.x-[self cropPt].x,
                                    thumbPt.y-[self cropPt].y);
        [self setupTrackingOnRect:tRect];
    }
}

- (void)mouseEntered:(NSEvent *)theEvent
{
    if (amDragging)
        return;

    NSDictionary *userDict = [theEvent userData];
    if (userDict) {
        NSCursor *newCursor = [userDict objectForKey:@"cursor"];
        if (newCursor) {
            [newCursor set];
            dragCursor=newCursor;
        }
        NSString *newMode = [userDict objectForKey:@"moveMode"];
        if (newMode)
            dragMode=newMode;
    }
}

- (void)mouseExited:(NSEvent *)theEvent
{
    if (!amDragging) {
        [[NSCursor arrowCursor] set];
        dragMode=nil;
        dragCursor=nil;
    }
}

- (void)mouseDragged:(NSEvent *)theEvent
{
    if (dragMode) {
        amDragging=YES;
        if (dragCursor)
            [dragCursor set];

        CGPoint newLoc = [NSEvent mouseLocation];
        NSInteger deltaX = mouseLoc.x - newLoc.x;
        NSInteger deltaY = mouseLoc.y - newLoc.y;

        CGRect moveMode = NSRectFromString(dragMode);
        CGRect trect = CGRectOffset(origThumbRect,-moveMode.origin.x*deltaX,moveMode.origin.y*deltaY);
        trect.size.width -= moveMode.size.width*deltaX;
        trect.size.height += moveMode.size.height*deltaY;

        [self setThumbRect:trect];
        updatedTracking=NO;
        [self setNeedsDisplay:YES];
    }
}

- (void)mouseMoved:(NSEvent *)theEvent
{
    if (dragCursor)
        [dragCursor set];
}

- (void)mouseDown:(NSEvent *)theEvent
{
    mouseLoc=[NSEvent mouseLocation];
    origThumbRect = [self thumbRect];
}

- (void)mouseUp:(NSEvent *)theEvent
{
    amDragging=NO;
    dragCursor=nil;
    [self setNeedsDisplay:YES];
}

- (void)introThumbRect
{
    NSInteger h = [self frame].size.height;
    if (!h)
        return;
    CGRect thumbRect = CGRectMake(0,0,140.0*h/64.0,h);
    thumbPt = [self cropPt];
    [self setThumbRect:thumbRect];
    [self setNeedsDisplay:YES];
}

- (void) antMarch:(NSTimer *)timer
{
    antPhase = (antPhase+1)%7;
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)dirtyRect
{
    [super drawRect:dirtyRect];

    // Drawing code here.
    [[NSColor greenColor] set];
    [NSBezierPath fillRect:dirtyRect];

    CGRect cropRect = CGRectMake([self cropPt].x,
                                 [self cropPt].y,
                                 [self frame].size.width,
                                 [self frame].size.height);

    CGRect myRect = CGRectMake(0,0,cropRect.size.width,cropRect.size.height);
    [[self fullImage] drawInRect:myRect
                        fromRect:cropRect
                       operation:NSCompositeCopy
                        fraction:1.0
                  respectFlipped:YES
                           hints:nil];

    if (CGRectEqualToRect(CGRectZero,[self thumbRect]))
        return;

    CGRect tRect = CGRectOffset([self thumbRect],
                                thumbPt.x-[self cropPt].x,
                                thumbPt.y-[self cropPt].y);
    CGRect iRect = CGRectIntersection(myRect,tRect);
    if (CGRectIsNull(iRect)) {
        if (thumbVisible) {
            thumbVisible=NO;
            [self updateTrackingAreas];
        }
        if (antTimer) {
            [antTimer invalidate];
            antTimer=nil;
        }
        return;
    }

    thumbVisible=YES;
    [self drawThumbBox];
    if (!antTimer) {
        antTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
                                                    target:self
                                                  selector:@selector(antMarch:)
                                                  userInfo:nil
                                                   repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:antTimer forMode: NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] addTimer:antTimer forMode: NSEventTrackingRunLoopMode];
    }

    //if (![self inDrag])
    if (dragCursor)
        [dragCursor set];

    if (!updatedTracking) {
        updatedTracking=YES;
        [self updateTrackingAreas];
    }
}

- (void)drawThumbBox
{
    NSInteger deltaX = thumbPt.x-[self cropPt].x;
    NSInteger deltaY = thumbPt.y-[self cropPt].y;

    CGRect tRect = CGRectOffset([self thumbRect],deltaX,deltaY);

    NSCompositingOperation curComp = [[NSGraphicsContext currentContext] compositingOperation];
    [[NSGraphicsContext currentContext] setCompositingOperation:NSCompositeXOR];

    // draw marching ants
    [[NSColor blackColor] set];
    NSBezierPath *selectionPath = [NSBezierPath bezierPathWithRect:tRect];
    CGFloat dashArray[2] = {5.0, 2.0};
    [selectionPath setLineDash:dashArray
                         count:sizeof(dashArray)/sizeof(CGFloat)
                         phase:antPhase];
    [selectionPath stroke];

    [[NSGraphicsContext currentContext] setCompositingOperation:curComp];
}

@end

0 个答案:

没有答案