]> git.sesse.net Git - vlc/blob - modules/gui/macosx/MainWindowTitle.m
Revert "macosx: clean code of objectAtIndex"
[vlc] / modules / gui / macosx / MainWindowTitle.m
1 /*****************************************************************************
2  * MainWindowTitle.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2011-2012 Felix Paul Kühne
5  * $Id$
6  *
7  * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #import <vlc_common.h>
25 #import "intf.h"
26 #import "MainWindowTitle.h"
27 #import "CoreInteraction.h"
28 #import "CompatibilityFixes.h"
29 #import <SystemConfiguration/SystemConfiguration.h> // for the revealInFinder clone
30
31 /*****************************************************************************
32  * VLCMainWindowTitleView
33  *
34  * this is our title bar, which can do anything a title should do
35  * it relies on the VLCWindowButtonCell to display the correct traffic light
36  * states, since we can't capture the mouse-moved events here correctly
37  *****************************************************************************/
38
39 @implementation VLCMainWindowTitleView
40 - (id)init
41 {
42     o_window_title_attributes_dict = [[NSDictionary dictionaryWithObjectsAndKeys: [NSColor whiteColor], NSForegroundColorAttributeName, [NSFont titleBarFontOfSize:12.0], NSFontAttributeName, nil] retain];
43
44     return [super init];
45 }
46
47 - (void)dealloc
48 {
49     [[NSNotificationCenter defaultCenter] removeObserver: self];
50
51     [o_red_img release];
52     [o_red_over_img release];
53     [o_red_on_img release];
54     [o_yellow_img release];
55     [o_yellow_over_img release];
56     [o_yellow_on_img release];
57     [o_green_img release];
58     [o_green_over_img release];
59     [o_green_on_img release];
60
61     [o_window_title_shadow release];
62     [o_window_title_attributes_dict release];
63
64     [super dealloc];
65 }
66
67 - (void)awakeFromNib
68 {
69     [self setAutoresizesSubviews: YES];
70     [self setImagesLeft:[NSImage imageNamed:@"topbar-dark-left"] middle: [NSImage imageNamed:@"topbar-dark-center-fill"] right:[NSImage imageNamed:@"topbar-dark-right"]];
71
72     [self loadButtonIcons];
73     [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(controlTintChanged:) name: NSControlTintDidChangeNotification object: nil];
74 }
75
76 - (void)controlTintChanged:(NSNotification *)notification
77 {
78     [o_red_img release];
79     [o_red_over_img release];
80     [o_red_on_img release];
81     [o_yellow_img release];
82     [o_yellow_over_img release];
83     [o_yellow_on_img release];
84     [o_green_img release];
85     [o_green_over_img release];
86     [o_green_on_img release];
87
88     [self loadButtonIcons];
89
90     [o_red_btn setNeedsDisplay];
91     [o_yellow_btn setNeedsDisplay];
92     [o_green_btn setNeedsDisplay];
93 }
94
95 - (void)loadButtonIcons
96 {
97     if (!OSX_SNOW_LEOPARD) {
98         if ([NSColor currentControlTint] == NSBlueControlTint)
99         {
100             o_red_img = [[NSImage imageNamed:@"lion-window-close"] retain];
101             o_red_over_img = [[NSImage imageNamed:@"lion-window-close-over"] retain];
102             o_red_on_img = [[NSImage imageNamed:@"lion-window-close-on"] retain];
103             o_yellow_img = [[NSImage imageNamed:@"lion-window-minimize"] retain];
104             o_yellow_over_img = [[NSImage imageNamed:@"lion-window-minimize-over"] retain];
105             o_yellow_on_img = [[NSImage imageNamed:@"lion-window-minimize-on"] retain];
106             o_green_img = [[NSImage imageNamed:@"lion-window-zoom"] retain];
107             o_green_over_img = [[NSImage imageNamed:@"lion-window-zoom-over"] retain];
108             o_green_on_img = [[NSImage imageNamed:@"lion-window-zoom-on"] retain];
109         } else {
110             o_red_img = [[NSImage imageNamed:@"lion-window-close-graphite"] retain];
111             o_red_over_img = [[NSImage imageNamed:@"lion-window-close-over-graphite"] retain];
112             o_red_on_img = [[NSImage imageNamed:@"lion-window-close-on-graphite"] retain];
113             o_yellow_img = [[NSImage imageNamed:@"lion-window-minimize-graphite"] retain];
114             o_yellow_over_img = [[NSImage imageNamed:@"lion-window-minimize-over-graphite"] retain];
115             o_yellow_on_img = [[NSImage imageNamed:@"lion-window-minimize-on-graphite"] retain];
116             o_green_img = [[NSImage imageNamed:@"lion-window-zoom-graphite"] retain];
117             o_green_over_img = [[NSImage imageNamed:@"lion-window-zoom-over-graphite"] retain];
118             o_green_on_img = [[NSImage imageNamed:@"lion-window-zoom-on-graphite"] retain];
119         }
120     } else {
121         if ([NSColor currentControlTint] == NSBlueControlTint)
122         {
123             o_red_img = [[NSImage imageNamed:@"snowleo-window-close"] retain];
124             o_red_over_img = [[NSImage imageNamed:@"snowleo-window-close-over"] retain];
125             o_red_on_img = [[NSImage imageNamed:@"snowleo-window-close-on"] retain];
126             o_yellow_img = [[NSImage imageNamed:@"snowleo-window-minimize"] retain];
127             o_yellow_over_img = [[NSImage imageNamed:@"snowleo-window-minimize-over"] retain];
128             o_yellow_on_img = [[NSImage imageNamed:@"snowleo-window-minimize-on"] retain];
129             o_green_img = [[NSImage imageNamed:@"snowleo-window-zoom"] retain];
130             o_green_over_img = [[NSImage imageNamed:@"snowleo-window-zoom-over"] retain];
131             o_green_on_img = [[NSImage imageNamed:@"snowleo-window-zoom-on"] retain];
132         } else {
133             o_red_img = [[NSImage imageNamed:@"snowleo-window-close-graphite"] retain];
134             o_red_over_img = [[NSImage imageNamed:@"snowleo-window-close-over-graphite"] retain];
135             o_red_on_img = [[NSImage imageNamed:@"snowleo-window-close-on-graphite"] retain];
136             o_yellow_img = [[NSImage imageNamed:@"snowleo-window-minimize-graphite"] retain];
137             o_yellow_over_img = [[NSImage imageNamed:@"snowleo-window-minimize-over-graphite"] retain];
138             o_yellow_on_img = [[NSImage imageNamed:@"snowleo-window-minimize-on-graphite"] retain];
139             o_green_img = [[NSImage imageNamed:@"snowleo-window-zoom-graphite"] retain];
140             o_green_over_img = [[NSImage imageNamed:@"snowleo-window-zoom-over-graphite"] retain];
141             o_green_on_img = [[NSImage imageNamed:@"snowleo-window-zoom-on-graphite"] retain];
142         }
143     }
144
145     [o_red_btn setImage: o_red_img];
146     [o_red_btn setAlternateImage: o_red_on_img];
147     [[o_red_btn cell] setShowsBorderOnlyWhileMouseInside: YES];
148     [[o_red_btn cell] setTag: 0];
149     [o_yellow_btn setImage: o_yellow_img];
150     [o_yellow_btn setAlternateImage: o_yellow_on_img];
151     [[o_yellow_btn cell] setShowsBorderOnlyWhileMouseInside: YES];
152     [[o_yellow_btn cell] setTag: 1];
153     [o_green_btn setImage: o_green_img];
154     [o_green_btn setAlternateImage: o_green_on_img];
155     [[o_green_btn cell] setShowsBorderOnlyWhileMouseInside: YES];
156     [[o_green_btn cell] setTag: 2];
157     [o_fullscreen_btn setImage: [NSImage imageNamed:@"window-fullscreen"]];
158     [o_fullscreen_btn setAlternateImage: [NSImage imageNamed:@"window-fullscreen-on"]];
159     [[o_fullscreen_btn cell] setShowsBorderOnlyWhileMouseInside: YES];
160     [[o_fullscreen_btn cell] setTag: 3];
161 }
162
163 - (BOOL)mouseDownCanMoveWindow
164 {
165     return YES;
166 }
167
168 - (IBAction)buttonAction:(id)sender
169 {
170     if (sender == o_red_btn)
171         [[self window] performClose: sender];
172     else if (sender == o_yellow_btn)
173         [[self window] miniaturize: sender];
174     else if (sender == o_green_btn)
175         [[self window] performZoom: sender];
176     else if (sender == o_fullscreen_btn) {
177         // same action as native fs button
178         [[self window] toggleFullScreen:self];
179
180     } else
181         msg_Err(VLCIntf, "unknown button action sender");
182
183     [self setWindowButtonOver: NO];
184     [self setWindowFullscreenButtonOver: NO];
185 }
186
187 - (void)setWindowTitle:(NSString *)title
188 {
189     if (!o_window_title_shadow) {
190         o_window_title_shadow = [[NSShadow alloc] init];
191         [o_window_title_shadow setShadowColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.5]];
192         [o_window_title_shadow setShadowOffset:NSMakeSize(0.0, -1.5)];
193         [o_window_title_shadow setShadowBlurRadius:0.5];
194         [o_window_title_shadow retain];
195     }
196
197     NSMutableAttributedString *o_attributed_title = [[NSMutableAttributedString alloc] initWithString:title attributes: o_window_title_attributes_dict];
198     NSUInteger i_titleLength = [title length];
199
200     [o_attributed_title addAttribute:NSShadowAttributeName value:o_window_title_shadow range:NSMakeRange(0, i_titleLength)];
201     [o_attributed_title setAlignment: NSCenterTextAlignment range:NSMakeRange(0, i_titleLength)];
202     [o_title_lbl setAttributedStringValue:o_attributed_title];
203     [o_attributed_title release];
204 }
205
206 - (void)setFullscreenButtonHidden:(BOOL)b_value
207 {
208     [o_fullscreen_btn setHidden: b_value];
209 }
210
211 - (void)setWindowButtonOver:(BOOL)b_value
212 {
213     if (b_value) {
214         [o_red_btn setImage: o_red_over_img];
215         [o_yellow_btn setImage: o_yellow_over_img];
216         [o_green_btn setImage: o_green_over_img];
217     } else {
218         [o_red_btn setImage: o_red_img];
219         [o_yellow_btn setImage: o_yellow_img];
220         [o_green_btn setImage: o_green_img];
221     }
222 }
223
224 - (void)setWindowFullscreenButtonOver:(BOOL)b_value
225 {
226     if (b_value)
227         [o_fullscreen_btn setImage: [NSImage imageNamed:@"window-fullscreen-over"]];
228     else
229         [o_fullscreen_btn setImage: [NSImage imageNamed:@"window-fullscreen"]];
230 }
231
232 - (void)mouseDown:(NSEvent *)event
233 {
234     NSPoint ml = [self convertPoint: [event locationInWindow] fromView: self];
235     if (([[self window] frame].size.height - ml.y) <= 22. && [event clickCount] == 2) {
236         //Get settings from "System Preferences" >  "Appearance" > "Double-click on windows title bar to minimize"
237         NSString *const MDAppleMiniaturizeOnDoubleClickKey = @"AppleMiniaturizeOnDoubleClick";
238         NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
239         [userDefaults addSuiteNamed:NSGlobalDomain];
240
241         if ([[userDefaults objectForKey:MDAppleMiniaturizeOnDoubleClickKey] boolValue])
242             [[self window] miniaturize:self];
243     }
244
245     [super mouseDown: event];
246 }
247
248 - (NSButton*)closeButton
249 {
250     return o_red_btn;
251 }
252
253 - (NSButton*)minimizeButton
254 {
255     return o_yellow_btn;
256 }
257
258 - (NSButton*)zoomButton
259 {
260     return o_green_btn;
261 }
262
263 @end
264
265 /*****************************************************************************
266  * VLCWindowButtonCell
267  *
268  * since the title bar cannot fetch these mouse events (the more top-level
269  * NSButton is unable fetch them as well), we are using a subclass of the
270  * button cell to do so. It's set in the nib for the respective objects.
271  *****************************************************************************/
272
273 @implementation VLCWindowButtonCell
274
275 - (void)mouseEntered:(NSEvent *)theEvent
276 {
277     if ([self tag] == 3)
278         [(VLCMainWindowTitleView *)[[self controlView] superview] setWindowFullscreenButtonOver: YES];
279     else
280         [(VLCMainWindowTitleView *)[[self controlView] superview] setWindowButtonOver: YES];
281 }
282
283 - (void)mouseExited:(NSEvent *)theEvent
284 {
285     if ([self tag] == 3)
286         [(VLCMainWindowTitleView *)[[self controlView] superview] setWindowFullscreenButtonOver: NO];
287     else
288         [(VLCMainWindowTitleView *)[[self controlView] superview] setWindowButtonOver: NO];
289 }
290
291 /* accessibility stuff */
292 - (NSArray*)accessibilityAttributeNames {
293     NSArray *theAttributeNames = [super accessibilityAttributeNames];
294     id theControlView = [self controlView];
295     return ([theControlView respondsToSelector: @selector(extendedAccessibilityAttributeNames:)] ? [theControlView extendedAccessibilityAttributeNames: theAttributeNames] : theAttributeNames); // ask the cell's control view (i.e., the button) for additional attribute values
296 }
297
298 - (id)accessibilityAttributeValue: (NSString*)theAttributeName {
299     id theControlView = [self controlView];
300     if ([theControlView respondsToSelector: @selector(extendedAccessibilityAttributeValue:)]) {
301         id theValue = [theControlView extendedAccessibilityAttributeValue: theAttributeName];
302         if (theValue) {
303             return theValue; // if this is an extended attribute value we added, return that -- otherwise, fall back to super's implementation
304         }
305     }
306     return [super accessibilityAttributeValue: theAttributeName];
307 }
308
309 - (BOOL)accessibilityIsAttributeSettable: (NSString*)theAttributeName {
310     id theControlView = [self controlView];
311     if ([theControlView respondsToSelector: @selector(extendedAccessibilityIsAttributeSettable:)]) {
312         NSNumber *theValue = [theControlView extendedAccessibilityIsAttributeSettable: theAttributeName];
313         if (theValue)
314             return [theValue boolValue]; // same basic strategy we use in -accessibilityAttributeValue:
315     }
316     return [super accessibilityIsAttributeSettable: theAttributeName];
317 }
318
319 @end
320
321
322 /*****************************************************************************
323  * VLCResizeControl
324  *
325  * For Leopard and Snow Leopard, we need to emulate the resize control on the
326  * bottom right of the window, since it is gone by using the borderless window
327  * mask. A proper fix would be Lion-only.
328  *****************************************************************************/
329
330 @implementation VLCResizeControl
331
332 - (void)mouseDown:(NSEvent *)theEvent {
333     BOOL keepOn = YES;
334
335     while (keepOn) {
336         theEvent = [[self window] nextEventMatchingMask: NSLeftMouseUpMask |
337                     NSLeftMouseDraggedMask];
338
339         switch ([theEvent type]) {
340             case NSLeftMouseDragged:
341             {
342                 NSRect windowFrame = [[self window] frame];
343                 CGFloat deltaX, deltaY, oldOriginY;
344                 deltaX = [theEvent deltaX];
345                 deltaY = [theEvent deltaY];
346                 oldOriginY = windowFrame.origin.y;
347
348                 windowFrame.origin.y = (oldOriginY + windowFrame.size.height) - (windowFrame.size.height + deltaY);
349                 windowFrame.size.width += deltaX;
350                 windowFrame.size.height += deltaY;
351
352                 NSSize winMinSize = [self window].minSize;
353                 if (windowFrame.size.width < winMinSize.width)
354                     windowFrame.size.width = winMinSize.width;
355
356                 if (windowFrame.size.height < winMinSize.height) {
357                     windowFrame.size.height = winMinSize.height;
358                     windowFrame.origin.y = oldOriginY;
359                 }
360
361                 [[self window] setFrame: windowFrame display: YES animate: NO];
362                 break;
363             }
364                 break;
365             case NSLeftMouseUp:
366                 keepOn = NO;
367                 break;
368             default:
369                 /* Ignore any other kind of event. */
370                 break;
371         }
372
373     };
374
375     return;
376 }
377
378 @end
379
380 /*****************************************************************************
381  * VLCColorView
382  *
383  * since we are using a clear window color when using the black window
384  * style, some filling is needed behind the video and some other elements
385  *****************************************************************************/
386
387 @implementation VLCColorView
388
389 - (void)drawRect:(NSRect)rect {
390     [[NSColor blackColor] setFill];
391     NSRectFill(rect);
392 }
393
394 @end
395
396 /*****************************************************************************
397  * custom window buttons to support the accessibility stuff
398  *****************************************************************************/
399
400 @implementation VLCCustomWindowButtonPrototype
401 + (Class)cellClass {
402     return [VLCWindowButtonCell class];
403 }
404
405 - (NSArray*)extendedAccessibilityAttributeNames: (NSArray*)theAttributeNames {
406     return ([theAttributeNames containsObject: NSAccessibilitySubroleAttribute] ? theAttributeNames : [theAttributeNames arrayByAddingObject: NSAccessibilitySubroleAttribute]); // run-of-the-mill button cells don't usually have a Subrole attribute, so we add that attribute
407 }
408
409 - (id)extendedAccessibilityAttributeValue: (NSString*)theAttributeName {
410     return nil;
411 }
412
413 - (NSNumber*)extendedAccessibilityIsAttributeSettable: (NSString*)theAttributeName {
414     return ([theAttributeName isEqualToString: NSAccessibilitySubroleAttribute] ? @NO : nil); // make the Subrole attribute we added non-settable
415 }
416
417 - (void)accessibilityPerformAction: (NSString*)theActionName {
418     if ([theActionName isEqualToString: NSAccessibilityPressAction]) {
419         if ([self isEnabled])
420             [self performClick: nil];
421     } else
422         [super accessibilityPerformAction: theActionName];
423 }
424
425 @end
426
427 @implementation VLCCustomWindowCloseButton
428 - (id)extendedAccessibilityAttributeValue: (NSString*)theAttributeName {
429     return ([theAttributeName isEqualToString: NSAccessibilitySubroleAttribute] ? NSAccessibilityCloseButtonAttribute : nil);
430 }
431
432 @end
433
434
435 @implementation VLCCustomWindowMinimizeButton
436 - (id)extendedAccessibilityAttributeValue: (NSString*)theAttributeName {
437     return ([theAttributeName isEqualToString: NSAccessibilitySubroleAttribute] ? NSAccessibilityMinimizeButtonAttribute : nil);
438 }
439
440 @end
441
442
443 @implementation VLCCustomWindowZoomButton
444 - (id)extendedAccessibilityAttributeValue: (NSString*)theAttributeName {
445     return ([theAttributeName isEqualToString: NSAccessibilitySubroleAttribute] ? NSAccessibilityZoomButtonAttribute : nil);
446 }
447
448 @end
449
450
451 @implementation VLCCustomWindowFullscreenButton
452 #ifdef MAC_OS_X_VERSION_10_7
453 - (id)extendedAccessibilityAttributeValue: (NSString*)theAttributeName {
454     return ([theAttributeName isEqualToString: NSAccessibilitySubroleAttribute] ? NSAccessibilityFullScreenButtonAttribute : nil);
455 }
456 #endif
457
458 @end
459
460
461 @implementation VLCWindowTitleTextField
462
463 - (void)dealloc
464 {
465     if (contextMenu)
466         [contextMenu release];
467
468     [super dealloc];
469 }
470
471 - (void)showRightClickMenuWithEvent:(NSEvent *)o_event
472 {
473     if (contextMenu)
474         [contextMenu release];
475
476     NSURL * representedURL = [[self window] representedURL];
477     if (! representedURL)
478         return;
479
480     NSArray * pathComponents;
481     pathComponents = [representedURL pathComponents];
482
483     if (!pathComponents)
484         return;
485
486     contextMenu = [[NSMenu alloc] initWithTitle: [[NSFileManager defaultManager] displayNameAtPath: [representedURL path]]];
487
488     NSUInteger count = [pathComponents count];
489     NSImage * icon;
490     NSMenuItem * currentItem;
491     NSMutableString * currentPath;
492     NSSize iconSize = NSMakeSize(16., 16.);
493     for (NSUInteger i = count - 1; i > 0; i--) {
494         currentPath = [NSMutableString stringWithCapacity:1024];
495         for (NSUInteger y = 0; y < i; y++)
496             [currentPath appendFormat: @"/%@", [pathComponents objectAtIndex:y + 1]];
497
498         [contextMenu addItemWithTitle: [[NSFileManager defaultManager] displayNameAtPath: currentPath] action:@selector(revealInFinder:) keyEquivalent:@""];
499         currentItem = [contextMenu itemAtIndex:[contextMenu numberOfItems] - 1];
500         [currentItem setTarget: self];
501
502         icon = [[NSWorkspace sharedWorkspace] iconForFile:currentPath];
503         [icon setSize: iconSize];
504         [currentItem setImage: icon];
505     }
506
507     if ([[pathComponents objectAtIndex:1] isEqualToString:@"Volumes"]) {
508         /* we don't want to show the Volumes item, since the Cocoa does it neither */
509         currentItem = [contextMenu itemWithTitle:[[NSFileManager defaultManager] displayNameAtPath: @"/Volumes"]];
510         if (currentItem)
511             [contextMenu removeItem: currentItem];
512     } else {
513         /* we're on the boot drive, so add it since it isn't part of the components */
514         [contextMenu addItemWithTitle: [[NSFileManager defaultManager] displayNameAtPath:@"/"] action:@selector(revealInFinder:) keyEquivalent:@""];
515         currentItem = [contextMenu itemAtIndex: [contextMenu numberOfItems] - 1];
516         icon = [[NSWorkspace sharedWorkspace] iconForFile:@"/"];
517         [icon setSize: iconSize];
518         [currentItem setImage: icon];
519         [currentItem setTarget: self];
520     }
521
522     /* add the computer item */
523     [contextMenu addItemWithTitle: [(NSString*)SCDynamicStoreCopyComputerName(NULL, NULL) autorelease] action:@selector(revealInFinder:) keyEquivalent:@""];
524     currentItem = [contextMenu itemAtIndex: [contextMenu numberOfItems] - 1];
525     icon = [NSImage imageNamed: NSImageNameComputer];
526     [icon setSize: iconSize];
527     [currentItem setImage: icon];
528     [currentItem setTarget: self];
529
530     [NSMenu popUpContextMenu: contextMenu withEvent: o_event forView: [self superview]];
531 }
532
533 - (IBAction)revealInFinder:(id)sender
534 {
535     NSUInteger count = [contextMenu numberOfItems];
536     NSUInteger selectedItem = [contextMenu indexOfItem: sender];
537
538     if (selectedItem == count - 1) { // the fake computer item
539         [[NSWorkspace sharedWorkspace] selectFile: @"/" inFileViewerRootedAtPath: @""];
540         return;
541     }
542
543     NSURL * representedURL = [[self window] representedURL];
544     if (! representedURL)
545         return;
546
547     if (selectedItem == 0) { // the actual file, let's save time
548         [[NSWorkspace sharedWorkspace] selectFile: [representedURL path] inFileViewerRootedAtPath: [representedURL path]];
549         return;
550     }
551
552     NSArray * pathComponents;
553     pathComponents = [representedURL pathComponents];
554     if (!pathComponents)
555         return;
556
557     NSMutableString * currentPath;
558     currentPath = [NSMutableString stringWithCapacity:1024];
559     selectedItem = count - selectedItem;
560
561     /* fix for non-startup volumes */
562     if ([[pathComponents objectAtIndex:1] isEqualToString:@"Volumes"])
563         selectedItem += 1;
564
565     for (NSUInteger y = 1; y < selectedItem; y++)
566         [currentPath appendFormat: @"/%@", [pathComponents objectAtIndex:y]];
567
568     [[NSWorkspace sharedWorkspace] selectFile: currentPath inFileViewerRootedAtPath: currentPath];
569 }
570
571 - (void)rightMouseDown:(NSEvent *)o_event
572 {
573     if ([o_event type] == NSRightMouseDown)
574         [self showRightClickMenuWithEvent:o_event];
575
576     [super mouseDown: o_event];
577 }
578
579 @end