// // ZoomCursor.m // ZoomCocoa // // Created by Andrew Hunter on Fri Jun 25 2004. // Copyright (c) 2004 Andrew Hunter. All rights reserved. // #import "ZoomCursor.h" #define BlinkInterval 0.6 @implementation ZoomCursor // = Initialisation = - (id) init { self = [super init]; if (self) { isBlinking = NO; isShown = YES; isActive = YES; isFirst = YES; blink = YES; cursorRect = NSMakeRect(0,0,0,0); delegate = nil; flasher = nil; lastVisible = [self visible]; lastActive = [self activeStyle]; } return self; } - (void) dealloc { if (flasher) { [flasher invalidate]; [flasher release]; } [super dealloc]; } // = Delegate = - (id) delegate { return delegate; } - (void) setDelegate: (id) dg { delegate = dg; } // = Blinking = - (BOOL) visible { return (isShown&&(!isBlinking||blink)); } - (BOOL) activeStyle { return (isActive&&isFirst); } - (void) ZCblunk { // Cursor has, uh, blunked // Only send the message if our visibility has changed BOOL nowVisible = [self visible]; BOOL nowActive = [self activeStyle]; if (nowActive == lastActive && nowVisible == lastVisible) { return; } lastVisible = nowVisible; lastActive = nowActive; // Notify the delegate that we have blinked if ([delegate respondsToSelector: @selector(blinkCursor:)]) { [(NSObject*)delegate blinkCursor: self]; } } - (void) ZCblinky { if ([self activeStyle]) { blink = !blink; } else { blink = YES; } [self ZCblunk]; } // = Drawing = - (void) draw { if (![self visible]) return; // Cursor colour [[NSColor colorWithDeviceRed: 0.3 green: 0.8 blue: 1.0 alpha: 0.6] set]; // Draw the cursor if ([self activeStyle]) { [NSBezierPath strokeRect: cursorRect]; [NSBezierPath fillRect: cursorRect]; } else { [NSBezierPath strokeRect: cursorRect]; } } // = Positioning = - (void) positionAt: (NSPoint) pt withFont: (NSFont*) font { // Cause the delegate to undraw any previous cursor BOOL wasShown = isShown; isShown = NO; [self ZCblunk]; // Move the cursor float width = [font widthOfString: @"n"]; // One 'en' float height = [font defaultLineHeightForFont]; cursorRect = NSMakeRect(pt.x, pt.y, width, height); cursorRect.origin.x = floor(cursorRect.origin.x + 0.5) + 0.5; cursorRect.origin.y = floor(cursorRect.origin.y + 0.5) + 0.5; cursorRect.size.width = floor(cursorRect.size.width + 0.5); cursorRect.size.height = floor(cursorRect.size.height + 0.5); // Redraw isShown = wasShown; [self ZCblunk]; cursorPos = pt; } - (void) positionInString: (NSString*) string withAttributes: (NSDictionary*) attributes atCharacterIndex: (int) index { // Cause the delegate to undraw any previous cursor BOOL wasShown = isShown; isShown = NO; [self ZCblunk]; NSFont* font = [attributes objectForKey: NSFontAttributeName]; // Move the cursor float width = [font widthOfString: @"n"]; // One 'en' float height = [font defaultLineHeightForFont]; float offset = [[string substringToIndex: index] sizeWithAttributes: attributes].width; cursorRect = NSMakeRect(cursorPos.x+offset, cursorPos.y, width, height); // Redraw isShown = wasShown; blink = YES; [self ZCblunk]; } - (NSRect) cursorRect { return NSInsetRect(cursorRect, -2.0, -2.0); } // = Display status = - (void) setBlinking: (BOOL) blnk { if (blnk == isBlinking) return; isBlinking = blnk; if (blnk == NO) { blink = YES; [self ZCblunk]; if (flasher) { [flasher invalidate]; [flasher release]; flasher = nil; } } else { if (!flasher) { flasher = [NSTimer timerWithTimeInterval: BlinkInterval target: self selector: @selector(ZCblinky) userInfo: nil repeats: YES]; [[NSRunLoop currentRunLoop] addTimer: [flasher retain] forMode: NSDefaultRunLoopMode]; } } } - (void) setShown: (BOOL) shown { if (shown == isShown) return; isShown = shown; [self ZCblunk]; } - (void) setActive: (BOOL) active { if (active == isActive) return; isActive = active; if (!isActive) blink = YES; [self ZCblunk]; } - (void) setFirst: (BOOL) first { if (first == isFirst) return; isFirst = first; if (!isFirst) blink = YES; [self ZCblunk]; } @end