Re: Bezier folies
Re: Bezier folies
- Subject: Re: Bezier folies
- From: Tom Waters <email@hidden>
- Date: Thu, 29 Nov 2001 09:37:46 -0800
I think an even better design would be to create an informal dataSource
protocol for your view, a la NSTableView...
Here's the example I did for Riccardo last time, extended to have a
controller class acting as the view's datasource.
I'll leave the IB connecting as an exercise to the reader. (there's a
button which is connected to the Controller's randomizePoints: action)
// MyView.h
#import <Cocoa/Cocoa.h>
@interface NSObject (MyViewDataSource)
- (NSPoint)pointAtIndex:(int)i;
- (void)setPoint:(NSPoint)p atIndex:(int)i;
- (int)pointAtPoint:(NSPoint)p;
@end
@interface MyView : NSView
{
id dataSource;
}
@end
// MyView.m
#import "MyView.h"
@implementation MyView
- (void)drawRect:(NSRect)rect
{
NSPoint p0 = [dataSource pointAtIndex:0];
NSPoint p1 = [dataSource pointAtIndex:1];
NSPoint p2 = [dataSource pointAtIndex:2];
NSPoint p3 = [dataSource pointAtIndex:3];
NSBezierPath *curve = [NSBezierPath bezierPath];
[[NSColor blackColor] set];
[curve moveToPoint:p0];
[curve lineToPoint:p1];
[curve lineToPoint:p2];
[curve lineToPoint:p3];
[curve stroke];
[curve removeAllPoints];
[[NSColor redColor] set];
[curve moveToPoint:p0];
[curve curveToPoint:p3 controlPoint1:p1 controlPoint2:p2];
[curve stroke];
}
- (void)mouseDown:(NSEvent *)theEvent
{
NSPoint p = [self convertPoint: [theEvent locationInWindow]
fromView: nil];
int point = [dataSource pointAtPoint:p];
if (point > -1) {
do {
theEvent = [[self window]
nextEventMatchingMask:NSLeftMouseDraggedMask | NSLeftMouseUpMask];
p = [self convertPoint:[theEvent locationInWindow] fromView:nil];
[dataSource setPoint:p atIndex:point];
[self setNeedsDisplayInRect:[self bounds]];
} while ([theEvent type] == NSLeftMouseDragged);
}
}
@end
// Controller.h
#import <Cocoa/Cocoa.h>
#define NUMPOINTS 4
#define HITDIST 8
@interface Controller : NSObject
{
IBOutlet id view;
IBOutlet id window;
NSPoint points[NUMPOINTS];
}
- (NSPoint)pointAtIndex:(int)i;
- (void)setPoint:(NSPoint)p atIndex:(int)i;
- (int)pointAtPoint:(NSPoint)p;
- (IBAction)randomizePoints:(id)sender;
@end
// Controller.m
#import "Controller.h"
@implementation Controller
- (void)awakeFromNib
{
[self randomizePoints:self];
}
- (NSPoint)pointAtIndex:(int)i
{
return points[i];
}
- (void)setPoint:(NSPoint)p atIndex:(int)i
{
points[i] = p;
}
- (int)pointAtPoint:(NSPoint)p
{
int n = NUMPOINTS;
int i;
for (i = 0; i < n; i++) {
float dx = p.x - points[i].x;
float dy = p.y - points[i].y;
float dist = sqrt(dx*dx + dy*dy);
if (dist < HITDIST)
return i;
}
return -1;
}
- (IBAction)randomizePoints:(id)sender
{
NSRect bounds = [view bounds];
int i;
for (i = 0; i < NUMPOINTS; i++) {
points[i].x = bounds.size.width * random() / 0x7fffffff;
points[i].y = bounds.size.height * random() / 0x7fffffff;
}
[view setNeedsDisplay:YES];
}
@end
On Thursday, November 29, 2001, at 08:54 AM, email@hidden wrote:
Hi everybody,
Do you remember I was toying around the NSBezierPath class ? Well, I've
decided to go a little step further and I'm now trying to implement a
little GUI. The main goal is : "I press a button and then a random
curve
is generated".
Here are the step I've done so far:
1) I've created 2 interfaces: a NSView subclass and another
"controller"
istantiated class for the gui...
2) ... I've #imported the NSView class inside the other...
3) ... I've made my NSPoints in the NSView class as @public ...
4) I try to access the points from the main class but it tells me it's
"undeclared" ?!?
How can it be possible ? How can I make a class gain variables and
values
from a "brother" one ?!?
Better design would require that you define the variables as @private
and then create accessor methods to access them/change them. That way
you can use the standard [object_name method_name] syntax to access
them.
If you want to learn more about accessor methods you may want to take a
look at Recipe 1 of "Vermont Recipes" which is located at
http://www.stepwise.com/Articles/VermontRecipes/