ftp.nice.ch/Attic/openStep/tools/workspace/TheShelf.0.3.3.sd.tgz#/TheShelf.0.3.3.sd/Source/IconViewShelf.bproj/TSIconViewShelfItem.m

This is TSIconViewShelfItem.m in view mode; [Download] [Up]

/* TSIconViewShelfItem.m created by tsengel on Fri 15-Aug-1997 */

#import "TSIconViewShelfItem.h"
#import "File.h"

@implementation TSIconViewShelfItem

- (id)initWithContentsOfFile:(NSString *)aString
{
    self = [super initWithContentsOfFile:aString];
    if( !self) return nil;

    // <<HACK>> evil...

    [NSBundle loadNibNamed:@"IconViewShelf" owner:self];

    [view setClassToHold:@"File"];
    [view addListener:[File class]];
    [view setTarget:self];
    [view setAction:@selector(selectShelfEntry:)];
    [view setDoubleAction:@selector(openShelfEntry:)];

    // We will add ourself as a listener so that we find out whne things change on the shelf. 

    [view addListener:self];

    if( !aString )
        [[view cellAtRow:0 column:0] setDelegate:[File fileForPath:NSHomeDirectory()]];

    return self;
}

- (void)revert:(id)sender
{
    [super revert:sender];

    if( !contentLoaded )
    {
        // Ok...now this is evil mean cheating... actually the problem is taht we fill the matrix before it has een resized
        // to the full windows size. This causes some trouble if the matrix has not enough elemets to fill in.
        // The currentl "fix" is the make the matrix quite large in the NIB... but this needs
        // a real fix.
        // E.g. like catching the"DiSwapIn" notification etc.

        [self updateShelfContent];
        contentLoaded = YES;
    }
}

- (void)updateShelfContent
/*"
   Takes the set path and tries to put the content into the shelf matrix...which is our view
"*/
{
    int		columns, rows;
    id  contentDict = [NSDictionary dictionaryWithContentsOfFile:[[self path] stringByAppendingPathComponent:@"Info.plist"]];
    id	itemEnum = [[contentDict objectForKey:@"Files"] objectEnumerator];
    id 	nextFilePath;
    id	aFile;
    id	aCell;

    for( rows = 0; rows<[view numberOfRows]; rows++ )
    {
        for( columns = 0; columns<[view numberOfColumns]; columns++ )
        {
            nextFilePath = [itemEnum nextObject];

            if( nextFilePath && ![nextFilePath isEqual:@""] )
            {	
                // We will make loaded items "sticky" becasue they are propably inteded to stay
                // on the shelf forever... command dragging will move them away.
                // THis behavior should be "adjustable" for the entire shelf via prefs or that like.

                aFile = [File fileForPath:nextFilePath];
                aCell = [view cellAtRow:rows column:columns];
                [aCell setLocked:YES];
                [aCell setDelegate:aFile];
            }
        }
    }
    // The content did change..so lets rememrb that so that we can save it...

    [self setContentDidChange:YES];
}

- (unsigned int)shelf:sender willDrag:objectToPaste from:(id <NSDraggingInfo>) source;
{
    // Just be sure we don't handle it as another click..it really is a drag operation !

    // NSLog( @"Markd the mouse drag op..." );
    _mouseDraggedAfterClick = YES;
    return NSDragOperationAll;
}

- (void)shelf:sender dragWillComplete:(id <NSDraggingInfo>) source;
{
    // Just be sure we don't handle it as another click !

    // NSLog( @"Shelf content did change due to drag.." );
    [self setContentDidChange:YES];
}

- (void)selectShelfEntry:(id)sender
{
    // Ok..this return here is evil...but single-doubleclick needs to be handled properly with a delayed perform
    // so right now this is disabled.

    _pendingClickEvent = [[NSApp currentEvent] eventNumber];

    [self performSelector:@selector(reallySelectCell:)
               withObject:[view selectedCell]
               afterDelay:0.8];
}

 - (void)reallySelectCell:aCell
 {
     // Let's check if this click is still wanted..perhaps we already
     // performed the double click or dragged some object after the first mouseDown.

    id	aPath;

    // NSLog( @"Trying to select cell...");

    if( _pendingClickEvent == -1 ) return;

    if( _mouseDraggedAfterClick )
    {
        _mouseDraggedAfterClick = NO;
        return;
    }

    // NSLog( @"Succeeded to select cell...");

    aPath = [[aCell delegate] path];
    if( [[NSUserDefaults standardUserDefaults] boolForKey:@"UseWorkspaceThreads"] )
        [NSThread detachNewThreadSelector:@selector(_detachedFileSelect:)
                                 toTarget:self
                               withObject:aPath];
    else
        [self performSelector:@selector(_detachedFileSelect:)
                   withObject:aPath
                   afterDelay:0.5];
 }

- (void)_detachedFileSelect:(id)thePath
{
    // The subpool is needed if we are a new thread...

    id		threadPool = [NSAutoreleasePool new];

    // <<HACK>> This is "bad!!!" since this "/" causes the workspace to open yet
    // another browser window. But the @"" does not work and causes an exception on 4.2...bad..

    [NSApp deactivate];
    [[NSWorkspace sharedWorkspace] selectFile:thePath
                     inFileViewerRootedAtPath:@"/"];
    [threadPool release];
}

- (void)openShelfEntry:(id)sender
{
    id	cell;
    id	aPath;

    // Sicne this event is handled now..reset the marker.

    _pendingClickEvent = -1;
    cell = [view selectedCell];
    aPath = [[cell delegate] path];

    if( [[aPath pathExtension] isEqual:@"app"] )
    {
        if( [[NSUserDefaults standardUserDefaults] boolForKey:@"UseWorkspaceThreads"] )
            [NSThread detachNewThreadSelector:@selector(_detachedAppLaunch:)
                                     toTarget:self
                                   withObject:aPath];
        else
            [self performSelector:@selector(_detachedAppLaunch:)
                       withObject:aPath
                       afterDelay:0.5];
    }
    else
    {
        if( [[NSUserDefaults standardUserDefaults] boolForKey:@"UseWorkspaceThreads"] )
            [NSThread detachNewThreadSelector:@selector(_detachedFileOpen:)
                                     toTarget:self
                                   withObject:aPath];
        else
            [self performSelector:@selector(_detachedFileOpen:)
                       withObject:aPath
                       afterDelay:0.5];
    }
}

- (void)_detachedAppLaunch:(id)thePath
{
    // The subpool is needed if we are a new thread...

    id		threadPool = [NSAutoreleasePool new];
    [NSApp deactivate];
    [[NSWorkspace sharedWorkspace] launchApplication:thePath];

    // Using the launchApplication:thePath showIcon:YES autolaunch:NO method does not work properly ???

    [threadPool release];
}

- (void)_detachedFileOpen:(id)thePath
{
    // The subpool is needed if we are a new thread...

    id		threadPool = [NSAutoreleasePool new];
    [NSApp deactivate];
    [[NSWorkspace sharedWorkspace] openFile:thePath];
    [threadPool release];
}

- (void)save
{
    id		basePath = [self path];
    id		ourFileArray = [NSMutableArray new];
    id		ourFileDict = [NSMutableDictionary new];

    int		rows, columns;

    id		aPath;

    [super save];

    // Now save all the file refs.

    for( rows = 0; rows<[view numberOfRows]; rows++ )
    {
        for( columns = 0; columns<[view numberOfColumns]; columns++ )
        {
            aPath = [[[view cellAtRow:rows column:columns] delegate] path];
            if( !aPath ) aPath = @"";
            [ourFileArray addObject:aPath];
        }
    }
    basePath = [basePath stringByAppendingPathComponent:@"Info.plist"];

    [ourFileDict setObject:@"IconViewShelf" forKey:@"ShelfType"];
    [ourFileDict setObject:ourFileArray forKey:@"Files"];
    [ourFileDict writeToFile:basePath atomically:YES];
}

@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.