Sunday, October 18, 2009

Dragging


This post and the next show a simple example of dragging in Cocoa. We make a single simple shape, and position it randomly within the view. This code makes use of the C functions srand() and random(), and I wrote a short function to encapsulate this: - (NSUInteger)randomIntInRange:(NSRange)r.

I noticed something unexpected. When I set the contentView of the window to be of class "MyView", its initWithFrame: method does not get called. This only happens if a put a custom view in the window. I don't know why.

In the code listing, I've tacked on the instance variables, for convenience. Some of these are only used next time.


#import "MyView.h"

@implementation MyView
@synthesize shape;

- (id)initWithFrame:(NSRect)frameRect {
NSLog(@"myView initWithFrame");
self = [super initWithFrame:frameRect];
if (nil == self) { return nil; }
srandom(time(0));
CL = [NSColorList
colorListNamed:@"Crayons"];
[CL retain];
[self setShape:[self makeShape]];
return self;
}

- (NSUInteger)randomIntInRange:(NSRange)r {
int j = r.location - 1;
do { j = random() % r.length; }
while (j < r.location);
return (NSUInteger) j;
}

- (NSPoint)
randomStartingPointShapeOfW:(NSUInteger)wd
h:(NSUInteger)ht {
x = [self randomIntInRange:
NSMakeRange(0,
[self bounds].size.width - wd)];
y = [self randomIntInRange:
NSMakeRange(0,
[self bounds].size.height - ht)];
return NSMakePoint(x,y);
}

- (NSBezierPath *)makeShape {
w = 100;
h = 100;
p = [self
randomStartingPointShapeOfW:w h:h];
return [NSBezierPath bezierPathWithOvalInRect:
NSMakeRect(p.x,p.y,w,h) ];
}

- (void)drawRect:(NSRect)rect{
c = [CL colorWithKey:@"Lemon"];
[c set];
NSRectFill([self bounds]);
c = [CL colorWithKey:@"Plum"];
[c set];
[shape fill];
}

@end

NSBezierPath *shape;

NSColor *c;
NSColorList *CL;
NSRect R;
NSRect bo;
NSRect bn;
NSPoint p;
NSPoint lastPoint;
NSAffineTransform *t;

NSUInteger i;
NSUInteger x;
NSUInteger y;
NSUInteger w;
NSUInteger h;
float dx;
float dy;

BOOL draggingInProgress;
BOOL didMove;