//
// ColumnViewController.m
// Perforce
//
// Created by Adam Czubernat on 12.05.2013.
// Copyright (c) 2013 Perforce Software, Inc. All rights reserved.
//
#import "ColumnViewController.h"
#import "ColumnCell.h"
#import "PSBrowser.h"
#import "ColumnViewDetails.h"
#import "ColumnViewHeader.h"
@interface ColumnViewController () <PSBrowserDelegate, ColumnViewHeaderDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate, NSMenuDelegate> {
__weak IBOutlet PSBrowser *browserView;
IBOutlet NSView *loadingOverlay;
__weak IBOutlet NSProgressIndicator *loadingOverlayIndicator;
NSProgressIndicator *progressIndicator;
PSView *warningIndicator;
id loadingItem;
// Selected details
P4Item *detailsItem;
// Selected header
P4Item *headerItem;
ColumnViewHeader *headerController;
NSMutableArray *columnHeaders;
// Will Load
NSString *reloadPath;
NSArray *reloadSelection;
CGFloat reloadScroll;
ColumnViewHeader *reloadHeader;
// QuickLook
QLPreviewPanel *quickLookPanel;
NSArray *quickLookItems;
}
- (void)clickAction;
- (void)doubleClickAction;
- (void)selectionChangedToItem:(P4Item *)item;
- (void)deselectHeader;
- (void)showLoadingOverlay;
- (void)showLoadingForItem:(P4Item *)item;
- (void)showErrorForItem:(P4Item *)item;
- (void)updateFavoritesNotification:(NSNotification *)notification;
@end
@implementation ColumnViewController
- (void)loadView {
[super loadView];
[browserView setBackgroundColor:[NSUserDefaults colorForKey:
kColorBackgroundColumnContainer]];
[browserView setCellClass:[ColumnCell class]];
[browserView setRowHeight:24.0f];
[browserView setSendsActionOnArrowKeys:YES];
[browserView setAllowsMultipleSelection:YES];
[browserView setAllowsBranchSelection:YES];
[browserView registerForDraggedTypes:@[ NSFilenamesPboardType ]];
[browserView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES];
[browserView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:NO];
[browserView setTarget:self];
[browserView setAction:@selector(clickAction)];
[browserView setDoubleAction:@selector(doubleClickAction)];
[browserView setFocusRingType:NSFocusRingTypeNone];
[(id)browserView setBorderType:NSNoBorder];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(updateFavoritesNotification:)
name:P4WorkspaceDefaultsChangedNotification
object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:P4WorkspaceDefaultsChangedNotification
object:nil];
}
#pragma mark - BrowserViewController Overrides
- (NSArray *)selectedItems {
NSMutableArray *array = [NSMutableArray array];
for (NSIndexPath *indexPath in [browserView selectionIndexPaths]) {
P4Item *item = [browserView itemAtIndexPath:indexPath];
[array addObject:item];
}
return array;
}
- (void)setRootItem:(P4Item *)item {
[super setRootItem:item];
[self deselectHeader];
[browserView loadColumnZero];
}
- (void)setWorkingItem:(P4Item *)item {
[super setWorkingItem:item];
[self selectionChangedToItem:item];
[self deselectHeader];
if (!workingItem)
return;
NSString *rootPath = rootItem.path;
NSString *relative = [workingItem.path stringByRemovingPrefix:rootPath];
[browserView loadColumnZero];
[browserView setPath:relative];
}
- (void)setSelectedIndexes:(NSIndexSet *)indexes {
[browserView selectRowIndexes:indexes inColumn:browserView.lastColumn];
[self clickAction];
}
- (void)refresh {
[browserView setNeedsDisplay];
}
- (void)willLoadPath:(NSString *)path {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showLoadingOverlay) object:nil];
[self performSelector:@selector(showLoadingOverlay) withObject:nil afterDelay:0.25f];
reloadPath = path;
if (isReloading) {
// Get scrollview position
NSScrollView *scrollView = nil;
for (NSView *subview in [browserView subviews])
if ([subview isKindOfClass:NSClassFromString(@"_NSBrowserScrollView")])
scrollView = (id)subview;
reloadScroll = [scrollView documentVisibleRect].origin.x;
reloadSelection = [[self selectedItems] valueForKey:@"path"];
reloadHeader = headerController;
}
}
- (void)showVersions:(P4Item *)item {
if (item != detailsItem) {
[browserView selectRow:[browserView clickedRow] inColumn:[browserView clickedColumn]];
[self clickAction];
}
ColumnViewDetails *details = (id)[browserView detailViewController];
[details showVersions];
}
- (void)editItemName:(P4Item *)item {
NSInteger row = [[item.parent children] indexOfObjectIdenticalTo:item];
NSIndexPath *indexPath = [browserView indexPathForColumn:[browserView lastColumn]];
indexPath = [indexPath indexPathByAddingIndex:row];
[browserView setSelectionIndexPath:indexPath];
[browserView editItemAtIndexPath:indexPath withEvent:nil select:NO];
[self selectionChangedToItem:item];
}
#pragma mark - Private
- (void)clickAction {
NSArray *selection = [self selectedItems];
if (!quickLookPanel && [QLPreviewPanel sharedPreviewPanelExists])
[[QLPreviewPanel sharedPreviewPanel] updateController];
if (quickLookPanel) {
quickLookItems = selection;
[quickLookPanel reloadData];
}
if (selection.count > 1)
return; // Don't show details for multiple items
P4Item *item = selection.lastObject ?: rootItem;
[self selectionChangedToItem:item];
// Show detail pane for files
if (item && ![item isDirectory]) {
ColumnViewDetails *detailsController;
detailsController = [[ColumnViewDetails alloc] initWithItem:item
actionDelegate:[self.view.window windowController]];
[browserView setDetailViewController:detailsController];
detailsItem = item;
}
}
- (void)doubleClickAction {
if (browserView.selectionIndexPaths.count > 1)
return; // Don't open multiple items
P4Item *item = [browserView itemAtIndexPath:browserView.selectionIndexPath];
if (!item)
return;
[self selectionChangedToItem:item];
// Perform default item action
P4ItemAction *action = [item defaultAction];
action.delegate = [self.view.window windowController];
[action performAction];
}
- (void)selectionChangedToItem:(P4Item *)item {
[self deselectHeader];
// // Auto mark as unread
// if (!item.isDirectory && item.isUpdated)
// [item markAsRead];
// Get parent if item is not expandable
P4Item *nodeItem = [item isDirectory] ? item : [item parent];
if (workingItem != nodeItem)
[super setWorkingItem:nodeItem];
[self selectionChanged:item];
}
- (void)deselectHeader {
[headerController setSelected:NO];
headerController = nil;
headerItem = nil;
}
- (void)showLoadingOverlay {
[loadingOverlay setFrame:self.view.bounds];
[self.view addSubview:loadingOverlay];
[loadingOverlayIndicator startAnimation:nil];
}
- (void)showLoadingForItem:(P4Item *)item {
[progressIndicator removeFromSuperview];
if (!item.isLoading)
return;
loadingItem = item;
if (!progressIndicator) {
progressIndicator = [[NSProgressIndicator alloc] init];
[progressIndicator setStyle:NSProgressIndicatorSpinningStyle];
[progressIndicator setIndeterminate:YES];
[progressIndicator setControlSize:NSRegularControlSize];
}
NSArray *columns = [browserView valueForKey:@"_columns"];
NSView *columnView = [columns objectAtIndex:browserView.lastColumn];
CGRect frame = columnView.frame;
frame.origin.x += (frame.size.width - 32.0f)/2.0f;
frame.origin.y += (frame.size.height - 32.0f)/2.0f;
frame.size.width = frame.size.height = 32.0f;
progressIndicator.frame = frame;
[progressIndicator setAutoresizing:NSViewAutoresizingLeftEdge];
[progressIndicator startAnimation:nil];
[columnView.superview addSubview:progressIndicator];
}
- (void)showErrorForItem:(P4Item *)item {
[warningIndicator removeFromSuperview];
if (!item.hasError)
return;
static NSImage *warningImage;
if (!warningImage)
warningImage = [NSImage imageNamed:@"Warning.png"];
NSArray *columns = [browserView valueForKey:@"_columns"];
NSView *columnView = columns.count ? [columns objectAtIndex:browserView.lastColumn] : browserView;
CGRect frame = columns.count ? columnView.frame : [browserView frameOfColumn:0];
frame.origin.x += (frame.size.width - 32.0f)/2.0f;
frame.origin.y += (frame.size.height - 32.0f)/2.0f;
frame.size.width = frame.size.height = 32.0f;
if (!warningIndicator) {
warningIndicator = [[PSView alloc] init];
warningIndicator.image = warningImage;
[warningIndicator setAutoresizing:NSViewAutoresizingLeftEdge];
}
warningIndicator.frame = frame;
[columnView.superview addSubview:warningIndicator];
}
#pragma mark - P4WorkspaceDefaults Notification
- (void)updateFavoritesNotification:(NSNotification *)notification {
if ([detailsItem isDirectory])
[self itemDidLoad:detailsItem];
}
#pragma mark - NSBrowser delegate
- (id)rootItemForBrowser:(NSBrowser *)browser {
return rootItem;
}
- (NSInteger)browser:(NSBrowser *)browser numberOfChildrenOfItem:(P4Item *)item {
return item.children.count;
}
- (id)browser:(NSBrowser *)browser child:(NSInteger)index ofItem:(P4Item *)item {
NSArray *children = item.children;
if (index < children.count)
return [children objectAtIndex:index];
return nil;
}
- (BOOL)browser:(NSBrowser *)browser isLeafItem:(P4Item *)item {
return !item.isDirectory;
}
- (id)browser:(NSBrowser *)browser objectValueForItem:(P4Item *)item {
return item.name;
}
- (void)browser:(NSBrowser *)sender willDisplayCell:(ColumnCell *)cell atRow:(NSInteger)row column:(NSInteger)column {;
P4Item *item = [browserView itemAtRow:row inColumn:column];
cell.image = item.icon;
cell.selectedImage = item.iconHighlighted;
[cell setLeaf:![item isDirectory]];
cell.unread = item.isUnread;
cell.tag = [self hasFilteredTagsForItem:item];
static NSColor *shelvedColor;
if (!shelvedColor)
shelvedColor = [NSColor colorWithHexString:@"#f2c600"];
cell.overlayColor = item.isShelved ? shelvedColor : item.overlay;
}
- (void)browser:(NSBrowser *)browser didChangeLastColumn:(NSInteger)oldLastColumn toColumn:(NSInteger)column {
if (column < 0)
return;
P4Item *item = [browser parentForItemsInColumn:column];
[self showLoadingForItem:item];
[self showErrorForItem:item];
}
- (NSViewController *)browser:(NSBrowser *)browser headerViewControllerForItem:(P4Item *)item {
if (item == rootItem)
return nil;
ColumnViewHeader *header = [[ColumnViewHeader alloc] init];
header.delegate = self;
if (headerItem == item) { // New header should be selected
headerController = header;
header.selected = YES;
}
// Get column number from parent count
NSInteger column = 0;
for (P4Item *parent = item.parent; parent; column++, parent = parent.parent);
if (!columnHeaders)
columnHeaders = [NSMutableArray array];
if (column-1 < columnHeaders.count)
[columnHeaders replaceObjectAtIndex:column-1 withObject:header];
else
[columnHeaders addObject:header];
return header;
}
- (BOOL)browser:(NSBrowser *)browser shouldEditItem:(P4Item *)item {
return [item isEditable];
}
- (void)browser:(NSBrowser *)browser setObjectValue:(NSString *)value forItem:(P4Item *)item {
[self renameItem:item name:value];
}
#pragma mark Keyboard support
- (void)browserDidReceiveCommandDeleteKey:(NSBrowser *)browser {
if (![browserView selectionIndexPath])
return;
NSArray *selectedItems = [self selectedItems];
[rootItem performAction:@selector(deleteItems:)
items:selectedItems
delegate:[self.view.window windowController]];
}
- (void)browserDidReceiveSpacebarKey:(NSBrowser *)browser {
QLPreviewPanel *previewPanel = [QLPreviewPanel sharedPreviewPanel];
// Dismiss if visible
if ([QLPreviewPanel sharedPreviewPanelExists] && [previewPanel isVisible]) {
[previewPanel orderOut:nil];
return;
}
if (![browserView selectionIndexPath])
return;
[previewPanel updateController];
[previewPanel makeKeyAndOrderFront:nil];
}
#pragma mark - Drag and Drop support
- (BOOL)browser:(NSBrowser *)browser writeRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column toPasteboard:(NSPasteboard *)pasteboard {
NSMutableArray *filenames = [NSMutableArray array];
[rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
P4Item *item = [browser itemAtRow:idx inColumn:column];
if ([item isEditable])
[filenames addObject:item.localPath];
}];
[pasteboard declareTypes:@[NSFilenamesPboardType] owner:self];
[pasteboard setPropertyList:filenames forType:NSFilenamesPboardType];
return YES;
}
- (BOOL)browser:(NSBrowser *)browser canDragRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column withEvent:(NSEvent *)event {
NSMutableArray *items = [NSMutableArray array];
[rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
P4Item *item = [browser itemAtRow:idx inColumn:column];
if ([item isEditable])
[items addObject:item];
}];
return items.count;
}
- (NSImage *)browser:(NSBrowser *)browser draggingImageForRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column withEvent:(NSEvent *)event offset:(NSPointPointer)dragImageOffset {
NSImage *result = [browser draggingImageForRowsWithIndexes:rowIndexes inColumn:column withEvent:event offset:dragImageOffset];
PSLog(@"");
[result lockFocus];
if (rowIndexes.count > 1) {
NSPoint mouse = (CGPoint) {
result.size.width * 0.5f - dragImageOffset->x,
result.size.height * 0.5f - dragImageOffset->y,
};
NSShadow *shadow = [[NSShadow alloc] init];
[shadow setShadowOffset:NSMakeSize(0.5, 0.5)];
[shadow setShadowBlurRadius:5.0];
[shadow setShadowColor:[NSColor blackColor]];
NSDictionary *attrs = @{
NSShadowAttributeName : shadow,
NSForegroundColorAttributeName : [NSColor whiteColor],
};
NSInteger cornerSize = 10.0f;
NSGradient *gradient = [[NSGradient alloc]
initWithStartingColor:[NSColor colorWithHexString:@"#FCC"]
endingColor:[NSColor redColor]];
NSBezierPath *bezier = [NSBezierPath
bezierPathWithRoundedRect:(CGRect) { mouse, {20.0f, 20.0f} }
xRadius:cornerSize
yRadius:cornerSize];
[gradient drawInBezierPath:bezier angle:90.0f];
BOOL copy = [[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask;
NSString *str = [NSString stringWithFormat:@"%@%ld", copy ? @"+": @"", rowIndexes.count];
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:str attributes:attrs];
[attrStr drawAtPoint:(CGPoint) {
mouse.x + (20.0f - attrStr.size.width) / 2.0f,
mouse.y + (20.0f - attrStr.size.height) / 2.0f + 1,
}];
[result unlockFocus];
}
return result;
}
- (NSDragOperation)browser:(NSBrowser *)browser validateDrop:(id <NSDraggingInfo>)info proposedRow:(NSInteger *)row column:(NSInteger *)column dropOperation:(NSBrowserDropOperation *)dropOperation {
NSDragOperation operation = NSDragOperationEvery;
// Check if option key is pressed
if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask)
operation = NSDragOperationCopy;
// Accept only file types
if ([[[info draggingPasteboard] types] indexOfObject:NSFilenamesPboardType] == -1)
return NSDragOperationNone;
if (*column == -1)
return NSDragOperationNone;
P4Item *parent = [browserView parentForItemsInColumn:*column];
NSInteger rows = parent.children.count;
if (*dropOperation == NSBrowserDropAbove) {
if (*row < rows) {
*row = -1;
return NSDragOperationNone;
}
*row = -1;
return operation;
}
P4Item *target = [browserView itemAtRow:*row inColumn:*column];
if (![target isDirectory] || ![target isEditable]) {
// Can't drop onto a file. Retarget to the column
*row = -1;
*dropOperation = NSBrowserDropOn;
if (![parent isEditable])
return NSDragOperationNone;
}
return operation;
}
- (BOOL)browser:(NSBrowser *)browser acceptDrop:(id <NSDraggingInfo>)info atRow:(NSInteger)row column:(NSInteger)column dropOperation:(NSBrowserDropOperation)dropOperation {
// Check if option key is pressed
BOOL copy = info.draggingSourceOperationMask == NSDragOperationCopy;
NSArray *paths = [info.draggingPasteboard propertyListForType:NSFilenamesPboardType];
if (column == -1 || !paths.count)
return NO;
// Find the target folder
P4Item *target = nil;
if (row == -1)
target = [browser parentForItemsInColumn:column];
else
target = [browser itemAtRow:row inColumn:column];
return [self insertFiles:paths intoItem:target copy:copy];
}
#pragma mark - ColumnHeader delegate
- (void)columnViewHeader:(ColumnViewHeader *)header clickedWithItem:(P4Item *)item {
[[browserView window] makeFirstResponder:browserView]; // Conclude editing
// Get column number from parent count
NSInteger column = 0;
for (P4Item *parent = item.parent; parent; column++, parent = parent.parent);
if (browserView.lastColumn == column) {
// Change is inside current parent. Select parent row in previous column
NSUInteger row = [browserView selectedRowInColumn:column-1];
// Store item for selection because new header will be created
headerItem = item;
[browserView selectRow:row inColumn:column-1];
[self selectionChanged:item];
} else {
[[browserView animator] setLastColumn:column]; // Trim selection to header's parent
[self selectionChangedToItem:item];
// Store selected header as selected
headerItem = item;
headerController = header;
}
// Stop indicator
if (item == loadingItem) {
loadingItem = nil;
[progressIndicator stopAnimation:nil];
[progressIndicator removeFromSuperview];
}
// Show details for header's folder
ColumnViewDetails *detailsController;
detailsController = [[ColumnViewDetails alloc]
initWithItem:item
actionDelegate:[self.view.window windowController]];
[browserView setDetailViewController:detailsController];
detailsItem = item;
}
#pragma mark - P4Item delegate
- (void)itemDidLoad:(P4Item *)item {
[super itemDidLoad:item];
// Remove loading indicator
if (item == loadingItem) {
loadingItem = nil;
[progressIndicator stopAnimation:nil];
[progressIndicator removeFromSuperview];
}
if (isLoading) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showLoadingOverlay) object:nil];
[loadingOverlay removeFromSuperview];
P4Item *item = [rootItem cachedItemForPath:reloadPath];
if (!item) {
[self failWithError:
[NSError errorWithFormat:@"Couldn't find file at %@", reloadPath]];
isLoading = isReloading = NO;
return;
}
isLoading = NO;
[self setSelectedItems:@[ item ]];
if (isReloading) {
isReloading = NO;
// Find items for previously selected paths
NSInteger idx = 0;
NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
for (P4Item *child in item.children) {
if ([reloadSelection containsObject:child.path])
[indexes addIndex:idx];
idx++;
}
[browserView selectRowIndexes:indexes inColumn:browserView.lastColumn];
// Set scrollview's position
NSScrollView *scrollView = nil;
for (NSView *subview in [browserView subviews])
if ([subview isKindOfClass:NSClassFromString(@"_NSBrowserScrollView")])
scrollView = (id)subview;
[scrollView scrollClipView:scrollView.contentView toPoint:CGPointMake(reloadScroll, 0.0)];
if (reloadHeader)
[self columnViewHeader:reloadHeader clickedWithItem:item];
else
[self clickAction];
}
return;
}
// Redisplay (for name, icon, overlay changes)
[browserView setNeedsDisplay:YES];
// Redisplay detail view
if (detailsItem == item && [browserView detailViewController]) {
ColumnViewDetails *detailsController;
detailsController = [[ColumnViewDetails alloc]
initWithItem:item
actionDelegate:[self.view.window windowController]];
[browserView setDetailViewController:detailsController];
}
// Directory change
if ([item isDirectory]) {
// Get column number from parent count
NSInteger column = 0;
for (P4Item *parent = item.parent; parent; column++, parent = parent.parent);
if (column > browserView.lastColumn)
return;
if (item != [browserView parentForItemsInColumn:column])
return;
// Reload children
[browserView reloadColumn:column];
// // Refresh navigation
// id lastItem = [navigationController lastItem];
// [navigationController removeLastItem];
// [navigationController setLastItem:lastItem];
// Refresh column header
if (column > 0)
[[columnHeaders objectAtIndex:column-1] setRepresentedObject:item];
}
}
- (void)itemDidInvalidate:(P4Item *)item {
if (item == detailsItem)
[browserView setDetailViewController:nil];
}
- (void)item:(id)item didFailWithError:(NSError *)error {
[self failWithError:error];
[self itemDidLoad:item];
[self showErrorForItem:item];
PSLog(@"ColumnView error: %@", error.localizedDescription);
}
#pragma mark - Quicklook Panel delegate
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel {
return YES;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel {
quickLookPanel = panel;
panel.delegate = self;
panel.dataSource = self;
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel {
quickLookPanel = nil;
}
- (BOOL)previewPanel:(QLPreviewPanel *)panel handleEvent:(NSEvent *)event {
// Redirect all key down events to the browser
if ([event type] == NSKeyDown) {
[browserView keyDown:event];
return YES;
}
return NO;
}
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
quickLookItems = [self selectedItems];
return quickLookItems.count;
}
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
return [quickLookItems objectAtIndex:index];
}
- (NSRect)previewPanel:(QLPreviewPanel *)panel sourceFrameOnScreenForPreviewItem:(id <QLPreviewItem>)item {
NSIndexPath *indexPath = [browserView selectionIndexPath];
if (!indexPath)
return CGRectZero;
// Calculate selected cell's image frame
NSUInteger row = [indexPath indexAtPosition:indexPath.length-1];
CGRect cellRect = [browserView frameOfRow:row inColumn:indexPath.length-1];
NSCell *cell = [browserView selectedCellInColumn:browserView.selectedColumn];
CGRect imageRect = [cell imageRectForBounds:cellRect];
CGRect columnRect = [browserView frameOfColumn:indexPath.length-1];
imageRect.origin.x += columnRect.origin.x;
imageRect.origin.y += columnRect.origin.y;
// Check that the icon rect is visible on screen
CGRect visibleRect = [browserView visibleRect];
if (!NSIntersectsRect(visibleRect, imageRect))
return CGRectZero;
// Convert icon rect to screen coordinates
imageRect = [browserView convertRectToBase:imageRect];
imageRect.origin = [[browserView window] convertBaseToScreen:imageRect.origin];
return imageRect;
}
- (id)previewPanel:(QLPreviewPanel *)panel transitionImageForPreviewItem:(id <QLPreviewItem>)previewItem contentRect:(NSRect *)contentRect {
P4Item *item = (P4Item *)previewItem;
return item.iconHighlighted;
}
#pragma mark - Menu delegate
- (void)menuWillOpen:(NSMenu *)menu {
[menu setAllowsContextMenuPlugIns:NO];
NSInteger col = [browserView clickedColumn];
NSInteger row = [browserView clickedRow];
NSIndexSet *set = [browserView selectedRowIndexesInColumn:col];
P4Item *item = nil;
if (set.count > 1 && [set containsIndex:row]) {
item = [browserView parentForItemsInColumn:col]; // Multiple
[menu setItems:[item.children objectsAtIndexes:set]
delegate:[self.view.window windowController]];
return;
} else if (col >= 0) {
if (row < 0)
item = [browserView parentForItemsInColumn:col];
else
item = [browserView itemAtRow:row inColumn:col];
}
[menu setItem:item delegate:[self.view.window windowController]];
}
@end
# |
Change |
User |
Description |
Committed |
|
#1
|
10691 |
DWishR |
Populate //guest/DWishR/piper/.... |
|
|
//guest/perforce_software/piper/Perforce/Classes/ViewControllers/ColumnView/ColumnViewController.m |
#1
|
8919 |
Matt Attaway |
Initial add of Piper, a lightweight Perforce client for artists and designers. |
|
|