source: trunk/Cocoa/Pester/Source/NJRFSObjectSelector.m@ 601

Last change on this file since 601 was 601, checked in by Nicholas Riley, 14 years ago

Float vs. double fixes to pacify GCC.

File size: 9.8 KB
RevLine 
[34]1#import "NJRFSObjectSelector.h"
[355]2#import "NSMenuItem-NJRExtensions.h"
[53]3#import "NSString-NJRExtensions.h"
[34]4#include <Carbon/Carbon.h>
5
[53]6static NSImage *PopupTriangleImage = nil;
7static NSSize PopupTriangleSize;
8
[600]9@interface NJRFSObjectSelector (NSOpenPanelRuntime)
10- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
11@end
12
[34]13@implementation NJRFSObjectSelector
14
15- (void)_initSelector;
16{
[53]17 if (PopupTriangleImage == nil) {
18 PopupTriangleImage = [[NSImage imageNamed: @"Popup triangle"] retain];
19 PopupTriangleSize = [PopupTriangleImage size];
20 }
[34]21 canChooseFiles = YES; canChooseDirectories = NO;
22 [self setAlias: nil];
23 [[self cell] setHighlightsBy: NSChangeBackgroundCell];
24 [[self cell] setGradientType: NSGradientNone];
25 [self registerForDraggedTypes:
26 [NSArray arrayWithObjects: NSFilenamesPboardType, NSURLPboardType, nil]];
27}
28
29- (void)dealloc;
30{
31 [selectedAlias release];
32 [fileTypes release];
33 [super dealloc];
34}
35
36- (id)initWithCoder:(NSCoder *)coder;
37{
38 if ( (self = [super initWithCoder: coder]) != nil) {
39 [self _initSelector];
40 }
41 return self;
42}
43
44- (id)initWithFrame:(NSRect)frame;
45{
46 if ( (self = [super initWithFrame: frame]) != nil) {
47 [self _initSelector];
48 }
49 return self;
50}
51
52- (void)drawRect:(NSRect)rect;
53{
[41]54 NSRect boundsRect = [self bounds];
[34]55 [super drawRect: rect];
56 if (dragAccepted) {
57 [[NSColor selectedControlColor] set];
58 [NSBezierPath setDefaultLineWidth: 2];
[41]59 [NSBezierPath strokeRect: NSInsetRect(boundsRect, 2, 2)];
60 } else if (selectedAlias != nil && [self isEnabled]) {
[34]61 // equivalent to popup triangle location for large bezel in Carbon
[53]62 [PopupTriangleImage compositeToPoint: NSMakePoint(NSMaxX(boundsRect) - PopupTriangleSize.width - 5, NSMaxY(boundsRect) - 5) operation: NSCompositeSourceOver];
[34]63 }
64}
65
66- (BOOL)acceptsPath:(NSString *)path;
67{
68 NSFileManager *fm = [NSFileManager defaultManager];
69 BOOL isDir;
70
71 if (![fm fileExistsAtPath: path isDirectory: &isDir]) return NO;
72
73 if (isDir) return canChooseDirectories;
74 if (canChooseFiles) {
75 NSEnumerator *e = [fileTypes objectEnumerator];
76 NSString *extension = [path pathExtension];
77 NSString *hfsType = NSHFSTypeOfFile(path);
78 NSString *fileType;
79
80 while ( (fileType = [e nextObject]) != nil) {
81 if ([fileType isEqualToString: extension] || [fileType isEqualToString: hfsType])
82 return YES;
83 }
84 }
85 return NO;
86}
87
88- (IBAction)select:(id)sender;
89{
90 NSOpenPanel *openPanel = [NSOpenPanel openPanel];
91 NSString *path = [selectedAlias fullPath];
92 [openPanel setAllowsMultipleSelection: NO];
93 [openPanel setCanChooseDirectories: canChooseDirectories];
94 [openPanel setCanChooseFiles: canChooseFiles];
95 [openPanel beginSheetForDirectory: [path stringByDeletingLastPathComponent]
96 file: [path lastPathComponent]
97 types: fileTypes
98 modalForWindow: [self window]
99 modalDelegate: self
100 didEndSelector: @selector(openPanelDidEnd:returnCode:contextInfo:)
101 contextInfo: nil];
102}
103
104- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
105{
106 [sheet close];
107
108 if (returnCode == NSOKButton) {
109 NSArray *files = [sheet filenames];
110 NSAssert1([files count] == 1, @"%d items returned, only one expected", [files count]);
111 [self setPath: [files objectAtIndex: 0]];
[355]112 if ([self target] != nil && [[self target] respondsToSelector:[self action]])
113 [[self target] performSelector: [self action] withObject: self];
[34]114 }
115}
116
[587]117- (void)revealInFinder:(NSMenuItem *)sender;
[34]118{
119 NSString *path = [sender representedObject];
120 if (path == nil) return;
121 [[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath: @""];
122}
123
124- (void)setAlias:(BDAlias *)alias;
125{
126 if (selectedAlias != alias) {
127 [selectedAlias release];
128 selectedAlias = [alias retain];
129 }
130
131 if (alias != nil) { // alias is set
132 NSString *path = [alias fullPath];
133 NSString *revealPath = nil;
134 NSMenu *menu = [[NSMenu alloc] initWithTitle: @""];
135 NSFileManager *fmgr = [NSFileManager defaultManager];
136 NSMenuItem *item;
137 if (path != nil) { // can resolve alias
[553]138 [self setImage: [[NSWorkspace sharedWorkspace] iconForFile: path]];
[53]139 { // set image first so titleRectForBounds: returns the correct value
140 NSMutableString *title = [[fmgr displayNameAtPath: path] mutableCopy];
141 NSDictionary *fontAttributes = [[self attributedTitle] fontAttributesInRange: NSMakeRange(0, 0)];
142 [title truncateToWidth: [[self cell] titleRectForBounds: [self bounds]].size.width - PopupTriangleSize.width by: NSLineBreakByTruncatingMiddle withAttributes: fontAttributes];
143 [self setTitle: title];
144 [title release];
145 }
[34]146 do {
[355]147 NSAssert1(![path isEqualToString: revealPath], @"Stuck on path |%@|", [alias fullPath]);
[34]148 item = [menu addItemWithTitle: [fmgr displayNameAtPath: path]
149 action: @selector(revealInFinder:)
150 keyEquivalent: @""];
151 [item setTarget: self];
152 [item setRepresentedObject: revealPath];
[355]153 [item setImageFromPath: path];
[34]154 revealPath = path;
155 path = [path stringByDeletingLastPathComponent];
156 } while (![revealPath isEqualToString: @"/"] && ![path isEqualToString: @"/Volumes"]);
157 [[self cell] setMenu: menu];
158 } else {
159 [self setImage: nil];
160 [self setTitle: @"(not available)"];
161 [[self cell] setMenu: nil];
162 }
[558]163 [menu release];
[34]164 } else {
165 [self setImage: nil];
166 [self setTitle: @"(none selected)"];
167 [[self cell] setMenu: nil];
168 }
[43]169 [self setEnabled: isEnabled];
[34]170}
171
[43]172- (BOOL)isEnabled;
173{
174 return isEnabled;
175}
176
[34]177- (void)setEnabled:(BOOL)enabled;
178{
[43]179 isEnabled = enabled;
[34]180 [super setEnabled: enabled ? selectedAlias != nil : NO];
181}
182
183- (void)rightMouseDown:(NSEvent *)theEvent;
184{
185 [self mouseDown: theEvent];
186}
187
188- (void)otherMouseDown:(NSEvent *)theEvent;
189{
190 [self mouseDown: theEvent];
191}
192
193extern MenuRef _NSGetCarbonMenu(NSMenu *menu);
194
195- (void)mouseDown:(NSEvent *)theEvent;
196{
[355]197 if (![self isEnabled]) return;
198
[34]199 NSMenu *menu = [[self cell] menu];
200 MenuRef mRef = _NSGetCarbonMenu(menu);
201
202 if (mRef == NULL) {
203 NSMenu *appMenu = [[[NSApp mainMenu] itemWithTitle: @""] submenu];
204 if (appMenu != nil) {
205 NSMenuItem *item = [appMenu addItemWithTitle: @"" action: NULL keyEquivalent: @""];
206 [appMenu setSubmenu: menu forItem: item];
207 [appMenu removeItem: item];
208 }
209 mRef = _NSGetCarbonMenu(menu);
210 }
211
212 ChangeMenuAttributes(mRef, kMenuAttrExcludesMarkColumn, 0);
213 theEvent = [NSEvent mouseEventWithType: [theEvent type]
214 location: [self convertPoint: NSMakePoint(-1, 1) toView: nil]
215 modifierFlags: [theEvent modifierFlags]
216 timestamp: [theEvent timestamp]
217 windowNumber: [theEvent windowNumber]
218 context: [theEvent context]
219 eventNumber: [theEvent eventNumber]
220 clickCount: [theEvent clickCount]
221 pressure: [theEvent pressure]];
222
[355]223 // XXX otherwise Cocoa thoughtfully doesn't give me the font I want
224 NSFont *font = [[self cell] font];
225 [NSMenu popUpContextMenu: menu withEvent: theEvent forView: self withFont:
[601]226 [NSFont fontWithName: [font fontName] size: [font pointSize] - 0.001f]];
[34]227}
228
229- (BDAlias *)alias;
230{
231 return selectedAlias;
232}
233
234- (void)setPath:(NSString *)path;
235{
236 [self setAlias: [BDAlias aliasWithPath: path]];
237}
238
239- (BOOL)canChooseDirectories;
240{
241 return canChooseDirectories;
242}
243
244- (BOOL)canChooseFiles;
245{
246 return canChooseFiles;
247}
248
249- (void)setCanChooseDirectories:(BOOL)flag;
250{
251 canChooseDirectories = flag;
252}
253
254- (void)setCanChooseFiles:(BOOL)flag;
255{
256 canChooseFiles = flag;
257}
258
259- (NSArray *)fileTypes;
260{
261 return fileTypes;
262}
263
264- (void)setFileTypes:(NSArray *)types;
265{
266 if (fileTypes == types) return;
267
268 [fileTypes release];
269 fileTypes = [types retain];
270}
271
272@end
273
274
275@implementation NJRFSObjectSelector (NSDraggingDestination)
276
277- (BOOL)acceptsDragFrom:(id <NSDraggingInfo>)sender;
278{
279 NSURL *url = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
280
281 if (url == nil || ![url isFileURL]) return NO;
282 return [self acceptsPath: [url path]];
283}
284
285- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender;
286{
287 if ([self acceptsDragFrom: sender] && [sender draggingSourceOperationMask] &
[41]288 (NSDragOperationCopy | NSDragOperationLink)) {
[34]289 dragAccepted = YES;
290 [self setNeedsDisplay: YES];
[41]291 return NSDragOperationLink;
[34]292 }
293 return NSDragOperationNone;
294}
295
296- (void)draggingExited:(id <NSDraggingInfo>)sender;
297{
298 dragAccepted = NO;
299 [self setNeedsDisplay: YES];
300}
301
302- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender;
303{
304 dragAccepted = NO;
305 [self setNeedsDisplay: YES];
306 return [self acceptsDragFrom: sender];
307}
308
309- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender;
310{
311 if ([sender draggingSource] != self) {
312 NSURL *url = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
313 if (url == nil) return NO;
314 [self setPath: [url path]];
[355]315 if ([self target] != nil && [[self target] respondsToSelector:[self action]])
316 [[self target] performSelector: [self action] withObject: self];
[34]317 }
318 return YES;
319}
320
321@end
Note: See TracBrowser for help on using the repository browser.