/* Copyright (C) 2002-2003, Jeffrey D. Argast. The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. Permission is hereby granted to use, copy, modify, and distribute this software or portions thereof for any purpose, without fee, subject to these conditions: (1) If any part of the source code is distributed, then this statement must be included, with this copyright and no-warranty notice unaltered. (2) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. */ #import "DepotController.h" #import "PerforceActionDepots.h" #import "OutlineItem.h" #import "PerforceDirectory.h" #import "PerforceDepot.h" #import "RevisionsController.h" #import "TextFieldDialogController.h" #import "PendingChangesController.h" #import "AppDefaults.h" #import "MessageDefs.h" #import "AppUtils.h" #import "PerforceActionAdd.h" @implementation DepotController - (void) appFinishedLaunching { // minor HACK: see comment down below fAwake = YES; [fOutlineView reloadData]; } - (void) dealloc { NSNotificationCenter* nCenter = [NSNotificationCenter defaultCenter]; [nCenter removeObserver:self]; [fDepots release]; [fTextFieldDialogController release]; [super dealloc]; } /* Asynchronous depot building */ - (void) resultFromPerforceDepots: (PerforceActionDepots*) action { if ( [action wasSuccess] ) { [fDepots addObjectsFromArray:[action getDepots]]; [fOutlineView reloadData]; } } /* End Async */ - (void) buildDepots { fDepots = [[NSMutableArray alloc] init]; [PerforceActionDepots defaultRunFor:self selector:@selector(resultFromPerforceDepots:)]; } - (void) awakeFromNib { NSTableColumn *tableColumn = nil; NSBrowserCell *browserCell = nil; tableColumn = [fOutlineView tableColumnWithIdentifier:@"1"]; browserCell = [[[NSBrowserCell alloc] init] autorelease]; [browserCell setEditable:NO]; [browserCell setLeaf:YES]; [tableColumn setDataCell:browserCell]; { NSNotificationCenter* nCenter = [NSNotificationCenter defaultCenter]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kDefaultsUserChanged object:nil]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kDefaultsClientChanged object:nil]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kDefaultsPortChanged object:nil]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kDefaultsShowEntireDepotChanged object:nil]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kDefaultsShowDeletedFilesChanged object:nil]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kGlobalSyncComplete object:nil]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kRefreshAllViews object:nil]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kActionSubmitSucceeded object:nil]; [nCenter addObserver:self selector:@selector(handleDefaultsChanged:) name:kDefaultsConfigurationsChanged object:nil]; [nCenter addObserver:self selector:@selector(handleDepotChildChanged:) name:kDepotControllerChildChanged object:nil]; } [fOutlineView setDoubleAction:@selector(doubleAction:)]; //[fOutlineView setAction:@selector(doubleAction:)]; [fOutlineView setTarget:self]; [fOutlineView registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]]; } - (void) handleDepotChildChanged: (NSNotification*) notification { [fOutlineView reloadData]; } - (void) handleDefaultsChanged: (NSNotification*) notification { [self refreshData]; } - (void) doubleAction: (id) sender { /* NSWindow* window = [fOutlineView window]; NSTableHeaderView* headerView = [fOutlineView headerView]; NSPoint clickPoint = [NSEvent mouseLocation]; clickPoint = [window convertScreenToBase:clickPoint]; clickPoint = [headerView convertPoint:clickPoint fromView:nil]; int colIdx = [headerView columnAtPoint:clickPoint]; if ( colIdx < 0 ) { [self doubleClick:sender]; } */ NSLog (@"double action"); } /* ** The outline view datasource protocol */ // outlineView:child:ofItem: - (id) outlineView: (NSOutlineView *) outlineView child: (int) index ofItem: (id) item { if ( item ) { return [item getChildAtIndex: index]; } if ( !fDepots ) { [self buildDepots]; } return [fDepots objectAtIndex: index]; } // outlineView:isItemExpandable: - (BOOL) outlineView: (NSOutlineView *) outlineView isItemExpandable: (id) item { if ( item ) { return [item hasChildren]; } return YES; } // outlineView:numberOfChildrenOfItem: - (int) outlineView: (NSOutlineView*) outlineView numberOfChildrenOfItem: (id) item { // minor HACK: we don't want to do any of this until the contoller // is awoken from nib. In other words, this method gets called // before all of the contollers are hooked up with their respective // views. If we don't have this check then the initial commands are // not shown in the NSTextView console window that is connected to // the ConsoleController if ( !fAwake ) return 0; if ( item ) { return [item getNumberOfChildren]; } if ( !fDepots ) { [self buildDepots]; } return [fDepots count]; } // outlineView:objectValueForTableColumn:byItem: - (id) outlineView: (NSOutlineView *) outlineView objectValueForTableColumn: (NSTableColumn *) tableColumn byItem: (id) item { return [item getCellText]; } /* ** outline view delegate methods */ - (void) outlineView: (NSOutlineView *) olv willDisplayCell: (NSCell *) cell forTableColumn: (NSTableColumn *) tableColumn item: (id) item { if ( [[tableColumn identifier] isEqualToString:@"1"] ) { [(NSBrowserCell*)cell setImage:[item getCellImage]]; } } // // getSelectedItem // - (id) getSelectedItem { int rowIdx; id item = nil; rowIdx = [fOutlineView selectedRow]; if ( rowIdx >= 0 ) { item = [fOutlineView itemAtRow:rowIdx]; } return item; } // // // - (void) refreshData { if ( fDepots ) { [fDepots release]; fDepots = nil; [fOutlineView reloadData]; } } // // showRevisionHistory // - (IBAction) showRevisionHistory: (id) sender { id item = [self getSelectedItem]; if ( item ) { [item showRevisionHistory]; } } - (IBAction) syncToHead: (id) sender { id item = [self getSelectedItem]; if ( item ) { [item syncToHead]; } } - (IBAction) syncToNone: (id) sender { id item = [self getSelectedItem]; if ( item ) { [item syncToNone]; } } - (void) syncUsing: (NSString*) dialogTitle withSep: (NSString*) separator { id item = [self getSelectedItem]; if ( item ) { if ( !fTextFieldDialogController ) { fTextFieldDialogController = [[TextFieldDialogController alloc] init]; } if ( [fTextFieldDialogController showDialog:dialogTitle] ) { NSMutableString* rev = [NSMutableString stringWithString:separator]; NSString* revValue = [fTextFieldDialogController getData]; if ( [revValue length] > 0 ) { [rev appendString:revValue]; [item syncTo:rev]; if ( [fOutlineView isItemExpanded:item] ) { [fOutlineView collapseItem:item]; } } } } } - (IBAction) syncToRevision: (id) sender { [self syncUsing:@"File Revision Number" withSep:@"#"]; } - (IBAction) syncToChangelist: (id) sender { [self syncUsing:@"Changelist Number" withSep:@"@"]; } - (IBAction) syncToLabel: (id) sender { [self syncUsing:@"Label Name" withSep:@"@"]; } - (IBAction) edit: (id) sender { id item = [self getSelectedItem]; if ( item ) { [item edit]; } } - (IBAction) delete: (id) sender { id item = [self getSelectedItem]; if ( item ) { [item delete]; } } - (IBAction) revert: (id) sender { id item = [self getSelectedItem]; if ( item ) { [item revert]; } } - (IBAction) diff: (id) sender { id item = [self getSelectedItem]; if ( item ) { [item diff]; } } - (IBAction) viewInEditor: (id) sender { id item = [self getSelectedItem]; if ( item ) { [item viewInEditor]; } } - (IBAction) clientViewOfDepot: (id) sender { [[AppDefaults defaultAppDefaults] setShowEntireDepot:NO]; } - (IBAction) entireViewOfDepot: (id) sender { [[AppDefaults defaultAppDefaults] setShowEntireDepot:YES]; } - (IBAction) showDeletedFiles: (id) sender { [[AppDefaults defaultAppDefaults] setShowDeletedFiles:YES]; } - (IBAction) hideDeletedFiles: (id) sender { [[AppDefaults defaultAppDefaults] setShowDeletedFiles:NO]; } - (BOOL)outlineView:(NSOutlineView *)olv writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pb { if ( [items count] > 1 ) return NO; id item = [items objectAtIndex:0]; WriteStringToPasteboard ([item getPasteboardData], pb); return YES; } - (NSDragOperation)outlineView:(NSOutlineView*)olv validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(int)index { [olv setDropItem:nil dropChildIndex:NSOutlineViewDropOnItemIndex]; return NSDragOperationCopy; } - (BOOL)outlineView:(NSOutlineView*)olv acceptDrop:(id )info item:(id)item childIndex:(int)index { NSPasteboard* pb = [info draggingPasteboard]; NSArray* value = nil; NSString* type; type = [pb availableTypeFromArray: [NSArray arrayWithObject:NSFilenamesPboardType]]; if ( type ) { value = [pb propertyListForType:NSFilenamesPboardType]; if ( value ) { NSFileManager* fileManager = [NSFileManager defaultManager]; NSMutableArray* filesToAdd = [[[NSMutableArray alloc] init] autorelease]; NSMutableString* pathPrefix = [[[NSMutableString alloc] init] autorelease]; int num = [value count]; int n; for ( n = 0; n < num; n++) { NSString* fileName; NSString* valueItem = [value objectAtIndex:n]; BOOL isDir = NO; [fileManager fileExistsAtPath:valueItem isDirectory:&isDir]; if ( !isDir ) { [filesToAdd addObject:valueItem]; } else { [pathPrefix setString:valueItem]; [pathPrefix appendString:@"/"]; NSDirectoryEnumerator* dirEnumerator = [fileManager enumeratorAtPath:valueItem]; while ( fileName = [dirEnumerator nextObject] ) { NSString* actualFileName = [fileName lastPathComponent]; // skip files that start with . if ( [actualFileName characterAtIndex:0] != '.' ) { NSMutableString* fullPath = [[NSMutableString alloc] initWithString:pathPrefix]; [fullPath appendString:fileName]; [filesToAdd addObject:fullPath]; [fullPath release]; } } } } if ( [filesToAdd count] > 0 ) { [PerforceActionAdd defaultAddFiles:filesToAdd]; return YES; } } } return NO; } @end