2007年11月21日水曜日

PQMousing

I've reused this code in all the custom views I've written lately, and it usually just works by plugging it in, so I thought it warranted posting.

I used to hate writing all that awful mouse event code, and once I'd done it, mouseDown: would end up being this page long affair full of if's else's, and ugly key press masks. You know the story. This code reduces mouseDown: to one line of code:

[self dispatchCorrectMousingActionForEvent:event toObject:self];

This will then proceed to fire at your Object the following methods, and it's up to you which ones you want to implement.

- (void)mouseDraggingStarted:(NSEvent *)event;
- (void)doubleClick:(NSEvent *)event;
- (void)basicMouseDown:(NSEvent *)event;
- (void)shiftMouseUp:(NSEvent *)event;
- (void)shiftMouseDown:(NSEvent *)event;
- (void)willDrag:(NSEvent *)event;
- (void)basicMouseUp:(NSEvent *)event;

I could add others of course, but these have gotten me by so far. If you have any additions, email me or add them to the comments!

//
// PQMousing.h
//
// Created by Mathieu Tozer on 13/07/07.
//

#import Cocoa/Cocoa.h //put inside angled brackets!

@interface NSObject (PQMousing)

- (void)dispatchCorrectMousingActionForEvent:(NSEvent *)event toObject:(id)object;

- (void)mouseDraggingStarted:(NSEvent *)event;
- (void)doubleClick:(NSEvent *)event;
- (void)basicMouseDown:(NSEvent *)event;
- (void)shiftMouseUp:(NSEvent *)event;
- (void)shiftMouseDown:(NSEvent *)event;
- (void)willDrag:(NSEvent *)event;
- (void)basicMouseUp:(NSEvent *)event;

@end

//
// PQMousing.m
//
// Created by Mathieu Tozer on 13/07/07.
//

#import "PQMousing.h"

const NSTimeInterval kTimeToWaitForDrag = .1;
@implementation NSObject (PQMousing)

- (void)dispatchCorrectMousingActionForEvent:(NSEvent *)event toObject:(id)object
{
//have a look for double click actions
if ([event clickCount] == 2) {
if ([object respondsToSelector:@selector(doubleClick:)]) {
[object doubleClick:event];
return;
}
}

NSEvent *nextEvent;
BOOL extending = (([event modifierFlags] & NSShiftKeyMask) ? YES : NO);
if (extending) {
if ([object respondsToSelector:@selector(shiftMouseDown:)]) [object shiftMouseDown:event];
} else {
if ([object respondsToSelector:@selector(basicMouseDown:)]) [object basicMouseDown:event];
}

//now wait for a possible drag or for a release
while (nextEvent = [NSApp nextEventMatchingMask:(NSLeftMouseDraggedMask || NSLeftMouseUpMask) untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES]) {
if ([nextEvent type] == NSLeftMouseDragged) {
if ([object respondsToSelector:@selector(mouseDraggingStarted:)]) {
if ([object respondsToSelector:@selector(willDrag:)]) [object willDrag:event];
if ([object respondsToSelector:@selector(mouseDraggingStarted:)]) [object mouseDraggingStarted:event];
}
break;
} else if ([nextEvent type] == NSLeftMouseUp) {
if (extending) {
if ([object respondsToSelector:@selector(shiftMouseUp:)]) [object shiftMouseUp:event];
} else {
if ([object respondsToSelector:@selector(basicMouseUp:)]) [object basicMouseUp:event];
}
break;
}
}
}


//subclasses may implement these
- (void)mouseDraggingStarted:(NSEvent *)event
{

}
- (void)doubleClick:(NSEvent *)event
{

}
- (void)basicMouseDown:(NSEvent *)event
{

}
- (void)shiftMouseUp:(NSEvent *)event
{

}
- (void)shiftMouseDown:(NSEvent *)event
{

}
- (void)willDrag:(NSEvent *)event
{

}
- (void)basicMouseUp:(NSEvent *)event
{

}

@end

0 件のコメント: