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

Last change on this file since 36 was 34, checked in by Nicholas Riley, 22 years ago

Changes for Pester 1.1d1.

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