304 lines
8.3 KiB
Objective-C
304 lines
8.3 KiB
Objective-C
/*
|
|
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
|
|
* This file is part of OpenRA, which is free software. It is made
|
|
* available to you under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation. For more information,
|
|
* see LICENSE.
|
|
*/
|
|
|
|
#import "Controller.h"
|
|
#import "Mod.h"
|
|
#import "SidebarEntry.h"
|
|
#import "GameInstall.h"
|
|
#import "ImageAndTextCell.h"
|
|
#import "JSBridge.h"
|
|
#import "Download.h"
|
|
|
|
@implementation Controller
|
|
@synthesize allMods;
|
|
@synthesize webView;
|
|
|
|
+ (void)initialize
|
|
{
|
|
[[NSUserDefaults standardUserDefaults]
|
|
registerDefaults:[NSDictionary dictionaryWithObject:[[NSBundle mainBundle] resourcePath]
|
|
forKey:@"gamepath"]];
|
|
}
|
|
|
|
- (void)awakeFromNib
|
|
{
|
|
NSString *gamePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"gamepath"];
|
|
|
|
game = [[GameInstall alloc] initWithPath:gamePath];
|
|
[[JSBridge sharedInstance] setController:self];
|
|
downloads = [[NSMutableDictionary alloc] init];
|
|
hasMono = [self hasSupportedMono];
|
|
if (hasMono)
|
|
{
|
|
NSTableColumn *col = [outlineView tableColumnWithIdentifier:@"mods"];
|
|
ImageAndTextCell *imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease];
|
|
[col setDataCell:imageAndTextCell];
|
|
|
|
sidebarItems = [[SidebarEntry headerWithTitle:@""] retain];
|
|
[self populateModInfo];
|
|
id modsRoot = [self sidebarModsTree];
|
|
[sidebarItems addChild:modsRoot];
|
|
//id otherRoot = [self sidebarOtherTree];
|
|
//[sidebarItems addChild:otherRoot];
|
|
|
|
|
|
[outlineView reloadData];
|
|
[outlineView expandItem:modsRoot expandChildren:YES];
|
|
|
|
if ([[modsRoot children] count] > 0)
|
|
{
|
|
id firstMod = [[modsRoot children] objectAtIndex:0];
|
|
int row = [outlineView rowForItem:firstMod];
|
|
[outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
|
[[webView mainFrame] loadRequest:[NSURLRequest requestWithURL: [firstMod url]]];
|
|
}
|
|
|
|
//[outlineView expandItem:otherRoot expandChildren:YES];
|
|
}
|
|
}
|
|
|
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
|
{
|
|
if (!hasMono)
|
|
{
|
|
NSAlert *alert = [NSAlert alertWithMessageText:@"Mono Framework"
|
|
defaultButton:@"Download Mono"
|
|
alternateButton:@"Quit"
|
|
otherButton:nil
|
|
informativeTextWithFormat:@"OpenRA requires the Mono Framework version 2.6.7 or later."];
|
|
|
|
[alert beginSheetModalForWindow:window modalDelegate:self didEndSelector:@selector(monoAlertEnded:code:context:) contextInfo:NULL];
|
|
}
|
|
}
|
|
|
|
- (void)monoAlertEnded:(NSAlert *)alert
|
|
code:(int)button
|
|
context:(void *)v
|
|
{
|
|
if (button == NSAlertDefaultReturn)
|
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.go-mono.com/mono-downloads/download.html"]];
|
|
|
|
[[NSApplication sharedApplication] terminate:self];
|
|
}
|
|
|
|
- (BOOL)hasSupportedMono
|
|
{
|
|
if (![[NSFileManager defaultManager] fileExistsAtPath:@"/Library/Frameworks/Mono.framework/Commands/mono"])
|
|
return NO;
|
|
|
|
NSPipe *outPipe = [NSPipe pipe];
|
|
NSTask *task = [[NSTask alloc] init];
|
|
[task setLaunchPath:@"/Library/Frameworks/Mono.framework/Commands/mono"];
|
|
[task setArguments:[NSMutableArray arrayWithObject:@"--version"]];
|
|
[task setStandardOutput:outPipe];
|
|
[task setStandardError:[task standardOutput]];
|
|
[task launch];
|
|
|
|
NSData *data = [[outPipe fileHandleForReading] readDataToEndOfFile];
|
|
[task waitUntilExit];
|
|
[task release];
|
|
|
|
NSString *ret = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
|
|
|
|
int major = 0;
|
|
int minor = 0;
|
|
int point = 0;
|
|
sscanf([ret UTF8String], "Mono JIT compiler version %d.%d.%d", &major, &minor, &point);
|
|
[ret release];
|
|
|
|
return (major > 2 ||
|
|
(major == 2 && minor > 6) ||
|
|
(major == 2 && minor == 6 && point >= 7));
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[sidebarItems release]; sidebarItems = nil;
|
|
[downloads release]; downloads = nil;
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)populateModInfo
|
|
{
|
|
// Get info for all installed mods
|
|
[allMods autorelease];
|
|
allMods = [[game infoForMods:[game installedMods]] retain];
|
|
}
|
|
|
|
- (SidebarEntry *)sidebarModsTree
|
|
{
|
|
SidebarEntry *rootItem = [SidebarEntry headerWithTitle:@"MODS"];
|
|
for (id key in allMods)
|
|
{
|
|
id aMod = [allMods objectForKey:key];
|
|
if ([aMod standalone])
|
|
{
|
|
id path = [[game gamePath] stringByAppendingPathComponent:@"mods"];
|
|
id child = [SidebarEntry entryWithMod:aMod allMods:allMods basePath:path];
|
|
[rootItem addChild:child];
|
|
}
|
|
}
|
|
|
|
return rootItem;
|
|
}
|
|
|
|
- (SidebarEntry *)sidebarOtherTree
|
|
{
|
|
SidebarEntry *rootItem = [SidebarEntry headerWithTitle:@"OTHER"];
|
|
[rootItem addChild:[SidebarEntry entryWithTitle:@"Support" url:nil icon:nil]];
|
|
[rootItem addChild:[SidebarEntry entryWithTitle:@"Credits" url:nil icon:nil]];
|
|
|
|
return rootItem;
|
|
}
|
|
|
|
- (void)launchMod:(NSString *)mod
|
|
{
|
|
[game launchMod:mod];
|
|
}
|
|
|
|
- (BOOL)registerDownload:(NSString *)key withURL:(NSString *)url filePath:(NSString *)path;
|
|
{
|
|
if ([downloads objectForKey:key] != nil)
|
|
return NO;
|
|
|
|
[downloads setObject:[Download downloadWithURL:url filename:path key:key game:game]
|
|
forKey:key];
|
|
return YES;
|
|
}
|
|
|
|
- (Download *)downloadWithKey:(NSString *)key
|
|
{
|
|
return [downloads objectForKey:key];
|
|
}
|
|
|
|
#pragma mark Sidebar Datasource and Delegate
|
|
- (NSInteger)outlineView:(NSOutlineView *)anOutlineView numberOfChildrenOfItem:(id)item
|
|
{
|
|
// Can be called before awakeFromNib; return nothing
|
|
if (sidebarItems == nil)
|
|
return 0;
|
|
|
|
// Root item
|
|
if (item == nil)
|
|
return [[sidebarItems children] count];
|
|
|
|
return [[item children] count];
|
|
}
|
|
|
|
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
|
|
{
|
|
return (item == nil) ? YES : [[item children] count] != 0;
|
|
}
|
|
|
|
- (id)outlineView:(NSOutlineView *)outlineView
|
|
child:(NSInteger)index
|
|
ofItem:(id)item
|
|
{
|
|
if (item == nil)
|
|
return [[sidebarItems children] objectAtIndex:index];
|
|
|
|
return [[item children] objectAtIndex:index];
|
|
}
|
|
|
|
-(BOOL)outlineView:(NSOutlineView*)outlineView isGroupItem:(id)item
|
|
{
|
|
if (item == nil)
|
|
return NO;
|
|
|
|
return [item isHeader];
|
|
}
|
|
|
|
- (id)outlineView:(NSOutlineView *)outlineView
|
|
objectValueForTableColumn:(NSTableColumn *)tableColumn
|
|
byItem:(id)item
|
|
{
|
|
return [item title];
|
|
}
|
|
|
|
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
|
|
{
|
|
// don't allow headers to be selected
|
|
if ([item isHeader] || [item url] == nil)
|
|
return NO;
|
|
|
|
[[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[item url]]];
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
|
{
|
|
if ([[tableColumn identifier] isEqualToString:@"mods"])
|
|
{
|
|
if ([cell isKindOfClass:[ImageAndTextCell class]])
|
|
{
|
|
[(ImageAndTextCell*)cell setImage:[item icon]];
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma mark WebView delegates
|
|
- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame
|
|
{
|
|
[windowObject setValue:[JSBridge sharedInstance] forKey:@"external"];
|
|
}
|
|
|
|
- (void)webView:(WebView *)webView addMessageToConsole:(NSDictionary *)dictionary
|
|
{
|
|
NSLog(@"%@",dictionary);
|
|
}
|
|
|
|
|
|
#pragma mark Application delegates
|
|
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
|
|
{
|
|
return YES;
|
|
}
|
|
|
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
|
{
|
|
int count = 0;
|
|
for (NSString *key in downloads)
|
|
if ([[(Download *)[downloads objectForKey:key] status] isEqualToString:@"DOWNLOADING"])
|
|
count++;
|
|
|
|
if (count == 0)
|
|
return NSTerminateNow;
|
|
|
|
NSString *format = count == 1 ? @"1 download is" : [NSString stringWithFormat:@"%d downloads are",count];
|
|
NSAlert *alert = [NSAlert alertWithMessageText:@"Are you sure you want to quit?"
|
|
defaultButton:@"Wait"
|
|
alternateButton:@"Quit"
|
|
otherButton:nil
|
|
informativeTextWithFormat:@"%@ in progress and will be cancelled if you quit.", format];
|
|
|
|
[alert beginSheetModalForWindow:window modalDelegate:self didEndSelector:@selector(quitAlertEnded:code:context:) contextInfo:NULL];
|
|
return NSTerminateLater;
|
|
}
|
|
|
|
- (void)quitAlertEnded:(NSAlert *)alert
|
|
code:(int)button
|
|
context:(void *)v
|
|
{
|
|
NSApplicationTerminateReply reply = (button == NSAlertDefaultReturn) ? NSTerminateCancel : NSTerminateNow;
|
|
[[NSApplication sharedApplication] replyToApplicationShouldTerminate:reply];
|
|
}
|
|
|
|
- (void)applicationWillTerminate:(NSNotification *)aNotification
|
|
{
|
|
// Cancel all in-progress downloads
|
|
for (NSString *key in downloads)
|
|
{
|
|
Download *d = [downloads objectForKey:key];
|
|
if ([[d status] isEqualToString:@"DOWNLOADING"])
|
|
[d cancel];
|
|
}
|
|
}
|
|
|
|
@end
|