Rev 6408 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"** R.app Copyright notes:* Copyright (C) 2004-5 The R Foundation* written by Stefano M. Iacus and Simon Urbanek*** R Copyright notes:* Copyright (C) 1995-1996 Robert Gentleman and Ross Ihaka* Copyright (C) 1998-2012 The R Development Core Team* Copyright (C) 2002-2004 The R Foundation** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** A copy of the GNU General Public License is available via WWW at* http://www.gnu.org/copyleft/gpl.html. You can also obtain it by* writing to the Free Software Foundation, Inc., 59 Temple Place,* Suite 330, Boston, MA 02111-1307 USA.*/#import "DataManager.h"#import "RController.h"#import "REngine/REngine.h"#import "RegexKitLite.h"#import <WebKit/WebKit.h>#import <WebKit/WebFrame.h>#define kDataManagerData @"data"#define kDataManagerPackage @"package"#define kDataManagerDescription @"description"#define kDataManagerURL @"URL"#define kSortModeNone 0#define kSortModeAsc 1#define kSortModeDesc 2static DataManager* sharedController;@implementation DataManager+ (DataManager*) sharedController{return sharedController;}- (void)awakeFromNib{[RDataSource setDoubleAction:@selector(loadRData:)];[dataInfoView setFrameLoadDelegate:self];[self enableGUIActions:NO];}- (id)init{self = [super init];if (self) {sharedController = self;datasets = [[NSMutableArray alloc] initWithCapacity:500];filteredDatasets = [[NSMutableArray alloc] initWithCapacity:500];sortMode = kSortModeNone;sortedColumn = nil;}return self;}- (void)dealloc {if(datasets) [datasets release], datasets = nil;if(filteredDatasets) [filteredDatasets release], filteredDatasets = nil;[super dealloc];}#pragma mark -- (NSWindow*)window{return DataManagerWindow;}- (void)show{[RDataSource reloadData];[DataManagerWindow makeKeyAndOrderFront:self];}#pragma mark -- (void)updateDatasets:(int)count withNames:(char**)name descriptions:(char**)desc packages:(char**)pkg URLs:(char**)url{[self enableGUIActions:NO];[[self window] display];[self show];[self resetDatasets];NSInteger i = 0;for(i = 0; i < count; i++) {NSDictionary *entry = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithUTF8String: name[i]], kDataManagerData,[NSString stringWithUTF8String: desc[i]], kDataManagerDescription,[NSString stringWithUTF8String: pkg[i]], kDataManagerPackage,[NSString stringWithUTF8String: url[i]], kDataManagerURL,nil];[datasets addObject:entry];[filteredDatasets addObject:entry];}[self filterTable:nil];[RDataSource reloadData];[self enableGUIActions:YES];}- (void)resetDatasets{[datasets removeAllObjects];[filteredDatasets removeAllObjects];}- (NSInteger)count{return [datasets count];}- (void)enableGUIActions:(BOOL)enabled{[loadButton setEnabled:enabled];[refreshButton setEnabled:enabled];[searchField setEnabled:enabled];[RDataSource setEnabled:enabled];}#pragma mark -- (IBAction)loadRData:(id)sender{NSIndexSet *selectedRows = [RDataSource selectedRowIndexes];if(![selectedRows count]) return;NSInteger anIndex = [selectedRows firstIndex];NSMutableArray *data = [[NSMutableArray alloc] initWithCapacity:[selectedRows count]];NSMutableArray *pkgs = [[NSMutableArray alloc] initWithCapacity:[selectedRows count]];while(anIndex != NSNotFound) {[data addObject:[[filteredDatasets objectAtIndex:anIndex] objectForKey:kDataManagerData]];[pkgs addObject:[[filteredDatasets objectAtIndex:anIndex] objectForKey:kDataManagerPackage]];anIndex = [selectedRows indexGreaterThanIndex:anIndex];}[[REngine mainEngine] evaluateString:[NSString stringWithFormat:@"data(%@,package=c(\"%@\"))",[data componentsJoinedByString:@","],[pkgs componentsJoinedByString:@"\",\""]]];}- (IBAction)filterTable:(id)sender{NSString *searchPattern = [searchField stringValue];if(![searchPattern length]) {[filteredDatasets setArray:datasets];[RDataSource deselectAll:nil];} else {NSPredicate *predicate = [NSPredicate predicateWithFormat:@"data CONTAINS[cd] %@ OR package CONTAINS[cd] %@ OR description CONTAINS[cd] %@",searchPattern, searchPattern, searchPattern];[filteredDatasets setArray:[datasets filteredArrayUsingPredicate:predicate]];}if(sortedColumn) {[RDataSource setIndicatorImage:(sortMode == kSortModeAsc) ? [NSImage imageNamed:@"NSAscendingSortIndicator"] : [NSImage imageNamed:@"NSDescendingSortIndicator"] inTableColumn:[RDataSource tableColumnWithIdentifier:sortedColumn]];[RDataSource setHighlightedTableColumn:[RDataSource tableColumnWithIdentifier:sortedColumn]];NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortedColumn ascending:(sortMode == kSortModeAsc)selector:@selector(localizedCaseInsensitiveCompare:)];[filteredDatasets sortUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];[sortDescriptor release];}[RDataSource reloadData];}- (IBAction)reloadDatasets:(id)sender{[self enableGUIActions:NO];[[self window] display];[[REngine mainEngine] executeString:@"data.manager()"];}- (IBAction)showHelp:(id)sender{if([RDataSource numberOfSelectedRows] != 1) return;NSInteger row = [RDataSource selectedRow];NSDictionary *selectedItem = [filteredDatasets objectAtIndex:row];SLog(@"DataManager showHelp: %@", selectedItem);NSString *urlText = nil;int port = [[RController sharedController] helpServerPort];if (port == 0) {NSRunInformationalAlertPanel(NLS(@"Cannot start HTML help server."), NLS(@"Help"), NLS(@"Ok"), nil, nil);return;}NSString *topic = [selectedItem objectForKey:kDataManagerData];NSRange r = [topic rangeOfString:@" ("];if (r.length > 0 && [topic length] - r.length > 3) // some datasets have the topic in parentstopic = [topic substringWithRange: NSMakeRange(r.location + 2, [topic length] - r.location - 3)];urlText = [NSString stringWithFormat:@"http://127.0.0.1:%d/library/%@/html/%@.html", port, [selectedItem objectForKey:kDataManagerPackage], topic];[[dataInfoView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlText]]];}- (IBAction)printDocument:(id)sender{[NSObject cancelPreviousPerformRequestsWithTarget:selfselector:@selector(showHelp:)object:RDataSource];NSPrintInfo *printInfo;NSPrintOperation *printOp;printInfo = [NSPrintInfo sharedPrintInfo];[printInfo setHorizontalPagination: NSFitPagination];[printInfo setVerticalPagination: NSAutoPagination];[printInfo setVerticallyCentered:NO];printOp = [NSPrintOperation printOperationWithView:[[[dataInfoView mainFrame] frameView] documentView]printInfo:printInfo];[printOp setShowPanels:YES];[printOp runOperationModalForWindow:[self window]delegate:selfdidRunSelector:@selector(sheetDidEnd:returnCode:contextInfo:)contextInfo:@""];}- (IBAction)executeSelection:(id)sender{DOMRange *dr = [dataInfoView selectedDOMRange];if (dr) { /* we don't do line-exec since we don't get the text outside the selection */NSString *stx = [dr markupString];// Ok, some simple processing here - it may not work in all casesstx = [stx stringByReplacingOccurrencesOfRegex:@"(?i)<br[^>]*?>" withString:@"\n"];stx = [stx stringByReplacingOccurrencesOfRegex:@"<[^>]*?>" withString:@""];stx = [stx stringByReplacingOccurrencesOfString:@"<" withString:@"<"];stx = [stx stringByReplacingOccurrencesOfString:@">" withString:@">"];stx = [stx stringByReplacingOccurrencesOfString:@"&" withString:@"&"];[[RController sharedController] sendInput:stx];}}#pragma mark -#pragma mark tableView delegates- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{return [filteredDatasets count];}- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex{if([[tableColumn identifier] isEqualToString:kDataManagerPackage])return [[filteredDatasets objectAtIndex:rowIndex] objectForKey:kDataManagerPackage];else if([[tableColumn identifier] isEqualToString:kDataManagerData])return [[filteredDatasets objectAtIndex:rowIndex] objectForKey:kDataManagerData];else if([[tableColumn identifier] isEqualToString:kDataManagerDescription])return [[filteredDatasets objectAtIndex:rowIndex] objectForKey:kDataManagerDescription];return @"...";}- (BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex{return NO;}- (void)tableViewSelectionDidChange:(NSNotification *)aNotification{// Check our notification object is our tableif ([aNotification object] != RDataSource) return;// Update Info delayed[NSObject cancelPreviousPerformRequestsWithTarget:selfselector:@selector(showHelp:)object:RDataSource];[self performSelector:@selector(showHelp:) withObject:RDataSource afterDelay:0.5];}- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)tableColumn{[tableView deselectAll:nil];// Tri-state sorting none -> asc -> desc -> none -> ...if(!sortedColumn || (sortedColumn && [sortedColumn isEqualToString:[tableColumn identifier]])) {sortMode++;if (sortMode > kSortModeDesc) sortMode = kSortModeNone;} else {sortMode = kSortModeAsc;}// remove sort indicator of old columnif(sortedColumn) {[self filterTable:nil];[tableView setIndicatorImage:nil inTableColumn:[tableView tableColumnWithIdentifier:sortedColumn]];}// remember last to be sorted columnsortedColumn = [tableColumn identifier];NSSortDescriptor* sortDescriptor;switch(sortMode) {case kSortModeNone:[tableView setIndicatorImage:nil inTableColumn:tableColumn];[tableView setHighlightedTableColumn:nil];[filteredDatasets removeAllObjects];[filteredDatasets setArray:datasets];sortedColumn = nil;break;case kSortModeAsc:[tableView setIndicatorImage:[NSImage imageNamed:@"NSAscendingSortIndicator"] inTableColumn:tableColumn];[tableView setHighlightedTableColumn:tableColumn];sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortedColumn ascending:YESselector:@selector(localizedCaseInsensitiveCompare:)];[filteredDatasets sortUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];[sortDescriptor release];break;case kSortModeDesc:[tableView setIndicatorImage:[NSImage imageNamed:@"NSDescendingSortIndicator"] inTableColumn:tableColumn];[tableView setHighlightedTableColumn:tableColumn];sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortedColumn ascending:NOselector:@selector(localizedCaseInsensitiveCompare:)];[filteredDatasets sortUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];[sortDescriptor release];break;}[RDataSource reloadData];}#pragma mark -- (void)sheetDidEnd:(id)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo{SLog(@"DataManager: sheetDidEnd: returnCode: %d contextInfo: %@", returnCode, contextInfo);// Order out the sheet - could be a NSPanel or NSWindowif ([sheet respondsToSelector:@selector(orderOut:)]) {[sheet orderOut:nil];}else if ([sheet respondsToSelector:@selector(window)]) {[[sheet window] orderOut:nil];}[DataManagerWindow makeKeyAndOrderFront:nil];}- (BOOL)validateMenuItem:(NSMenuItem *)menuItem{if ([menuItem action] == @selector(executeSelection:)) {return ([dataInfoView selectedDOMRange] == nil) ? NO : YES;}return YES;}@end