diff --git a/OpenRA.Launcher.Mac/Controller.h b/OpenRA.Launcher.Mac/Controller.h
index fea1a83370..7e4fec97cb 100644
--- a/OpenRA.Launcher.Mac/Controller.h
+++ b/OpenRA.Launcher.Mac/Controller.h
@@ -20,4 +20,6 @@
}
- (IBAction)launchGame:(id)sender;
- (SidebarEntry *)sidebarModsTree;
+- (SidebarEntry *)sidebarOtherTree;
+
@end
diff --git a/OpenRA.Launcher.Mac/Controller.m b/OpenRA.Launcher.Mac/Controller.m
index a2e2e28594..352c70b8a8 100644
--- a/OpenRA.Launcher.Mac/Controller.m
+++ b/OpenRA.Launcher.Mac/Controller.m
@@ -16,7 +16,7 @@
- (void) awakeFromNib
{
- game = [[GameInstall alloc] initWithPath:@"/Users/paul/src/OpenRA"];
+ game = [[GameInstall alloc] initWithURL:[NSURL URLWithString:@"/Users/paul/src/OpenRA"]];
sidebarItems = [[SidebarEntry headerWithTitle:@""] retain];
[sidebarItems addChild:[self sidebarModsTree]];
[sidebarItems addChild:[self sidebarOtherTree]];
@@ -25,7 +25,7 @@
[col setDataCell:imageAndTextCell];
[outlineView reloadData];
- [outlineView expandItem:[outlineView itemAtRow:1] expandChildren:YES];
+ [outlineView expandItem:[outlineView itemAtRow:0] expandChildren:YES];
[outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
}
@@ -111,11 +111,11 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
{
// don't allow headers to be selected
- if ([item isHeader])
- return NO;
-
- // TODO: Display the webpage
+ if ([item isHeader] || [item url] == nil)
+ return NO;
+ [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:[item url]]];
+
return YES;
}
diff --git a/OpenRA.Launcher.Mac/English.lproj/MainMenu.xib b/OpenRA.Launcher.Mac/English.lproj/MainMenu.xib
index 40355c080b..3a200f77a1 100644
--- a/OpenRA.Launcher.Mac/English.lproj/MainMenu.xib
+++ b/OpenRA.Launcher.Mac/English.lproj/MainMenu.xib
@@ -21,8 +21,8 @@
0
diff --git a/OpenRA.Launcher.Mac/GameInstall.h b/OpenRA.Launcher.Mac/GameInstall.h
index 50bcd033f1..588b08b403 100644
--- a/OpenRA.Launcher.Mac/GameInstall.h
+++ b/OpenRA.Launcher.Mac/GameInstall.h
@@ -10,13 +10,13 @@
@class Mod;
@interface GameInstall : NSObject {
- NSString *gamePath;
- NSMutableString *utilityBuffer;
+ NSURL *gameURL;
}
--(id)initWithPath:(NSString *)path;
+-(id)initWithURL:(NSURL *)path;
-(void)launchGame;
-- (void)runUtilityApp:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel;
+- (NSString *)runUtilityQuery:(NSString *)arg;
+- (void)runUtilityQuery:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel;
- (NSArray *)installedMods;
- (NSArray *)infoForMods:(NSArray *)mods;
@end
diff --git a/OpenRA.Launcher.Mac/GameInstall.m b/OpenRA.Launcher.Mac/GameInstall.m
index 9006a0cff4..4a245e7d62 100644
--- a/OpenRA.Launcher.Mac/GameInstall.m
+++ b/OpenRA.Launcher.Mac/GameInstall.m
@@ -11,47 +11,32 @@
@implementation GameInstall
--(id)initWithPath:(NSString *)path
+-(id)initWithURL:(NSURL *)url
{
self = [super init];
if (self != nil)
{
- gamePath = path;
+ gameURL = url;
}
return self;
}
- (void)dealloc
{
- [utilityBuffer release];
[super dealloc];
}
--(void)clearBuffer
-{
- [utilityBuffer release];
- utilityBuffer = [[NSMutableString stringWithString:@""] retain];
-}
-
-- (void)bufferData:(NSString *)string
-{
- if (string == nil) return;
- [utilityBuffer appendString:string];
-}
-
- (NSArray *)installedMods
{
- [self clearBuffer];
- [self runUtilityApp:@"-l" handleOutput:self withMethod:@selector(bufferData:)];
- id mods = [[NSString stringWithString:utilityBuffer] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ id raw = [self runUtilityQuery:@"-l"];
+ id mods = [raw stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
return [mods componentsSeparatedByString:@"\n"];
}
- (NSArray *)infoForMods:(NSArray *)mods
{
- [self clearBuffer];
- [self runUtilityApp:[NSString stringWithFormat:@"-i=%@",[mods componentsJoinedByString:@","]] handleOutput:self withMethod:@selector(bufferData:)];
- NSArray *lines = [utilityBuffer componentsSeparatedByString:@"\n"];
+ id query = [NSString stringWithFormat:@"-i=%@",[mods componentsJoinedByString:@","]];
+ NSArray *lines = [[self runUtilityQuery:query] componentsSeparatedByString:@"\n"];
NSMutableArray *ret = [NSMutableArray array];
NSMutableDictionary *fields = nil;
@@ -63,6 +48,9 @@
continue;
id kv = [line componentsSeparatedByString:@":"];
+ if ([kv count] < 2)
+ continue;
+
id key = [kv objectAtIndex:0];
id value = [kv objectAtIndex:1];
@@ -76,7 +64,10 @@
{
// Commit prev mod
if (current != nil)
- [ret addObject:[Mod modWithId:current fields:fields]];
+ {
+ id url = [gameURL URLByAppendingPathComponent:[NSString stringWithFormat:@"mods/%@",current]];
+ [ret addObject:[Mod modWithId:current fields:fields baseURL:url]];
+ }
NSLog(@"Parsing mod %@",value);
current = value;
fields = [NSMutableDictionary dictionary];
@@ -93,7 +84,7 @@
{
// Use LaunchServices because neither NSTask or NSWorkspace support Info.plist _and_ arguments pre-10.6
NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"OpenRA.app/Contents/MacOS/OpenRA"];
- NSArray *args = [NSArray arrayWithObjects:gamePath, @"mono", @"--debug", @"OpenRA.Game.exe", @"Game.Mods=ra",nil];
+ NSArray *args = [NSArray arrayWithObjects:[gameURL absoluteString], @"mono", @"--debug", @"OpenRA.Game.exe", @"Game.Mods=ra",nil];
FSRef appRef;
CFURLGetFSRef((CFURLRef)[NSURL URLWithString:path], &appRef);
@@ -116,7 +107,7 @@
SetFrontProcess(&psn);
}
-- (void)runUtilityApp:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel
+- (NSString *)runUtilityQuery:(NSString *)arg
{
NSTask *aTask = [[NSTask alloc] init];
NSPipe *aPipe = [NSPipe pipe];
@@ -125,7 +116,29 @@
NSMutableArray *taskArgs = [NSMutableArray arrayWithObject:@"OpenRA.Utility.exe"];
[taskArgs addObject:arg];
- [aTask setCurrentDirectoryPath:gamePath];
+ [aTask setCurrentDirectoryPath:[gameURL absoluteString]];
+ [aTask setLaunchPath:@"/Library/Frameworks/Mono.framework/Commands/mono"];
+ [aTask setArguments:taskArgs];
+ [aTask setStandardOutput:aPipe];
+ [aTask setStandardError:[aTask standardOutput]];
+ [aTask launch];
+ NSData *data = [readHandle readDataToEndOfFile];
+ [aTask release];
+
+ return [NSString stringWithUTF8String:[data bytes]];
+}
+
+
+- (void)runUtilityQuery:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel
+{
+ NSTask *aTask = [[NSTask alloc] init];
+ NSPipe *aPipe = [NSPipe pipe];
+ NSFileHandle *readHandle = [aPipe fileHandleForReading];
+
+ NSMutableArray *taskArgs = [NSMutableArray arrayWithObject:@"OpenRA.Utility.exe"];
+ [taskArgs addObject:arg];
+
+ [aTask setCurrentDirectoryPath:[gameURL absoluteString]];
[aTask setLaunchPath:@"/Library/Frameworks/Mono.framework/Commands/mono"];
[aTask setArguments:taskArgs];
[aTask setStandardOutput:aPipe];
@@ -134,7 +147,7 @@
NSData *inData = nil;
while ((inData = [readHandle availableData]) && [inData length])
[obj performSelector:sel withObject:[NSString stringWithUTF8String:[inData bytes]]];
-
+ [aTask waitUntilExit];
[aTask release];
}
diff --git a/OpenRA.Launcher.Mac/Mod.h b/OpenRA.Launcher.Mac/Mod.h
index a1add343ac..b8ea2393db 100644
--- a/OpenRA.Launcher.Mac/Mod.h
+++ b/OpenRA.Launcher.Mac/Mod.h
@@ -9,6 +9,7 @@
#import
@interface Mod : NSObject {
+ NSURL *baseURL;
NSString *mod;
NSString *title;
NSString *version;
@@ -25,6 +26,8 @@
@property (readonly) NSString *requires;
@property (readonly) BOOL standalone;
-+ (id)modWithId:(NSString *)mid fields:(id)fields;
-- (id)initWithId:(NSString *)mod fields:(NSDictionary *)fields;
++ (id)modWithId:(NSString *)mid fields:(id)fields baseURL:(NSURL *)url;
+- (id)initWithId:(NSString *)anId fields:(NSDictionary *)fields baseURL:(NSURL *)url;
+
+- (NSURL *)pageURL;
@end
diff --git a/OpenRA.Launcher.Mac/Mod.m b/OpenRA.Launcher.Mac/Mod.m
index 2536f34381..68ecff5770 100644
--- a/OpenRA.Launcher.Mac/Mod.m
+++ b/OpenRA.Launcher.Mac/Mod.m
@@ -18,19 +18,20 @@
@synthesize requires;
@synthesize standalone;
-+ (id)modWithId:(NSString *)mod fields:(id)fields
++ (id)modWithId:(NSString *)mod fields:(id)fields baseURL:(NSURL *)url
{
- id newObject = [[self alloc] initWithId:mod fields:fields];
+ id newObject = [[self alloc] initWithId:mod fields:fields baseURL:url];
[newObject autorelease];
return newObject;
}
-- (id)initWithId:(NSString *)anId fields:(NSDictionary *)fields
+- (id)initWithId:(NSString *)anId fields:(NSDictionary *)fields baseURL:(NSURL *)url
{
self = [super init];
if (self)
{
- mod = anId;
+ mod = [anId retain];
+ baseURL = [url retain];
title = [[fields objectForKey:@"Title"] retain];
version = [[fields objectForKey:@"Version"] retain];
author = [[fields objectForKey:@"Author"] retain];
@@ -41,9 +42,10 @@
return self;
}
-
- (void) dealloc
{
+ [mod release]; mod = nil;
+ [baseURL release]; baseURL = nil;
[title release]; title = nil;
[version release]; version = nil;
[author release]; author = nil;
@@ -52,4 +54,9 @@
[super dealloc];
}
+- (NSURL *)pageURL
+{
+ return [baseURL URLByAppendingPathComponent:@"mod.html"];
+}
+
@end
diff --git a/OpenRA.Launcher.Mac/SidebarEntry.h b/OpenRA.Launcher.Mac/SidebarEntry.h
index d4c08a7016..16a1ed25ef 100644
--- a/OpenRA.Launcher.Mac/SidebarEntry.h
+++ b/OpenRA.Launcher.Mac/SidebarEntry.h
@@ -28,5 +28,5 @@
+ (id)entryWithMod:(Mod *)baseMod allMods:(NSArray *)allMods;
- (id)initWithTitle:(NSString *)aTitle object:(id)anObject icon:(id)anIcon isHeader:(BOOL)aHeader;
- (void)addChild:(id)child;
-
+- (NSURL *)url;
@end
diff --git a/OpenRA.Launcher.Mac/SidebarEntry.m b/OpenRA.Launcher.Mac/SidebarEntry.m
index b1324a984d..32e42c1ee4 100644
--- a/OpenRA.Launcher.Mac/SidebarEntry.m
+++ b/OpenRA.Launcher.Mac/SidebarEntry.m
@@ -68,6 +68,22 @@
[children addObject:child];
}
+- (BOOL)shouldSelect
+{
+ return [object shouldSelect];
+}
+
+- (NSURL *)url
+{
+ if (object == nil)
+ {
+ NSLog(@"object is nil");
+ return nil;
+ }
+
+ return [object pageURL];
+}
+
- (void) dealloc
{
[title release]; title = nil;
diff --git a/mods/cnc/mod.html b/mods/cnc/mod.html
new file mode 100644
index 0000000000..ded663f982
--- /dev/null
+++ b/mods/cnc/mod.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
Latest News
+
+
Version XXYYZZ Available
+
+ - Cool feature one
+ - Cool feature two
+ - Bugfixes!!!
+
+
+
+
+
+
+
+
+
+
+