//
// MainWindowController.m
// Perforce
//
// Created by Adam Czubernat on 09.05.2013.
// Copyright (c) 2013 Perforce Software, Inc. All rights reserved.
//
#import "MainWindowController.h"
#import "DebugWindowController.h"
#import "LoginPanelController.h"
#import "WorkspacePanelController.h"
#import "SubmitPanelController.h"
#import "SyncPanelController.h"
#import "LoadingPanelController.h"
#import "SidebarViewController.h"
#import "BrowserViewController.h"
#import "ColumnViewController.h"
#import "IconViewController.h"
#import "P4Workspace.h"
#import "P4Reachability.h"
#define PANE_DEFAULT_WIDTH 200.0f
#define PANE_MIN_WIDTH 150.0f
#define PATH_DEFAULT_HEIGHT 40.0f
@interface MainWindowController () <NSMenuDelegate, NSSplitViewDelegate, NSPathControlDelegate,
LoginPanelControllerDelegate,
WorkspacePanelControllerDelegate,
SidebarViewControllerDelegate,
BrowserViewDelegate,
P4ItemActionDelegate> {
NSString *launchURL;
NSMutableArray *redoStack;
NSMutableArray *undoStack;
SidebarViewController *sidebarController;
BrowserViewController *browserController;
LoginPanelController *loginPanel;
DebugWindowController *debugController;
P4ItemAction *pendingAction;
LoadingPanelController *pendingActionPanel;
// Subviews
__weak IBOutlet PSView *_topBar;
__weak IBOutlet PSSplitView *_mainSplitView;
__weak IBOutlet NSView *_leftPane;
__weak IBOutlet PSSplitView *_rightSplitView;
__weak IBOutlet NSView *_rightTopPane;
__weak IBOutlet NSView *_rightBottonPane;
__weak IBOutlet PSView *_pathSeparator;
__weak IBOutlet NSPathControl *_pathControl;
__weak IBOutlet NSView *_networkWarning;
// Top Bar buttons
__weak IBOutlet NSButton *_backButton;
__weak IBOutlet NSButton *_nextButton;
__weak IBOutlet NSButton *_addButton;
__weak IBOutlet NSButton *_createDirectoryButton;
__weak IBOutlet NSButton *_checkInAllButton;
__weak IBOutlet NSButton *_viewColumnButton;
__weak IBOutlet NSButton *_viewIconButton;
__weak IBOutlet NSButton *_syncButton;
__weak IBOutlet PSActivityIndicator *_syncButtonIndicator;
__weak IBOutlet NSSearchField *_searchField;
// Search
__weak NSView *_searchBar;
}
- (void)changePath:(NSString *)path;
- (void)next;
- (void)back;
- (void)clear;
- (void)updateNavigationButtons;
- (void)showNetworkWarning:(BOOL)show animated:(BOOL)animated;
- (void)setBrowserController:(BrowserViewController *)browser;
- (void)syncWorkspace;
- (void)submitFiles:(NSArray *)paths;
- (void)addFiles;
- (void)createDirectory;
- (void)syncStartedNotification:(NSNotification *)notification;
- (void)syncFinishedNotification:(NSNotification *)notification;
- (void)submitFinishedNotification:(NSNotification *)notification;
- (void)sessionExpiredNotification:(NSNotification *)notification;
- (void)networkReachabilityNotification:(NSNotification *)notification;
- (void)pathControlDoubleClick:(id)sender;
- (IBAction)backButtonPressed:(id)sender;
- (IBAction)nextButtonPressed:(id)sender;
- (IBAction)addButtonPressed:(id)sender;
- (IBAction)createDirectoryButtonPressed:(id)sender;
- (IBAction)checkInAllButtonPressed:(id)sender;
- (IBAction)viewColumnButtonPressed:(id)sender;
- (IBAction)viewIconButtonPressed:(id)sender;
- (IBAction)syncButtonPressed:(id)sender;
- (IBAction)searchAction:(id)sender;
@end
@implementation MainWindowController
- (id)init {
return self = [super initWithWindowNibName:NSStringFromClass([self class])];
}
- (void)awakeFromNib {
[super awakeFromNib];
[self.window setFrameUsingName:@"MainWindow"];
[self.window setFrameAutosaveName:@"MainWindow"];
sidebarController = [[SidebarViewController alloc] init];
sidebarController.delegate = self;
[_mainSplitView setDelegate:self];
[_mainSplitView replaceSubview:_leftPane with:sidebarController.view];
[_mainSplitView adjustSubviews];
[_mainSplitView setPosition:PANE_DEFAULT_WIDTH ofDividerAtIndex:0];
// Custom appearance of vertical divider
[_mainSplitView setDividerWidth:0.0f];
[_mainSplitView setHidesDivider:YES];
[_pathSeparator setImage:[NSImage imageNamed:@"SeparatorVerticalDark.png"]];
[_pathSeparator setContentMode:PSViewContentModeCenter];
[_rightSplitView setDelegate:self];
[_rightSplitView setPosition:(_rightSplitView.bounds.size.height - 1.0f
- PATH_DEFAULT_HEIGHT) ofDividerAtIndex:0];
[_rightSplitView adjustSubviews];
[_pathControl setFocusRingType:NSFocusRingTypeNone];
[_pathControl setPathComponentCells:@[]];
[_pathControl setDoubleAction:@selector(pathControlDoubleClick:)];
[_pathControl setTarget:self];
[_pathControl setDelegate:self];
// Config
_topBar.backgroundColor = [NSUserDefaults colorForKey:kColorBackgroundTopBar];
_pathControl.backgroundColor = [NSUserDefaults colorForKey:kColorBackgroundBottomBar];
[(NSBox *)_rightTopPane setFillColor:[NSUserDefaults colorForKey:kColorBackgroundColumnContainer]];
[self showNetworkWarning:![P4Reachability isConnected] animated:NO];
}
- (void)windowDidLoad {
[super windowDidLoad];
[P4Reachability startNotifier];
}
- (void)showWindow:(id)sender {
[super showWindow:sender];
if ([[P4Workspace sharedInstance] isLoggedIn])
return;
// Show login screen
loginPanel = [LoginPanelController loginPanel];
loginPanel.delegate = self;
loginPanel.allowsAutomaticLogin = YES;
loginPanel.allowsSSOLogin = NO;
[loginPanel presentWithWindow:self.window];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(syncStartedNotification:)
name:P4SyncStartedNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(syncFinishedNotification:)
name:P4SyncFinishedNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(submitFinishedNotification:)
name:P4SubmitFinishedNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(sessionExpiredNotification:)
name:P4SessionExpiredNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(networkReachabilityNotification:)
name:P4ReachabilityNotification
object:nil];
}
#pragma mark - Public
- (void)loadURL:(NSString *)url {
if (![url hasPrefix:@"p4://"])
return;
// Check if logged in
if (![[P4Workspace sharedInstance] isLoggedIn] ||
![[P4Workspace sharedInstance] workspace]) {
// Store url until user logs in
launchURL = url;
return;
}
launchURL = nil;
url = [url substringFromIndex:3];
url = [url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// Prepare local path
NSString *root = [[P4Workspace sharedInstance] root];
NSString *relativePath = [url stringByRemovingPrefix:@"//"];
NSString *path = [root stringByAppendingString:relativePath];
// Check if local path exists
BOOL dir = NO;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&dir];
if (exists && dir == [url hasSuffix:@"/"]) {
// Load local workspace url
[browserController loadPath:path];
} else {
// Load depot url
[browserController loadPath:url];
}
}
#pragma mark - Private
- (void)changePath:(NSString *)path {
[sidebarController setWorkingPath:path];
if (!path || [path isEqualToString:undoStack.lastObject])
return;
[undoStack addObject:path];
redoStack = [NSMutableArray array];
[self updateNavigationButtons];
}
- (void)next {
[undoStack addObject:redoStack.lastObject];
[redoStack removeLastObject];
[self updateNavigationButtons];
[browserController loadPath:undoStack.lastObject];
}
- (void)back {
[redoStack addObject:undoStack.lastObject];
[undoStack removeLastObject];
[self updateNavigationButtons];
[browserController loadPath:undoStack.lastObject];
}
- (void)clear {
undoStack = [NSMutableArray array];
redoStack = [NSMutableArray array];
[self updateNavigationButtons];
}
- (void)updateNavigationButtons {
[_backButton setEnabled:undoStack.count > 1];
[_nextButton setEnabled:redoStack.count];
}
- (void)showNetworkWarning:(BOOL)show animated:(BOOL)animated {
if (show == [_networkWarning isHidden]) {
CGRect frame = _pathControl.frame;
frame.size.width = _networkWarning.frame.origin.x;
if (!show)
frame.size.width += _networkWarning.frame.size.width;
if (animated) {
[_networkWarning setAlphaValue:!show];
[_networkWarning setHidden:NO];
[NSView animateWithDuration:0.25f animations:^{
[[_networkWarning animator] setAlphaValue:show];
[[_pathControl animator] setFrame:frame];
} completion:^{
[_networkWarning setHidden:!show];
}];
} else {
[_pathControl setFrame:frame];
[_networkWarning setHidden:!show];
}
}
}
- (void)setBrowserController:(BrowserViewController *)browser {
if (browserController == browser)
return;
BOOL column = [browser isKindOfClass:[ColumnViewController class]];
[_viewColumnButton setEnabled:!column];
[_viewIconButton setEnabled:column];
[_rightSplitView replaceSubview:_rightTopPane with:browser.view];
_rightTopPane = browser.view;
[browser setRootItem:browserController.rootItem];
[browser setWorkingItem:browserController.workingItem];
[browser setSelectedItems:browserController.selectedItems];
[browser setDelegate:self];
// Swap next responders
[browser setNextResponder:browser.view.nextResponder];
[browser.view setNextResponder:browser];
[self.window makeFirstResponder:browser.view];
browserController = browser;
PSLogStore(@"BrowserController", @"%@", browser);
// Swap search bars
if (_searchBar) {
NSView *view = browserController.searchBar;
CGFloat height = view.frame.size.height;
[_rightSplitView replaceSubview:_searchBar with:view];
_searchBar = view;
CGRect frame = view.frame;
frame.size.height = height;
view.frame = frame;
}
}
- (void)syncWorkspace {
SyncPanelController *syncPanel = [[SyncPanelController alloc] init];
[syncPanel presentWithWindow:self.window];
}
- (void)submitFiles:(NSArray *)paths {
SubmitPanelController *submitPanel = [[SubmitPanelController alloc] init];
[submitPanel presentWithWindow:self.window];
[submitPanel selectPaths:paths];
}
- (void)addFiles {
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setCanChooseFiles:YES];
[openPanel setCanChooseDirectories:YES];
[openPanel setAllowsMultipleSelection:YES];
[openPanel setCanCreateDirectories:YES];
[openPanel setPrompt:@"Select"];
NSURL *directory = [NSURL fileURLWithPath:NSHomeDirectory()];
[openPanel setDirectoryURL:directory];
[openPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
if (result != NSOKButton)
return;
NSArray *selectedPaths = [[openPanel URLs] valueForKey:@"path"];
[[browserController workingItem]
performAction:@selector(addFiles:)
object:selectedPaths
delegate:self];
}];
}
- (void)createDirectory {
[[browserController workingItem]
performAction:@selector(createDirectory)
object:nil
delegate:self];
}
#pragma mark - SplitView delegate
- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMaximumPosition ofSubviewAt:(NSInteger)dividerIndex {
if (splitView == _mainSplitView)
return proposedMaximumPosition * 0.5f; // Half of window size
return proposedMaximumPosition;
}
- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex {
if (splitView == _mainSplitView)
return PANE_MIN_WIDTH;
return proposedMinimumPosition;
}
- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview {
if (splitView == _mainSplitView)
return subview == sidebarController.view; // Collapsable side pane
return NO;
}
- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)view {
if (view == sidebarController.view)
return (sidebarController.view.bounds.size.width > // Don't resize side pane / unless it's larger than half of window size
_mainSplitView.bounds.size.width * 0.5f);
if (view == _rightBottonPane)
return NO;
if (view == _searchBar)
return NO;
return YES;
}
- (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect ofDividerAtIndex:(NSInteger)dividerIndex {
if (splitView == _rightSplitView)
return CGRectZero;
return proposedEffectiveRect;
}
#pragma mark - LoginPanel Delegate
- (void)loginPanelDidLogin {
WorkspacePanelController *workspacePanel = [[WorkspacePanelController alloc] init];
workspacePanel.delegate = self;
[workspacePanel presentWithWindow:self.window];
}
- (void)loginPanelDidCancel {
[loginPanel dismiss];
loginPanel = nil;
}
- (void)loginPanelDidLoginWithWorkspace:(NSString *)workspace {
[self workspacePanelDidSelectWorkspace:workspace];
}
- (void)loginPanelDidRelogin {
[loginPanel dismiss];
loginPanel = nil;
[browserController reload];
}
#pragma mark - WorkspacePanel Delegate
- (void)workspacePanelDidSelectWorkspace:(NSString *)workspace {
[loginPanel dismiss];
loginPanel = nil;
[self clear];
// Load workspace defaults
[P4WorkspaceDefaults setWorkspace:workspace];
Class browserClass = [[P4WorkspaceDefaults sharedInstance] iconView] ?
[IconViewController class] : [ColumnViewController class];
if (![browserController isKindOfClass:browserClass])
[self setBrowserController:[[browserClass alloc] init]];
[sidebarController reload];
[browserController setRootItem:nil];
if (launchURL)
[self loadURL:launchURL];
else
[browserController loadPath:[P4Workspace sharedInstance].root];
#ifdef DEBUG
[[P4Workspace sharedInstance] setAutosyncInterval:5*60];
#else
[[P4Workspace sharedInstance] setAutosyncInterval:2*60];
#endif
}
- (void)workspacePanelDidCreateWorkspace:(NSString *)workspace {
[self workspacePanelDidSelectWorkspace:workspace];
}
- (void)workspacePanelDidCancel { }
#pragma mark - Sidebar Delegate
- (void)sidebarDidSelectPath:(NSString *)path {
[browserController loadPath:path];
}
#pragma mark - BrowserView Delegate
- (void)browserView:(BrowserViewController *)browser didChangeWorkingItem:(P4Item *)item {
BOOL editable = item.isEditable;
[_addButton setEnabled:editable];
[_createDirectoryButton setEnabled:editable];
[self changePath:item.path];
}
- (void)browserView:(BrowserViewController *)browser didChangeSelectedItem:(P4Item *)item {
NSColor *color = [NSUserDefaults colorForKey:kColorBackgroundBottomBar];
NSPathComponentCell *(^createCellBlock)(NSString *, NSString *) =
^NSPathComponentCell *(NSString *name, NSString *path) {
PSPathComponentCell *pathCell = [[PSPathComponentCell alloc] init];
pathCell.font = [NSFont fontWithName:@"Helvetica-Bold" size:12];
pathCell.textColor = [NSColor darkGrayColor];
[pathCell setBackgroundColor:color];
[pathCell setImage:[NSImage imageNamed:@"IconFolder"]];
[pathCell setTitle:name];
[pathCell setRepresentedObject:path];
return pathCell;
};
NSString *rootName = nil;
NSString *rootPath = nil;
NSString *relative = item.path;
if ([item.status isEqualToString:@"delete"] ||
[item.status isEqualToString:@"move/delete"])
relative = item.remotePath;
if ([relative hasPrefix:@"//"]) {
rootPath = @"//";
rootName = @"All Files";
} else if ([relative hasPrefix:@"/"]) {
rootPath = [P4Workspace sharedInstance].root;
rootName = @"Workspace";
} else {
rootPath = browserController.rootItem.path;
rootName = browserController.rootItem.name;
relative = nil;
}
relative = [relative stringByRemovingPrefix:rootPath];
relative = [relative stringByRemovingSuffix:@"/"];
NSMutableArray *cells = [NSMutableArray array];
if (rootName)
[cells addObject:createCellBlock(rootName, rootPath)];
NSString *path = rootPath;
for (NSString *component in [relative pathComponents]) {
path = [path stringByAppendingFormat:@"%@/", component];
[cells addObject:createCellBlock(component, path)];
}
PSPathComponentCell *lastCell = [cells lastObject];
if (item && !item.isDirectory)
lastCell.image = item.icon;
[lastCell setLastItem:YES];
[lastCell setRepresentedObject:nil];
[_pathControl setPathComponentCells:cells];
}
- (void)browserView:(id)browser didChangeSearchQuery:(NSString *)query {
if (query) {
if (!_searchBar.superview) {
_searchBar = browserController.searchBar;
[_rightSplitView insertFirstSubview:_searchBar animated:YES];
}
// Update undo stack
if ([[undoStack lastObject] hasPrefix:@"search://"]) {
[undoStack removeLastObject];
NSString *path = browserController.workingItem.path ?: @"search://"; // Dirty way to ensure non-nil
[undoStack addObject:path];
}
} else {
_searchField.stringValue = @"";
if (_searchBar.superview) {
[_rightSplitView removeFirstSubviewAnimated:YES];
_searchBar = nil;
}
// Remove history stack entries
if ([[undoStack lastObject] hasPrefix:@"search://"])
[undoStack removeLastObject];
if ([[redoStack lastObject] hasPrefix:@"search://"])
[redoStack removeLastObject];
[self updateNavigationButtons];
}
}
#pragma mark - P4ItemAction delegate
- (void)action:(P4ItemAction *)action loadingMessage:(NSString *)message {
if (pendingActionPanel)
return;
pendingAction = action;
pendingActionPanel = [[LoadingPanelController alloc]
initWithStyle:NSProgressIndicatorSpinningStyle];
pendingActionPanel.title = message;
[pendingActionPanel presentWithWindow:self.window];
}
- (void)action:(P4ItemAction *)action didFinish:(NSArray *)response error:(NSError *)error {
if (pendingAction == action) {
[pendingActionPanel dismiss];
pendingActionPanel = nil;
pendingAction = nil;
}
if (error) {
// Don't show alert for session expiration
if (error.code == P4ErrorSessionExpired)
return;
NSAlert *alert = [NSAlert alertWithError:error];
[alert setMessageText:@"\nAction failed"];
[alert setInformativeText:error.localizedDescription];
[alert setIcon:[[NSImage alloc] init]];
[alert
beginSheetModalForWindow:self.window
modalDelegate:nil
didEndSelector:nil
contextInfo:NULL];
return;
}
if (action.selector == @selector(createDirectory))
[browserController editItemName:[action.item cachedItemForPath:response.lastObject]];
else if (action.selector == @selector(checkIn))
[self submitFiles:@[ action.item.remotePath ]];
else if (action.selector == @selector(checkInItems:))
[self submitFiles:[action.items valueForKey:@"remotePath"]];
else if (action.selector == @selector(checkInAll))
[self submitFiles:response];
else if (action.selector == @selector(addFiles:))
[self submitFiles:[response valueForKey:@"depotFile"]];
else if (action.selector == @selector(showVersions))
[browserController showVersions:action.item];
}
- (BOOL)action:(id)action prompt:(NSString *)message {
return [[NSAlert
alertWithMessageText:@"Confirm"
defaultButton:@"Yes"
alternateButton:@"No"
otherButton:nil
informativeTextWithFormat:@"%@", message] runModal] == NSAlertDefaultReturn;
}
#pragma mark - P4Workspace notifications
- (void)syncStartedNotification:(NSNotification *)notification {
[_checkInAllButton setEnabled:NO];
[_syncButtonIndicator setHidden:NO];
[_syncButtonIndicator setAlphaValue:0.0f];
[NSView animateWithDuration:0.25f animations:^{
[_syncButton.animator setAlphaValue:0.0f];
[_syncButtonIndicator.animator setAlphaValue:1.0f];
} completion:^{
[_syncButton setHidden:YES];
}];
}
- (void)syncFinishedNotification:(NSNotification *)notification {
[_checkInAllButton setEnabled:YES];
[_syncButton setHidden:NO];
[_syncButton setAlphaValue:0.0f];
[NSView animateWithDuration:0.25f animations:^{
[_syncButton.animator setAlphaValue:1.0f];
[_syncButtonIndicator.animator setAlphaValue:0.0f];
} completion:^{
[_syncButton setAlphaValue:1.0f];
[_syncButton setHidden:NO]; // Make sure it's not hidden
[_syncButtonIndicator setHidden:YES];
}];
[browserController reload];
}
- (void)submitFinishedNotification:(NSNotification *)notification {
[browserController reload];
}
#pragma mark - Network notifications
- (void)sessionExpiredNotification:(NSNotification *)notification {
if (loginPanel)
return;
loginPanel = [LoginPanelController reloginPanel];
loginPanel.delegate = self;
[loginPanel presentExclusiveWithWindow:self.window];
}
- (void)networkReachabilityNotification:(NSNotification *)notification {
[self showNetworkWarning:![P4Reachability isConnected] animated:YES];
}
#pragma mark - PathControl
- (NSDragOperation)pathControl:(NSPathControl *)pathControl validateDrop:(id <NSDraggingInfo>)info {
return NSDragOperationNone;
}
- (void)pathControlDoubleClick:(id)sender {
NSPathComponentCell *cell = [_pathControl clickedPathComponentCell];
NSString *path = cell.representedObject;
if (path)
[browserController loadPath:path];
}
#pragma mark - NSMenu delegate
- (void)menuWillOpen:(NSMenu *)menu {
if (menu == fileMenu) {
BOOL connected = [[P4Workspace sharedInstance] isLoggedIn];
[[menu itemAtIndex:0] setEnabled:!connected];
[[menu itemAtIndex:1] setEnabled:connected];
[[menu itemAtIndex:2] setEnabled:connected];
} else if (menu == actionsMenu) {
NSArray *selectedItems = [browserController selectedItems];
if (selectedItems.count > 1)
[menu setItems:selectedItems delegate:self];
else if (selectedItems.count)
[menu setItem:selectedItems.lastObject delegate:self];
else {
[menu removeAllItems];
[[menu addItemWithTitle:@"No selection" action:nil keyEquivalent:@""] setEnabled:NO];
}
} else if (menu == viewMenu) {
BOOL column = [browserController isKindOfClass:[ColumnViewController class]];
[[menu itemAtIndex:0] setEnabled:!column];
[[menu itemAtIndex:1] setEnabled:column];
[[menu itemAtIndex:0] setState:column];
[[menu itemAtIndex:1] setState:!column];
}
}
#pragma mark - Menu Actions
- (IBAction)fileMenuConnect:(id)sender {
if (loginPanel)
return;
loginPanel = [LoginPanelController loginPanel];
loginPanel.delegate = self;
[loginPanel presentWithWindow:self.window];
}
- (IBAction)fileMenuConnectionDetails:(id)sender {
if (loginPanel)
return;
loginPanel = [LoginPanelController connectionPanel];
loginPanel.delegate = self;
[loginPanel presentWithWindow:self.window];
}
- (IBAction)fileMenuDisconnect:(id)sender {
LoadingPanelController *loading = [[LoadingPanelController alloc]
initWithStyle:NSProgressIndicatorSpinningStyle];
loading.title = @"Logging out...";
[loading presentWithWindow:self.window];
[[P4Workspace sharedInstance] logout:^(P4Operation *operation, NSArray *response) {
[P4WorkspaceDefaults setWorkspace:nil];
[sidebarController reload];
[browserController setRootItem:nil];
[loading dismiss];
[self fileMenuConnect:nil];
}];
}
- (IBAction)viewMenuColumnView:(id)sender {
[[P4WorkspaceDefaults sharedInstance] setIconView:NO];
[self setBrowserController:[[ColumnViewController alloc] init]];
}
- (IBAction)viewMenuIconView:(id)sender {
[[P4WorkspaceDefaults sharedInstance] setIconView:YES];
[self setBrowserController:[[IconViewController alloc] init]];
}
- (IBAction)debugMenuRunCommand:(id)sender {
debugController = [[DebugWindowController alloc] init];
[debugController showWindow:self];
}
- (IBAction)debugMenuSaveLog:(id)sender {
PSDebugLogSave();
}
#pragma mark - Toolbar actions
- (IBAction)backButtonPressed:(id)sender {
[self back];
}
- (IBAction)nextButtonPressed:(id)sender {
[self next];
}
- (IBAction)syncButtonPressed:(id)sender {
[self syncWorkspace];
}
- (IBAction)addButtonPressed:(id)sender {
[self addFiles];
}
- (IBAction)checkInAllButtonPressed:(id)sender {
[self submitFiles:nil];
}
- (IBAction)viewColumnButtonPressed:(id)sender {
[self viewMenuColumnView:sender];
}
- (IBAction)viewIconButtonPressed:(id)sender {
[self viewMenuIconView:sender];
}
- (IBAction)createDirectoryButtonPressed:(id)sender {
[self createDirectory];
}
#pragma mark - Search action
- (IBAction)searchAction:(id)sender {
[browserController search:[_searchField stringValue]];
}
@end
# |
Change |
User |
Description |
Committed |
|
#1
|
10691 |
DWishR |
Populate //guest/DWishR/piper/.... |
|
|
//guest/perforce_software/piper/Perforce/Classes/WindowControllers/MainWindowController.m |
#1
|
8919 |
Matt Attaway |
Initial add of Piper, a lightweight Perforce client for artists and designers. |
|
|