/* RecyclerIcon.m * * Copyright (C) 2004 Free Software Foundation, Inc. * * Author: Enrico Sersale * Date: June 2004 * * This file is part of the GNUstep Recycler application * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. */ #include #include #include "RecyclerIcon.h" #include "Recycler.h" #include "GNUstep.h" #define ISIZE 48 static id desktopApp = nil; @implementation RecyclerIcon - (void)dealloc { TEST_RELEASE (trashFullIcon); [super dealloc]; } + (void)initialize { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *appname = [defaults stringForKey: @"DesktopApplicationName"]; NSString *selname = [defaults stringForKey: @"DesktopApplicationSelName"]; if (appname && selname) { Class desktopAppClass = [[NSBundle mainBundle] principalClass]; SEL sel = NSSelectorFromString(selname); desktopApp = [desktopAppClass performSelector: sel]; } } - (id)initWithRecyclerNode:(FSNode *)anode { self = [super initForNode: anode nodeInfoType: FSNInfoNameType extendedType: nil iconSize: ISIZE iconPosition: NSImageOnly labelFont: [NSFont systemFontOfSize: 12] textColor: [NSColor controlTextColor] gridIndex: 0 dndSource: NO acceptDnd: YES slideBack: NO]; if (self) { NSArray *subNodes = [node subNodes]; int count = [subNodes count]; int i; ASSIGN (icon, [fsnodeRep trashIconOfSize: icnBounds.size.width]); ASSIGN (trashFullIcon, [fsnodeRep trashFullIconOfSize: icnBounds.size.width]); for (i = 0; i < [subNodes count]; i++) { if ([[subNodes objectAtIndex: i] isReserved]) { count--; } } trashFull = (count != 0); [self registerForDraggedTypes: [NSArray arrayWithObject: NSFilenamesPboardType]]; ws = [NSWorkspace sharedWorkspace]; } return self; } - (void)setTrashFull:(BOOL)value { trashFull = value; [self setNeedsDisplay: YES]; } - (void)mouseDown:(NSEvent *)theEvent { if ([theEvent clickCount] == 1) { if ([(Recycler *)desktopApp isDocked] == NO) { NSWindow *win = [self window]; NSPoint lastLocation = [theEvent locationInWindow]; NSPoint location; NSDate *theDistantFuture = [NSDate distantFuture]; BOOL done = NO; unsigned eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask | NSPeriodicMask | NSOtherMouseUpMask | NSRightMouseUpMask; [NSEvent startPeriodicEventsAfterDelay: 0.02 withPeriod: 0.02]; while (done == NO) { theEvent = [NSApp nextEventMatchingMask: eventMask untilDate: theDistantFuture inMode: NSEventTrackingRunLoopMode dequeue: YES]; switch ([theEvent type]) { case NSRightMouseUp: case NSOtherMouseUp: case NSLeftMouseUp: done = YES; break; case NSPeriodic: location = [win mouseLocationOutsideOfEventStream]; if (NSEqualPoints(location, lastLocation) == NO) { NSPoint origin = [win frame].origin; origin.x += (location.x - lastLocation.x); origin.y += (location.y - lastLocation.y); [win setFrameOrigin: origin]; } break; default: break; } } [NSEvent stopPeriodicEvents]; } } else { id workspaceApp = [desktopApp workspaceApplication]; if (workspaceApp) { NSString *path = [node path]; [workspaceApp selectFile: path inFileViewerRootedAtPath: path]; } } } - (void)drawRect:(NSRect)rect { if (trashFull) { [trashFullIcon compositeToPoint: icnPoint operation: NSCompositeSourceOver]; } else { [icon compositeToPoint: icnPoint operation: NSCompositeSourceOver]; } } @end @implementation RecyclerIcon (DraggingDestination) - (NSDragOperation)draggingEntered:(id )sender { NSPasteboard *pb = [sender draggingPasteboard]; if ([[pb types] containsObject: NSFilenamesPboardType]) { isDragTarget = YES; return NSDragOperationAll; } isDragTarget = NO; return NSDragOperationNone; } - (NSDragOperation)draggingUpdated:(id )sender { NSPasteboard *pb = [sender draggingPasteboard]; if ([[pb types] containsObject: NSFilenamesPboardType]) { isDragTarget = YES; [self select]; return NSDragOperationAll; } isDragTarget = NO; return NSDragOperationNone; } - (void)draggingExited:(id )sender { isDragTarget = NO; } - (BOOL)prepareForDragOperation:(id )sender { return isDragTarget; } - (BOOL)performDragOperation:(id )sender { return isDragTarget; } - (void)concludeDragOperation:(id )sender { NSPasteboard *pb = [sender draggingPasteboard]; [self unselect]; isDragTarget = NO; if ([[pb types] containsObject: NSFilenamesPboardType]) { NSArray *sourcePaths = [pb propertyListForType: NSFilenamesPboardType]; NSString *source = [[sourcePaths objectAtIndex: 0] stringByDeletingLastPathComponent]; if ([[NSFileManager defaultManager] isWritableFileAtPath: source]) { // NSArray *vpaths = [ws mountedLocalVolumePaths]; NSMutableArray *files = [NSMutableArray array]; // NSMutableArray *umountPaths = [NSMutableArray array]; int i; for (i = 0; i < [sourcePaths count]; i++) { NSString *srcpath = [sourcePaths objectAtIndex: i]; FSNode *nd = [FSNode nodeWithPath: srcpath]; if ([nd isMountPoint] == NO) { [files addObject: [srcpath lastPathComponent]]; } // if ([vpaths containsObject: srcpath]) { // [umountPaths addObject: srcpath]; // } else { // [files addObject: [srcpath lastPathComponent]]; // } } // for (i = 0; i < [umountPaths count]; i++) { // [ws unmountAndEjectDeviceAtPath: [umountPaths objectAtIndex: i]]; // } if ([files count]) { if ([[NSFileManager defaultManager] isWritableFileAtPath: source] == NO) { NSString *err = NSLocalizedString(@"Error", @""); NSString *msg = NSLocalizedString(@"You do not have write permission\nfor", @""); NSString *buttstr = NSLocalizedString(@"Continue", @""); NSRunAlertPanel(err, [NSString stringWithFormat: @"%@ \"%@\"!\n", msg, source], buttstr, nil, nil); return; } [desktopApp performFileOperation: @"NSWorkspaceRecycleOperation" source: source destination: [node path] files: files]; } } } } @end