List installed mods in the sidebar. Changes utility mod info syntax.

This commit is contained in:
Paul Chote
2010-11-16 14:33:47 +13:00
parent 16dd07bab3
commit 7271dd5248
9 changed files with 199 additions and 66 deletions

View File

@@ -16,6 +16,5 @@
GameInstall *game; GameInstall *game;
IBOutlet NSOutlineView *outlineView; IBOutlet NSOutlineView *outlineView;
} }
- (ModEntry *)modTree;
- (IBAction)launchGame:(id)sender; - (IBAction)launchGame:(id)sender;
@end @end

View File

@@ -15,8 +15,9 @@
- (void) awakeFromNib - (void) awakeFromNib
{ {
game = [[GameInstall alloc] initWithPath:@"/Users/paul/src/OpenRA"];
sidebarItems = [[ModEntry headerWithTitle:@""] retain]; sidebarItems = [[ModEntry headerWithTitle:@""] retain];
[sidebarItems addChild:[self modTree]]; [sidebarItems addChild:[game modTree]];
NSTableColumn *col = [outlineView tableColumnWithIdentifier:@"mods"]; NSTableColumn *col = [outlineView tableColumnWithIdentifier:@"mods"];
ImageAndTextCell *imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease]; ImageAndTextCell *imageAndTextCell = [[[ImageAndTextCell alloc] init] autorelease];
@@ -25,8 +26,6 @@
[outlineView reloadData]; [outlineView reloadData];
[outlineView expandItem:[outlineView itemAtRow:1] expandChildren:YES]; [outlineView expandItem:[outlineView itemAtRow:1] expandChildren:YES];
[outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO]; [outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
game = [[GameInstall alloc] initWithPath:@"/Users/paul/src/OpenRA"];
} }
- (void) dealloc - (void) dealloc
@@ -35,24 +34,6 @@
[super dealloc]; [super dealloc];
} }
- (ModEntry *)modTree
{
// Create root item
ModEntry *rootItem = [ModEntry headerWithTitle:@"MODS"];
NSString* imageName = [[NSBundle mainBundle] pathForResource:@"OpenRA" ofType:@"icns"];
NSImage* imageObj = [[NSImage alloc] initWithContentsOfFile:imageName];
NSDictionary *foo = [NSDictionary dictionaryWithObjectsAndKeys:
@"Test mod", @"Title",
@"Foobar", @"Author",
imageObj, @"Icon",
nil];
[imageObj release];
[rootItem addChild:[ModEntry modWithFields:foo]];
return rootItem;
}
#pragma mark Sidebar Datasource and Delegate #pragma mark Sidebar Datasource and Delegate
- (int)outlineView:(NSOutlineView *)anOutlineView numberOfChildrenOfItem:(id)item - (int)outlineView:(NSOutlineView *)anOutlineView numberOfChildrenOfItem:(id)item
{ {
@@ -100,7 +81,12 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item; - (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
{ {
// don't allow headers to be selected // don't allow headers to be selected
return ![item isHeader]; if ([item isHeader])
return NO;
// TODO: Display the webpage
return YES;
} }
- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item - (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item

View File

@@ -13,7 +13,7 @@
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<integer value="57"/> <integer value="57"/>
<integer value="371"/> <integer value="557"/>
</object> </object>
<object class="NSArray" key="IBDocument.PluginDependencies"> <object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
@@ -295,7 +295,7 @@
<object class="NSOutlineView" id="87877668"> <object class="NSOutlineView" id="87877668">
<reference key="NSNextResponder" ref="162526188"/> <reference key="NSNextResponder" ref="162526188"/>
<int key="NSvFlags">256</int> <int key="NSvFlags">256</int>
<string key="NSFrameSize">{144, 468}</string> <string key="NSFrameSize">{188, 468}</string>
<reference key="NSSuperview" ref="162526188"/> <reference key="NSSuperview" ref="162526188"/>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
<object class="_NSCornerView" key="NSCornerView"> <object class="_NSCornerView" key="NSCornerView">
@@ -307,7 +307,7 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSTableColumn" id="196480461"> <object class="NSTableColumn" id="196480461">
<string key="NSIdentifier">mods</string> <string key="NSIdentifier">mods</string>
<double key="NSWidth">141</double> <double key="NSWidth">185</double>
<double key="NSMinWidth">16</double> <double key="NSMinWidth">16</double>
<double key="NSMaxWidth">1000</double> <double key="NSMaxWidth">1000</double>
<object class="NSTableHeaderCell" key="NSHeaderCell"> <object class="NSTableHeaderCell" key="NSHeaderCell">
@@ -398,7 +398,7 @@
<float key="NSOutlineViewIndentationPerLevelKey">14</float> <float key="NSOutlineViewIndentationPerLevelKey">14</float>
</object> </object>
</object> </object>
<string key="NSFrame">{{1, 1}, {144, 468}}</string> <string key="NSFrame">{{1, 1}, {188, 468}}</string>
<reference key="NSSuperview" ref="183995183"/> <reference key="NSSuperview" ref="183995183"/>
<reference key="NSNextKeyView" ref="87877668"/> <reference key="NSNextKeyView" ref="87877668"/>
<reference key="NSDocView" ref="87877668"/> <reference key="NSDocView" ref="87877668"/>
@@ -425,7 +425,7 @@
<double key="NSPercent">0.99295777082443237</double> <double key="NSPercent">0.99295777082443237</double>
</object> </object>
</object> </object>
<string key="NSFrameSize">{146, 470}</string> <string key="NSFrameSize">{190, 470}</string>
<reference key="NSSuperview" ref="488988116"/> <reference key="NSSuperview" ref="488988116"/>
<reference key="NSNextKeyView" ref="162526188"/> <reference key="NSNextKeyView" ref="162526188"/>
<int key="NSsFlags">562</int> <int key="NSsFlags">562</int>
@@ -435,7 +435,7 @@
<bytes key="NSScrollAmts">QSAAAEEgAABBoAAAQaAAAA</bytes> <bytes key="NSScrollAmts">QSAAAEEgAABBoAAAQaAAAA</bytes>
</object> </object>
</object> </object>
<string key="NSFrameSize">{145, 469}</string> <string key="NSFrameSize">{189, 469}</string>
<reference key="NSSuperview" ref="991115689"/> <reference key="NSSuperview" ref="991115689"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSClassName">NSView</string> <string key="NSClassName">NSView</string>
@@ -447,8 +447,8 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSButton" id="430464371"> <object class="NSButton" id="430464371">
<reference key="NSNextResponder" ref="257490795"/> <reference key="NSNextResponder" ref="257490795"/>
<int key="NSvFlags">268</int> <int key="NSvFlags">289</int>
<string key="NSFrame">{{383, 15}, {111, 27}}</string> <string key="NSFrame">{{339, 19}, {111, 27}}</string>
<reference key="NSSuperview" ref="257490795"/> <reference key="NSSuperview" ref="257490795"/>
<bool key="NSEnabled">YES</bool> <bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="492098390"> <object class="NSButtonCell" key="NSCell" id="492098390">
@@ -466,7 +466,7 @@
</object> </object>
</object> </object>
</object> </object>
<string key="NSFrame">{{146, 0}, {513, 469}}</string> <string key="NSFrame">{{190, 0}, {469, 469}}</string>
<reference key="NSSuperview" ref="991115689"/> <reference key="NSSuperview" ref="991115689"/>
<int key="NSViewLayerContentsRedrawPolicy">2</int> <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSClassName">NSView</string> <string key="NSClassName">NSView</string>
@@ -1089,7 +1089,7 @@
<integer value="1"/> <integer value="1"/>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSAffineTransform"> <object class="NSAffineTransform">
<bytes key="NSTransformStruct">P4AAAL+AAABDnQAAw6CAAA</bytes> <bytes key="NSTransformStruct">P4AAAL+AAABDv4AAwiAAAA</bytes>
</object> </object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string>

View File

@@ -1,18 +1,21 @@
// /*
// GameInstall.h * Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
// OpenRA * 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
// Created by Paul Chote on 15/11/10. * as published by the Free Software Foundation. For more information,
// Copyright 2010 __MyCompanyName__. All rights reserved. * see LICENSE.
// */
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
@class ModEntry;
@interface GameInstall : NSObject { @interface GameInstall : NSObject {
NSString *gamePath; NSString *gamePath;
NSMutableString *utilityBuffer;
} }
-(id)initWithPath:(NSString *)path; -(id)initWithPath:(NSString *)path;
- (ModEntry *)modTree;
-(void)launchGame; -(void)launchGame;
- (void)runUtilityApp:(NSString *)arg handleOutput:(id)obj withMethod:(SEL)sel;
@end @end

View File

@@ -1,13 +1,13 @@
// /*
// GameInstall.m * Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
// OpenRA * 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
// Created by Paul Chote on 15/11/10. * as published by the Free Software Foundation. For more information,
// Copyright 2010 __MyCompanyName__. All rights reserved. * see LICENSE.
// */
#import "GameInstall.h" #import "GameInstall.h"
#import "ModEntry.h"
@implementation GameInstall @implementation GameInstall
@@ -16,13 +16,98 @@
self = [super init]; self = [super init];
if (self != nil) if (self != nil)
{ {
NSLog(@"creating game at path %@",path);
gamePath = path; gamePath = path;
} }
return self; 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]];
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"];
NSMutableArray *ret = [NSMutableArray array];
NSMutableDictionary *fields = nil;
NSString *current = nil;
for (id l in lines)
{
id line = [l stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (line == nil || [line length] == 0)
continue;
id kv = [line componentsSeparatedByString:@":"];
id key = [kv objectAtIndex:0];
id value = [kv objectAtIndex:1];
if ([key isEqualToString:@"Error"])
{
NSLog(@"Error: %@",value);
continue;
}
if ([key isEqualToString:@"Mod"])
{
// Commit prev mod
if (current != nil)
[ret addObject:[ModEntry modWithId:current fields:fields]];
NSLog(@"Parsing mod %@",value);
current = value;
fields = [NSMutableDictionary dictionary];
}
if (fields != nil)
[fields setObject:[value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]
forKey:key];
}
return ret;
}
- (ModEntry *)modTree
{
// Get info for all installed mods
id modnames = [self installedMods];
NSArray *allMods = [self infoForMods:modnames];
ModEntry *rootItem = [ModEntry headerWithTitle:@"MODS"];
for (id aMod in allMods)
{
if ([aMod standalone])
{
[rootItem addChild:aMod];
[aMod buildChildTree:allMods];
}
}
return rootItem;
}
-(void)launchGame -(void)launchGame
{ {
// Use LaunchServices because neither NSTask or NSWorkspace support Info.plist _and_ arguments pre-10.6 // Use LaunchServices because neither NSTask or NSWorkspace support Info.plist _and_ arguments pre-10.6
@@ -49,4 +134,27 @@
if (err == noErr) if (err == noErr)
SetFrontProcess(&psn); SetFrontProcess(&psn);
} }
- (void)runUtilityApp:(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:gamePath];
[aTask setLaunchPath:@"/Library/Frameworks/Mono.framework/Commands/mono"];
[aTask setArguments:taskArgs];
[aTask setStandardOutput:aPipe];
[aTask launch];
NSData *inData = nil;
while ((inData = [readHandle availableData]) && [inData length])
[obj performSelector:sel withObject:[NSString stringWithUTF8String:[inData bytes]]];
[aTask release];
}
@end @end

View File

@@ -10,6 +10,7 @@
@interface ModEntry : NSObject { @interface ModEntry : NSObject {
BOOL isHeader; BOOL isHeader;
NSString *mod;
NSString *title; NSString *title;
NSString *version; NSString *version;
NSString *author; NSString *author;
@@ -20,6 +21,7 @@
} }
@property (readonly) BOOL isHeader; @property (readonly) BOOL isHeader;
@property (readonly) NSString *mod;
@property (readonly) NSString *title; @property (readonly) NSString *title;
@property (readonly) NSString *version; @property (readonly) NSString *version;
@property (readonly) NSString *author; @property (readonly) NSString *author;
@@ -30,8 +32,10 @@
@property (readonly) NSImage* icon; @property (readonly) NSImage* icon;
+ (id)headerWithTitle:(NSString *)aTitle; + (id)headerWithTitle:(NSString *)aTitle;
+ (id)modWithFields:(id)fields; + (id)errorWithTitle:(NSString *)aTitle;
- (id)initWithFields:(NSDictionary *)fields isHeader:(BOOL)header; + (id)modWithId:(NSString *)mid fields:(id)fields;
- (id)initWithId:(NSString *)mod fields:(NSDictionary *)fields isHeader:(BOOL)header;
- (void)addChild:(id)child; - (void)addChild:(id)child;
- (void)buildChildTree:(NSArray *)allMods;
- (id)icon; - (id)icon;
@end @end

View File

@@ -10,6 +10,7 @@
@implementation ModEntry @implementation ModEntry
@synthesize mod;
@synthesize isHeader; @synthesize isHeader;
@synthesize title; @synthesize title;
@synthesize version; @synthesize version;
@@ -22,31 +23,44 @@
+ (id)headerWithTitle:(NSString *)aTitle + (id)headerWithTitle:(NSString *)aTitle
{ {
id newObject = [[self alloc] initWithFields:[NSDictionary dictionaryWithObject:aTitle forKey:@"Title"] isHeader:YES]; id newObject = [[self alloc] initWithId:@"title" fields:[NSDictionary dictionaryWithObject:aTitle forKey:@"Title"] isHeader:YES];
[newObject autorelease]; [newObject autorelease];
return newObject; return newObject;
} }
+ (id)modWithFields:(id)fields + (id)errorWithTitle:(NSString *)aTitle
{ {
id newObject = [[self alloc] initWithFields:fields isHeader:NO]; id newObject = [[self alloc] initWithId:@"error" fields:[NSDictionary dictionaryWithObject:aTitle forKey:@"Title"] isHeader:NO];
[newObject autorelease]; [newObject autorelease];
return newObject; return newObject;
} }
- (id)initWithFields:(NSDictionary *)fields isHeader:(BOOL)header + (id)modWithId:(NSString *)mod fields:(id)fields
{
id newObject = [[self alloc] initWithId:mod fields:fields isHeader:NO];
[newObject autorelease];
return newObject;
}
- (id)initWithId:(NSString *)anId fields:(NSDictionary *)fields isHeader:(BOOL)header
{ {
self = [super init]; self = [super init];
if (self) if (self)
{ {
mod = anId;
isHeader = header; isHeader = header;
title = [fields objectForKey:@"Title"]; title = [[fields objectForKey:@"Title"] retain];
version = [fields objectForKey:@"Version"]; version = [[fields objectForKey:@"Version"] retain];
author = [fields objectForKey:@"Author"]; author = [[fields objectForKey:@"Author"] retain];
description = [fields objectForKey:@"Description"]; description = [[fields objectForKey:@"Description"] retain];
requires = [fields objectForKey:@"Requires"]; requires = [[fields objectForKey:@"Requires"] retain];
standalone = ([fields objectForKey:@"Standalone"] == @"True"); standalone = ([[fields objectForKey:@"Standalone"] isEqualToString:@"True"]);
icon = [[fields objectForKey:@"Icon"] retain];
if (!isHeader)
{
NSString* imageName = [[NSBundle mainBundle] pathForResource:@"OpenRA" ofType:@"icns"];
icon = [[NSImage alloc] initWithContentsOfFile:imageName];
}
children = [[NSMutableArray alloc] init]; children = [[NSMutableArray alloc] init];
} }
return self; return self;
@@ -54,11 +68,29 @@
- (void)addChild:(ModEntry *)child - (void)addChild:(ModEntry *)child
{ {
NSLog(@"Adding child %@ to %@",[child mod], mod);
[children addObject:child]; [children addObject:child];
} }
- (void)buildChildTree:(NSArray *)allMods
{
for (id aMod in allMods)
{
if (![[aMod requires] isEqualToString:mod])
continue;
[self addChild:aMod];
[aMod buildChildTree:allMods];
}
}
- (void) dealloc - (void) dealloc
{ {
[title release]; title = nil;
[version release]; version = nil;
[author release]; author = nil;
[description release]; description = nil;
[requires release]; requires = nil;
[icon release]; icon = nil; [icon release]; icon = nil;
[super dealloc]; [super dealloc];
} }

View File

@@ -42,7 +42,7 @@ namespace OpenRA.Utility
return; return;
} }
Console.WriteLine("{0}:", m); Console.WriteLine("Mod:{0}", m);
Console.WriteLine(" Title: {0}", mod.Title); Console.WriteLine(" Title: {0}", mod.Title);
Console.WriteLine(" Version: {0}", mod.Version); Console.WriteLine(" Version: {0}", mod.Version);
Console.WriteLine(" Author: {0}", mod.Author); Console.WriteLine(" Author: {0}", mod.Author);

View File

@@ -2,7 +2,8 @@ Metadata:
Title: C&C Title: C&C
Description: OpenRA Reimagining of the classic game Description: OpenRA Reimagining of the classic game
Version: a0001 Version: a0001
Author: The OpenRA Developers
Standalone: true
Folders: Folders:
. .
mods/cnc mods/cnc