TrackView.m
/* |
File: TrackView.m |
Abstract: The NSView that handles the label color tracking. |
Version: 1.2 |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
Inc. ("Apple") in consideration of your agreement to the following |
terms, and your use, installation, modification or redistribution of |
this Apple software constitutes acceptance of these terms. If you do |
not agree with these terms, please do not use, install, modify or |
redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. may |
be used to endorse or promote products derived from the Apple Software |
without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or |
implied, are granted by Apple herein, including but not limited to any |
patent rights that may be infringed by your derivative works or by other |
works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
Copyright (C) 2012 Apple Inc. All Rights Reserved. |
*/ |
#import "TrackView.h" |
@implementation TrackView |
// key for dictionary in NSTrackingAreas's userInfo |
NSString* kTrackerKey = @"whichTracker"; |
// key values for dictionary in NSTrackingAreas's userInfo, |
// which tracking area is being tracked |
enum trackingAreaIDs |
{ |
kTrackingArea1 = 1, |
kTrackingArea2, |
kTrackingArea3, |
kTrackingArea4, |
kTrackingArea5, |
kTrackingArea6, |
kTrackingArea7, |
kTrackingArea8 |
}; |
// ------------------------------------------------------------------------------- |
// awakeFromNib: |
// |
// Setup the tracking areas for each colored dot. Each colored dot is a separate |
// NSView for easy management/tracking purposes. |
// ------------------------------------------------------------------------------- |
- (void)awakeFromNib |
{ |
[self setupTrackingAreas]; |
} |
// ------------------------------------------------------------------------------- |
// dealloc: |
// ------------------------------------------------------------------------------- |
- (void)dealloc |
{ |
[trackingAreas release]; |
[super dealloc]; |
} |
// ------------------------------------------------------------------------------- |
// setupTrackingAreas: |
// ------------------------------------------------------------------------------- |
- (void)setupTrackingAreas |
{ |
if (trackingAreas == nil) |
{ |
// load all the suviews and add tracking areas to them |
NSArray *viewsToFrame = [self subviews]; |
trackingAreas = [NSMutableArray array]; // keep all tracking areas in an array |
// determine the tracking options |
NSTrackingAreaOptions trackingOptions = NSTrackingEnabledDuringMouseDrag | |
NSTrackingMouseEnteredAndExited | |
NSTrackingActiveInActiveApp | |
NSTrackingActiveAlways; |
NSInteger numViews = [[self subviews] count]; |
NSInteger index; |
for (index = 1; index < numViews; index++) |
{ |
// make tracking data (to be stored in NSTrackingArea's userInfo) so we can later determine which tracking area is focused on |
// |
NSDictionary *trackerData = [NSDictionary dictionaryWithObjectsAndKeys: |
[NSNumber numberWithInt:index], kTrackerKey, nil]; |
NSTrackingArea *trackingArea = [[NSTrackingArea alloc] |
initWithRect:[[viewsToFrame objectAtIndex:index-1] frame] |
// note: since we are working with this view's coordinate system, |
// we need to use the 'frame' for each subview instead of its bounds |
options:trackingOptions |
owner:self |
userInfo:trackerData]; |
[trackingAreas addObject:trackingArea]; // keep track of this tracking area for later disposal |
[self addTrackingArea:trackingArea]; // add the tracking area to the view/window |
[trackingArea release]; |
} |
} |
} |
// ------------------------------------------------------------------------------- |
// drawRect:rect |
// |
// Returns the NSColor corresponding to the sub-view index. |
// ------------------------------------------------------------------------------- |
- (NSColor *)colorForViewIndex:(NSInteger)viewIndex |
{ |
NSColor *returnColor = nil; |
switch (viewIndex) |
{ |
case kTrackingArea1: // grey |
returnColor = [NSColor grayColor]; |
break; |
case kTrackingArea2: // purple |
returnColor = [NSColor purpleColor]; |
break; |
case kTrackingArea3: // blue |
returnColor = [NSColor blueColor]; |
break; |
case kTrackingArea4: // green |
returnColor = [NSColor greenColor]; |
break; |
case kTrackingArea5: // yellow |
returnColor = [NSColor yellowColor]; |
break; |
case kTrackingArea6: // orange |
returnColor = [NSColor orangeColor]; |
break; |
case kTrackingArea7: // red |
returnColor = [NSColor redColor]; |
break; |
case kTrackingArea8: // none (black) |
returnColor = [NSColor blackColor]; |
break; |
} |
return returnColor; |
} |
// ------------------------------------------------------------------------------- |
// drawRect:rect |
// |
// Examine all the sub-view colored dots and color them with their appropriate colors. |
// ------------------------------------------------------------------------------- |
- (void)drawRect:(NSRect)rect |
{ |
NSArray *viewsToFrame = [self subviews]; |
NSInteger viewCount = [viewsToFrame count] - 1; |
NSInteger index; |
for (index = 1; index <= viewCount; index++) |
{ |
if (whichTrackedID == index) |
{ |
// obtain the bezier path (a filled circle) to draw in |
NSBezierPath *theFill = [NSBezierPath bezierPathWithOvalInRect:[[viewsToFrame objectAtIndex:whichTrackedID - 1] frame]]; |
NSColor *theColor = [self colorForViewIndex:whichTrackedID]; |
if (trackEntered) |
{ |
// if we are tracking inside any label, we want to brighten the color to show selection feedback |
// take the current label color and brighten it |
CGFloat hue, saturation, brightness, alpha; |
[[theColor |
colorUsingColorSpaceName:NSDeviceRGBColorSpace] getHue:&hue |
saturation:&saturation brightness:&brightness alpha:&alpha]; |
theColor = [NSColor colorWithDeviceHue:hue saturation:saturation-.60 brightness:brightness + 40.0 alpha:alpha]; |
} |
// finally, render the color change (light or dark) |
[self lockFocus]; |
[theColor set]; |
[theFill fill]; |
[self unlockFocus]; |
} |
else |
{ |
// obtain the bezier path (a filled circle) to draw in |
NSBezierPath *theFill = [NSBezierPath bezierPathWithOvalInRect:[[viewsToFrame objectAtIndex:index-1] frame]]; |
// fill the area with the appropriate color |
[[self colorForViewIndex:index] set]; |
[theFill fill]; |
} |
} |
} |
// ------------------------------------------------------------------------------- |
// getTrackerIDFromDict:dict |
// |
// Used in obtaining dictionary entry info from the 'userData', used by each |
// mouse event method. It helps determine which tracking area is being tracked. |
// ------------------------------------------------------------------------------- |
- (int)getTrackerIDFromDict:(NSDictionary *)dict |
{ |
id whichTracker = [dict objectForKey: kTrackerKey]; |
return [whichTracker intValue]; |
} |
// ------------------------------------------------------------------------------- |
// mouseEntered:event |
// |
// Because we installed NSTrackingArea to our NSImageView, this method will be called. |
// ------------------------------------------------------------------------------- |
- (void)mouseEntered:(NSEvent *)event |
{ |
// which tracking area is being tracked? |
whichTrackedID = [self getTrackerIDFromDict:[event userData]]; |
trackEntered = YES; |
[self setNeedsDisplay:YES]; // force update the currently tracked label back to its original color |
} |
// ------------------------------------------------------------------------------- |
// mouseExited:event |
// |
// Because we installed NSTrackingArea to our NSImageView, this method will be called. |
// ------------------------------------------------------------------------------- |
- (void)mouseExited:(NSEvent *)event |
{ |
// which tracking area is being tracked? |
whichTrackedID = [self getTrackerIDFromDict:[event userData]]; |
trackEntered = NO; |
[self setNeedsDisplay:YES]; // force update the currently tracked label to a lighter color |
} |
// ------------------------------------------------------------------------------- |
// mouseDown:event |
// ------------------------------------------------------------------------------- |
- (void)mouseUp:(NSEvent*)event |
{ |
NSPoint mousePoint = [self convertPoint: [event locationInWindow] fromView:nil]; |
// figure out which label color was clicked on at mouseUp time |
NSArray *labelViews = [self subviews]; |
NSInteger numViews = [labelViews count]; |
NSInteger index; |
for (index = 1; index < numViews; index++) |
{ |
NSRect labelRect = [[labelViews objectAtIndex:index-1] frame]; |
if (NSPointInRect(mousePoint, labelRect)) |
{ |
// here you would respond to the particular label selection... |
NSLog(@"label %d was selected", (int)index); |
} |
} |
// on mouse up, we want to dismiss the menu being tracked |
NSMenu *menu = [[self enclosingMenuItem] menu]; |
[menu cancelTracking]; |
// we are no longer tracking, reset the tracked label color (if any) |
whichTrackedID = NSNotFound; |
[self setNeedsDisplay:YES]; |
} |
@end |
© 2012 Apple Inc. All Rights Reserved. (Last updated: 2012-06-07)