この「wall 'o コード」を、カスタム NSView 内で領域選択を行う (ほぼ) 完全な手段として提示し、その後、「行進アリ」の四角形を展開/移動する機能を備えています。
うまくいけば、そこにいる誰かがそれが役に立つと思う.
「introThumbRect」への最初の呼び出しでボールが転がります。長方形の辺は、マウス カーソルが適切に変化することで拡大できます。選択長方形も移動できます。初期/結果の四角形は、ビューの「thumbRect」プロパティにあります (「fullImage」座標系を基準にします)。「cropPt」値は、表示された画像「fullImage」の左上です。ここでは、(0,0) であると仮定します。
私が抱えている問題の 1 つは、マウスのドラッグが発生すると (つまり、辺が拡大されたり、四角形が移動されたりすると)、マウス カーソルを元のドラッグ状態に維持するために戦っているということです。矢印カーソルに戻したいのですが、たとえば、開いた手のカーソルとして維持する必要があります。これはトラッキング領域を再計算した結果だと思いますが、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