5 // Created by CiarĂ¡n Walsh on 23/09/2008.
6 // Copyright 2008 __MyCompanyName__. All rights reserved.
8 // Adopted from http://www.cocoadev.com/index.pl?NSTableViewImagesAndText
10 #import "PBIconAndTextCell.h"
13 @implementation PBIconAndTextCell
22 - (id)copyWithZone:(NSZone *)zone
24 PBIconAndTextCell *cell = [super copyWithZone:zone];
29 - (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength
31 NSRect textFrame, imageFrame;
32 NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
33 [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength];
36 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
42 imageSize = [image size];
43 NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge);
44 if ([self drawsBackground]) {
45 [[self backgroundColor] set];
46 NSRectFill(imageFrame);
48 imageFrame.origin.x += 3;
49 imageFrame.size = imageSize;
51 if ([controlView isFlipped])
52 imageFrame.origin.y += floor((cellFrame.size.height + imageFrame.size.height) / 2);
54 imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2);
56 [image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver];
58 [super drawWithFrame:cellFrame inView:controlView];
63 NSSize cellSize = [super cellSize];
64 cellSize.width += (image ? [image size].width : 0) + 3;
71 // Adopted from PhotoSearch Apple sample code
73 - (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView
75 NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
77 NSRect textFrame, imageFrame;
78 NSDivideRect (cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
79 if (NSMouseInRect(point, imageFrame, [controlView isFlipped]))
80 return NSCellHitContentArea | NSCellHitTrackableArea;
82 return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];
85 + (BOOL)prefersTrackingUntilMouseUp
87 // NSCell returns NO for this by default. If you want to have trackMouse:inRect:ofView:untilMouseUp: always track until the mouse is up, then you MUST return YES. Otherwise, strange things will happen.
91 - (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)flag
93 [self setControlView:controlView];
95 NSRect textFrame, imageFrame;
96 NSDivideRect (cellFrame, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
97 while ([theEvent type] != NSLeftMouseUp) {
98 // This is VERY simple event tracking. We simply check to see if the mouse is in the "i" button or not and dispatch entered/exited mouse events
99 NSPoint point = [controlView convertPoint:[theEvent locationInWindow] fromView:nil];
100 BOOL mouseInButton = NSMouseInRect(point, imageFrame, [controlView isFlipped]);
101 if (mouseDownInButton != mouseInButton) {
102 mouseDownInButton = mouseInButton;
103 [controlView setNeedsDisplayInRect:cellFrame];
105 if ([theEvent type] == NSMouseEntered || [theEvent type] == NSMouseExited)
106 [NSApp sendEvent:theEvent];
107 // Note that we process mouse entered and exited events and dispatch them to properly handle updates
108 theEvent = [[controlView window] nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask | NSMouseEnteredMask | NSMouseExitedMask)];
111 // Another way of implementing the above code would be to keep an NSButtonCell as an ivar, and simply call trackMouse:inRect:ofView:untilMouseUp: on it, if the tracking area was inside of it.
112 if (mouseDownInButton) {
113 // Send the action, and redisplay
114 mouseDownInButton = NO;
115 [controlView setNeedsDisplayInRect:cellFrame];
117 [NSApp sendAction:self.action to:self.target from:self];
120 // We return YES since the mouse was released while we were tracking. Not returning YES when you processed the mouse up is an easy way to introduce bugs!