source: trunk/Cocoa/Pester/Source/NSImage-OAExtensions.m@ 578

Last change on this file since 578 was 555, checked in by Nicholas Riley, 15 years ago

Fix (unimportant, in practice) retain leak in Omni NSImage extension.

File size: 7.5 KB
Line 
1// Copyright 1997-2002 Omni Development, Inc. All rights reserved.
2//
3// This software may only be used and reproduced according to the
4// terms in the file OmniSourceLicense.html, which should be
5// distributed with this project and can also be found at
6// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.
7
8#import "NSImage-OAExtensions.h"
9
10#import <AppKit/AppKit.h>
11
12// RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniAppKit/OpenStepExtensions.subproj/NSImage-OAExtensions.m,v 1.17 2002/03/09 01:53:54 kc Exp $")
13
14@implementation NSImage (OAExtensions)
15
16+ (NSImage *)imageNamed:(NSString *)imageName inBundleForClass:(Class)aClass;
17{
18 return [self imageNamed:imageName inBundle:[NSBundle bundleForClass:aClass]];
19}
20
21+ (NSImage *)imageNamed:(NSString *)imageName inBundle:(NSBundle *)aBundle;
22{
23 NSImage *image;
24 NSString *path;
25
26 image = [self imageNamed:imageName];
27 if (image && [image size].width != 0)
28 return image;
29
30 path = [aBundle pathForImageResource:imageName];
31 if (!path)
32 return nil;
33
34 image = [[NSImage alloc] initWithContentsOfFile:path];
35 [image setName:imageName];
36
37 return [image autorelease];
38}
39
40+ (NSImage *)imageForFileType:(NSString *)fileType;
41 // It turns out that -[NSWorkspace iconForFileType:] doesn't cache previously returned values, so we cache them here.
42{
43 static NSMutableDictionary *imageDictionary = nil;
44 id image;
45
46 // ASSERT_IN_MAIN_THREAD(@"+imageForFileType: is not thread-safe; must be called from the main thread");
47 // We could fix this by adding locks around imageDictionary
48
49 if (!fileType)
50 return nil;
51
52 if (imageDictionary == nil)
53 imageDictionary = [[NSMutableDictionary alloc] init];
54
55 image = [imageDictionary objectForKey:fileType];
56 if (image == nil) {
57#ifdef DEBUG
58 // Make sure that our caching doesn't go insane (and that we don't ask it to cache insane stuff)
59 NSLog(@"Caching workspace image for file type '%@'", fileType);
60#endif
61 image = [[NSWorkspace sharedWorkspace] iconForFileType:fileType];
62 if (image == nil)
63 image = [NSNull null];
64 [imageDictionary setObject:image forKey:fileType];
65 }
66 return image != [NSNull null] ? image : nil;
67}
68
69#define X_SPACE_BETWEEN_ICON_AND_TEXT_BOX 2
70#define X_TEXT_BOX_BORDER 2
71#define Y_TEXT_BOX_BORDER 2
72static NSDictionary *titleFontAttributes;
73
74+ (NSImage *)draggingIconWithTitle:(NSString *)title andImage:(NSImage *)image;
75{
76 NSImage *drawImage;
77 NSSize imageSize, totalSize;
78 NSSize titleSize, titleBoxSize;
79 NSRect titleBox;
80 NSPoint textPoint;
81
82 NSParameterAssert(image != nil);
83 imageSize = [image size];
84
85 if (!titleFontAttributes)
86 titleFontAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[NSFont systemFontOfSize:12.0], NSFontAttributeName, [NSColor textColor], NSForegroundColorAttributeName, nil];
87
88 if (!title || [title length] == 0)
89 return image;
90
91 titleSize = [title sizeWithAttributes:titleFontAttributes];
92 titleBoxSize = NSMakeSize(titleSize.width + 2.0 * X_TEXT_BOX_BORDER, titleSize.height + Y_TEXT_BOX_BORDER);
93
94 totalSize = NSMakeSize(imageSize.width + X_SPACE_BETWEEN_ICON_AND_TEXT_BOX + titleBoxSize.width, MAX(imageSize.height, titleBoxSize.height));
95
96 drawImage = [[NSImage alloc] initWithSize:totalSize];
97 [drawImage setFlipped:YES];
98
99 [drawImage lockFocus];
100
101 // Draw transparent background
102 [[NSColor colorWithDeviceWhite:1.0 alpha:0.0] set];
103 NSRectFill(NSMakeRect(0, 0, totalSize.width, totalSize.height));
104
105 // Draw icon
106 [image compositeToPoint:NSMakePoint(0.0, rint(totalSize.height / 2.0 + imageSize.height / 2.0)) operation:NSCompositeSourceOver];
107
108 // Draw box around title
109 titleBox = NSMakeRect(imageSize.width + X_SPACE_BETWEEN_ICON_AND_TEXT_BOX, floor((totalSize.height - titleBoxSize.height)/2.0), titleBoxSize.width, titleBoxSize.height);
110 [[[NSColor selectedTextBackgroundColor] colorWithAlphaComponent:0.5] set];
111 NSRectFill(titleBox);
112
113 // Draw title
114 textPoint = NSMakePoint(imageSize.width + X_SPACE_BETWEEN_ICON_AND_TEXT_BOX + X_TEXT_BOX_BORDER, Y_TEXT_BOX_BORDER - 1);
115
116 [title drawAtPoint:textPoint withAttributes:titleFontAttributes];
117
118 [drawImage unlockFocus];
119
120 return [drawImage autorelease];
121}
122
123//
124
125- (void)drawFlippedInRect:(NSRect)rect operation:(NSCompositingOperation)op fraction:(float)delta;
126{
127 CGContextRef context;
128
129 context = [[NSGraphicsContext currentContext] graphicsPort];
130 CGContextSaveGState(context); {
131 CGContextTranslateCTM(context, 0, NSMaxY(rect));
132 CGContextScaleCTM(context, 1, -1);
133
134 rect.origin.y = 0; // We've translated ourselves so it's zero
135 [self drawInRect:rect fromRect:NSZeroRect operation:op fraction:delta];
136 } CGContextRestoreGState(context);
137
138 /*
139 NSAffineTransform *flipTransform;
140 NSPoint transformedPoint;
141 NSSize transformedSize;
142 NSRect transformedRect;
143
144 flipTransform = [[NSAffineTransform alloc] init];
145 [flipTransform scaleXBy:1.0 yBy:-1.0];
146
147 transformedPoint = [flipTransform transformPoint:rect.origin];
148 transformedSize = [flipTransform transformSize:rect.size];
149 [flipTransform concat];
150 transformedRect = NSMakeRect(transformedPoint.x, transformedPoint.y + transformedSize.height, transformedSize.width, -transformedSize.height);
151 [anImage drawInRect:transformedRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
152 [flipTransform concat];
153 [flipTransform release];
154 */
155}
156
157- (void)drawFlippedInRect:(NSRect)rect operation:(NSCompositingOperation)op;
158{
159 [self drawFlippedInRect:rect operation:op fraction:1.0];
160}
161
162- (int)addDataToPasteboard:(NSPasteboard *)aPasteboard exceptTypes:(NSMutableSet *)notThese
163{
164 NSArray *myRepresentations;
165 int repIndex, repCount;
166 int count = 0;
167
168 if (!notThese)
169 notThese = [NSMutableSet set];
170
171#define IF_ADD(typename, dataOwner) if( ![notThese containsObject:(typename)] && [aPasteboard addTypes:[NSArray arrayWithObject:(typename)] owner:(dataOwner)] > 0 )
172
173#define ADD_CHEAP_DATA(typename, expr) IF_ADD(typename, nil) { [aPasteboard setData:(expr) forType:(typename)]; [notThese addObject:(typename)]; count ++; }
174
175 /* If we have image representations lying around that already have data in some concrete format, add that data to the pasteboard. */
176 myRepresentations = [self representations];
177 repCount = [myRepresentations count];
178 for(repIndex = 0; repIndex < repCount; repIndex ++) {
179 NSImageRep *aRep = [myRepresentations objectAtIndex:repIndex];
180
181 if ([aRep respondsToSelector:@selector(PDFRepresentation)]) {
182 ADD_CHEAP_DATA(NSPDFPboardType, [(NSPDFImageRep *)aRep PDFRepresentation]);
183 }
184
185 if ([aRep respondsToSelector:@selector(PICTRepresentation)]) {
186 ADD_CHEAP_DATA(NSPICTPboardType, [(NSPICTImageRep *)aRep PICTRepresentation]);
187 }
188
189 if ([aRep respondsToSelector:@selector(EPSRepresentation)]) {
190 ADD_CHEAP_DATA(NSPostScriptPboardType, [(NSEPSImageRep *)aRep EPSRepresentation]);
191 }
192 }
193
194 /* Always offer to convert to TIFF. Do this lazily, though, since we probably have to extract it from a bitmap image rep. */
195 IF_ADD(NSTIFFPboardType, self) {
196 count ++;
197 }
198
199 return count;
200}
201
202- (void)pasteboard:(NSPasteboard *)aPasteboard provideDataForType:(NSString *)wanted
203{
204 if ([wanted isEqual:NSTIFFPboardType]) {
205 [aPasteboard setData:[self TIFFRepresentation] forType:NSTIFFPboardType];
206 }
207}
208
209
210
211@end
Note: See TracBrowser for help on using the repository browser.