jens@20
|
1 |
/*
|
jens@20
|
2 |
ImageAndTextCell.m
|
jens@20
|
3 |
Copyright (c) 2001-2006, Apple Computer, Inc., all rights reserved.
|
jens@20
|
4 |
Author: Chuck Pisula
|
jens@20
|
5 |
|
jens@20
|
6 |
Milestones:
|
jens@20
|
7 |
* 03-01-2001: Initial creation by Chuck Pisula
|
jens@20
|
8 |
* 11-04-2005: Added hitTestForEvent:inRect:ofView: for better NSOutlineView support by Corbin Dunn
|
jens@20
|
9 |
|
jens@20
|
10 |
Subclass of NSTextFieldCell which can display text and an image simultaneously.
|
jens@20
|
11 |
*/
|
jens@20
|
12 |
|
jens@20
|
13 |
/*
|
jens@20
|
14 |
IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
|
jens@20
|
15 |
consideration of your agreement to the following terms, and your use, installation,
|
jens@20
|
16 |
modification or redistribution of this Apple software constitutes acceptance of these
|
jens@20
|
17 |
terms. If you do not agree with these terms, please do not use, install, modify or
|
jens@20
|
18 |
redistribute this Apple software.
|
jens@20
|
19 |
|
jens@20
|
20 |
In consideration of your agreement to abide by the following terms, and subject to these
|
jens@20
|
21 |
terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in
|
jens@20
|
22 |
this original Apple software (the "Apple Software"), to use, reproduce, modify and
|
jens@20
|
23 |
redistribute the Apple Software, with or without modifications, in source and/or binary
|
jens@20
|
24 |
forms; provided that if you redistribute the Apple Software in its entirety and without
|
jens@20
|
25 |
modifications, you must retain this notice and the following text and disclaimers in all
|
jens@20
|
26 |
such redistributions of the Apple Software. Neither the name, trademarks, service marks
|
jens@20
|
27 |
or logos of Apple Computer, Inc. may be used to endorse or promote products derived from
|
jens@20
|
28 |
the Apple Software without specific prior written permission from Apple. Except as expressly
|
jens@20
|
29 |
stated in this notice, no other rights or licenses, express or implied, are granted by Apple
|
jens@20
|
30 |
herein, including but not limited to any patent rights that may be infringed by your
|
jens@20
|
31 |
derivative works or by other works in which the Apple Software may be incorporated.
|
jens@20
|
32 |
|
jens@20
|
33 |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES,
|
jens@20
|
34 |
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
|
jens@20
|
35 |
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS
|
jens@20
|
36 |
USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
|
jens@20
|
37 |
|
jens@20
|
38 |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
|
jens@20
|
39 |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
jens@20
|
40 |
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
|
jens@20
|
41 |
REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND
|
jens@20
|
42 |
WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
|
jens@20
|
43 |
OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
jens@20
|
44 |
*/
|
jens@20
|
45 |
|
jens@20
|
46 |
#import "ImageAndTextCell.h"
|
jens@20
|
47 |
#import <AppKit/NSCell.h>
|
jens@20
|
48 |
|
jens@20
|
49 |
@implementation ImageAndTextCell
|
jens@20
|
50 |
|
jens@20
|
51 |
- (id)init {
|
jens@20
|
52 |
self = [super init];
|
jens@20
|
53 |
if( self ) {
|
jens@20
|
54 |
[self setLineBreakMode:NSLineBreakByTruncatingTail];
|
jens@20
|
55 |
[self setSelectable:YES];
|
jens@20
|
56 |
}
|
jens@20
|
57 |
return self;
|
jens@20
|
58 |
}
|
jens@20
|
59 |
|
jens@20
|
60 |
- (void)dealloc {
|
jens@20
|
61 |
[image release];
|
jens@20
|
62 |
[super dealloc];
|
jens@20
|
63 |
}
|
jens@20
|
64 |
|
jens@20
|
65 |
- (id)copyWithZone:(NSZone *)zone {
|
jens@20
|
66 |
ImageAndTextCell *cell = (ImageAndTextCell *)[super copyWithZone:zone];
|
jens@20
|
67 |
// The image ivar will be directly copied; we need to retain or copy it.
|
jens@20
|
68 |
cell->image = [image retain];
|
jens@20
|
69 |
return cell;
|
jens@20
|
70 |
}
|
jens@20
|
71 |
|
jens@20
|
72 |
- (void)setImage:(NSImage *)anImage {
|
jens@20
|
73 |
if (anImage != image) {
|
jens@20
|
74 |
[image release];
|
jens@20
|
75 |
image = [anImage retain];
|
jens@20
|
76 |
}
|
jens@20
|
77 |
}
|
jens@20
|
78 |
|
jens@20
|
79 |
- (NSImage *)image {
|
jens@20
|
80 |
return image;
|
jens@20
|
81 |
}
|
jens@20
|
82 |
|
jens@20
|
83 |
- (NSRect)imageRectForBounds:(NSRect)cellFrame {
|
jens@20
|
84 |
NSRect result;
|
jens@20
|
85 |
if (image != nil) {
|
jens@20
|
86 |
result.size = [image size];
|
jens@20
|
87 |
result.origin = cellFrame.origin;
|
jens@20
|
88 |
result.origin.x += 3;
|
jens@20
|
89 |
result.origin.y += ceil((cellFrame.size.height - result.size.height) / 2);
|
jens@20
|
90 |
} else {
|
jens@20
|
91 |
result = NSZeroRect;
|
jens@20
|
92 |
}
|
jens@20
|
93 |
return result;
|
jens@20
|
94 |
}
|
jens@20
|
95 |
|
jens@20
|
96 |
// We could manually implement expansionFrameWithFrame:inView: and drawWithExpansionFrame:inView: or just properly implement titleRectForBounds to get expansion tooltips to automatically work for us
|
jens@20
|
97 |
- (NSRect)titleRectForBounds:(NSRect)cellFrame {
|
jens@20
|
98 |
NSRect result;
|
jens@20
|
99 |
if (image != nil) {
|
jens@20
|
100 |
CGFloat imageWidth = [image size].width;
|
jens@20
|
101 |
result = cellFrame;
|
jens@20
|
102 |
result.origin.x += (3 + imageWidth);
|
jens@20
|
103 |
result.size.width -= (3 + imageWidth);
|
jens@20
|
104 |
} else {
|
jens@20
|
105 |
result = NSZeroRect;
|
jens@20
|
106 |
}
|
jens@20
|
107 |
return result;
|
jens@20
|
108 |
}
|
jens@20
|
109 |
|
jens@20
|
110 |
|
jens@20
|
111 |
- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent {
|
jens@20
|
112 |
NSRect textFrame, imageFrame;
|
jens@20
|
113 |
NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
|
jens@20
|
114 |
[super editWithFrame: textFrame inView: controlView editor:textObj delegate:anObject event: theEvent];
|
jens@20
|
115 |
}
|
jens@20
|
116 |
|
jens@20
|
117 |
- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength {
|
jens@20
|
118 |
NSRect textFrame, imageFrame;
|
jens@20
|
119 |
NSDivideRect (aRect, &imageFrame, &textFrame, 3 + [image size].width, NSMinXEdge);
|
jens@20
|
120 |
[super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength];
|
jens@20
|
121 |
}
|
jens@20
|
122 |
|
jens@20
|
123 |
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
|
jens@20
|
124 |
if (image != nil) {
|
jens@20
|
125 |
NSRect imageFrame;
|
jens@20
|
126 |
NSSize imageSize = [image size];
|
jens@20
|
127 |
NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge);
|
jens@20
|
128 |
if ([self drawsBackground]) {
|
jens@20
|
129 |
[[self backgroundColor] set];
|
jens@20
|
130 |
NSRectFill(imageFrame);
|
jens@20
|
131 |
}
|
jens@20
|
132 |
imageFrame.origin.x += 3;
|
jens@20
|
133 |
imageFrame.size = imageSize;
|
jens@20
|
134 |
|
jens@20
|
135 |
if ([controlView isFlipped])
|
jens@20
|
136 |
imageFrame.origin.y += ceil((cellFrame.size.height + imageFrame.size.height) / 2);
|
jens@20
|
137 |
else
|
jens@20
|
138 |
imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2);
|
jens@20
|
139 |
|
jens@20
|
140 |
[image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver];
|
jens@20
|
141 |
}
|
jens@20
|
142 |
[super drawWithFrame:cellFrame inView:controlView];
|
jens@20
|
143 |
}
|
jens@20
|
144 |
|
jens@20
|
145 |
- (NSSize)cellSize {
|
jens@20
|
146 |
NSSize cellSize = [super cellSize];
|
jens@20
|
147 |
cellSize.width += (image ? [image size].width : 0) + 3;
|
jens@20
|
148 |
return cellSize;
|
jens@20
|
149 |
}
|
jens@20
|
150 |
|
jens@20
|
151 |
- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView {
|
jens@20
|
152 |
NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
|
jens@20
|
153 |
// If we have an image, we need to see if the user clicked on the image portion.
|
jens@20
|
154 |
if (image != nil) {
|
jens@20
|
155 |
// This code closely mimics drawWithFrame:inView:
|
jens@20
|
156 |
NSSize imageSize = [image size];
|
jens@20
|
157 |
NSRect imageFrame;
|
jens@20
|
158 |
NSDivideRect(cellFrame, &imageFrame, &cellFrame, 3 + imageSize.width, NSMinXEdge);
|
jens@20
|
159 |
|
jens@20
|
160 |
imageFrame.origin.x += 3;
|
jens@20
|
161 |
imageFrame.size = imageSize;
|
jens@20
|
162 |
// If the point is in the image rect, then it is a content hit
|
jens@20
|
163 |
if (NSMouseInRect(point, imageFrame, [controlView isFlipped])) {
|
jens@20
|
164 |
// We consider this just a content area. It is not trackable, nor it it editable text. If it was, we would or in the additional items.
|
jens@20
|
165 |
// By returning the correct parts, we allow NSTableView to correctly begin an edit when the text portion is clicked on.
|
jens@20
|
166 |
return NSCellHitContentArea;
|
jens@20
|
167 |
}
|
jens@20
|
168 |
}
|
jens@20
|
169 |
// At this point, the cellFrame has been modified to exclude the portion for the image. Let the superclass handle the hit testing at this point.
|
jens@20
|
170 |
return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];
|
jens@20
|
171 |
}
|
jens@20
|
172 |
|
jens@20
|
173 |
|
jens@20
|
174 |
@end
|
jens@20
|
175 |
|