The R Project SVN R-packages

Rev

Rev 6408 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
714 iacus 1
/*
2
 *  R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
3
 *  
4
 *  R.app Copyright notes:
1254 iacus 5
 *                     Copyright (C) 2004-5  The R Foundation
714 iacus 6
 *                     written by Stefano M. Iacus and Simon Urbanek
7
 *
8
 *                  
9
 *  R Copyright notes:
10
 *                     Copyright (C) 1995-1996   Robert Gentleman and Ross Ihaka
6408 ripley 11
 *                     Copyright (C) 1998-2012   The R Development Core Team
714 iacus 12
 *                     Copyright (C) 2002-2004   The R Foundation
13
 *
14
 *  This program is free software; you can redistribute it and/or modify
15
 *  it under the terms of the GNU General Public License as published by
16
 *  the Free Software Foundation; either version 2 of the License, or
17
 *  (at your option) any later version.
18
 *
19
 *  This program is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  A copy of the GNU General Public License is available via WWW at
25
 *  http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
26
 *  writing to the Free Software Foundation, Inc., 59 Temple Place,
27
 *  Suite 330, Boston, MA  02111-1307  USA.
28
 */
29
 
568 iacus 30
#import "DataManager.h"
31
#import "RController.h"
816 urbaneks 32
#import "REngine/REngine.h"
5737 urbaneks 33
#import "RegexKitLite.h"
568 iacus 34
 
35
#import <WebKit/WebKit.h>
36
#import <WebKit/WebFrame.h>
37
 
5729 urbaneks 38
#define kDataManagerData          @"data"
39
#define kDataManagerPackage       @"package"
40
#define kDataManagerDescription   @"description"
41
#define kDataManagerURL           @"URL"
568 iacus 42
 
5729 urbaneks 43
#define kSortModeNone 0
44
#define kSortModeAsc  1
45
#define kSortModeDesc 2
46
 
47
static DataManager* sharedController;
48
 
568 iacus 49
@implementation DataManager
50
 
5729 urbaneks 51
+ (DataManager*) sharedController{
52
	return sharedController;
53
}
54
 
568 iacus 55
- (void)awakeFromNib
56
{
688 urbaneks 57
	[RDataSource setDoubleAction:@selector(loadRData:)];
5705 urbaneks 58
	[dataInfoView setFrameLoadDelegate:self];
5729 urbaneks 59
	[self enableGUIActions:NO];
568 iacus 60
}
61
 
62
- (id)init
63
{
5729 urbaneks 64
	self = [super init];
65
	if (self) {
688 urbaneks 66
		sharedController = self;
5729 urbaneks 67
		datasets = [[NSMutableArray alloc] initWithCapacity:500];
68
		filteredDatasets = [[NSMutableArray alloc] initWithCapacity:500];
69
		sortMode = kSortModeNone;
70
		sortedColumn = nil;
568 iacus 71
	}
5729 urbaneks 72
 
73
	return self;
568 iacus 74
}
75
 
76
- (void)dealloc {
5729 urbaneks 77
	if(datasets) [datasets release], datasets = nil;
78
	if(filteredDatasets) [filteredDatasets release], filteredDatasets = nil;
568 iacus 79
	[super dealloc];
80
}
81
 
5729 urbaneks 82
#pragma mark -
83
 
84
- (NSWindow*)window
688 urbaneks 85
{
5729 urbaneks 86
	return DataManagerWindow;
688 urbaneks 87
}
88
 
5729 urbaneks 89
- (void)show
568 iacus 90
{
5729 urbaneks 91
	[RDataSource reloadData];
92
	[DataManagerWindow makeKeyAndOrderFront:self];
93
}
94
 
95
#pragma mark -
96
 
97
- (void)updateDatasets:(int)count withNames:(char**)name descriptions:(char**)desc packages:(char**)pkg URLs:(char**)url
98
{
99
 
100
	[self enableGUIActions:NO];
101
	[[self window] display];
688 urbaneks 102
	[self show];
5729 urbaneks 103
	[self resetDatasets];
104
 
105
	NSInteger i = 0;
106
 
107
	for(i = 0; i < count; i++) {
108
		NSDictionary *entry = [NSDictionary dictionaryWithObjectsAndKeys:
109
			[NSString stringWithUTF8String: name[i]], kDataManagerData,
110
			[NSString stringWithUTF8String: desc[i]], kDataManagerDescription,
111
			[NSString stringWithUTF8String: pkg[i]],  kDataManagerPackage,
112
			[NSString stringWithUTF8String: url[i]],  kDataManagerURL,
113
			nil
114
		];
115
		[datasets addObject:entry];
116
		[filteredDatasets addObject:entry];
117
	}
118
 
119
	[self filterTable:nil];
120
	[RDataSource reloadData];
121
	[self enableGUIActions:YES];
122
 
568 iacus 123
}
124
 
5729 urbaneks 125
- (void)resetDatasets
568 iacus 126
{
5729 urbaneks 127
	[datasets removeAllObjects];
128
	[filteredDatasets removeAllObjects];
568 iacus 129
}
130
 
5729 urbaneks 131
- (NSInteger)count
132
{
133
	return [datasets count];
568 iacus 134
}
135
 
5729 urbaneks 136
- (void)enableGUIActions:(BOOL)enabled
568 iacus 137
{
5729 urbaneks 138
	[loadButton setEnabled:enabled];
139
	[refreshButton setEnabled:enabled];
140
	[searchField setEnabled:enabled];
141
	[RDataSource setEnabled:enabled];
568 iacus 142
}
143
 
5729 urbaneks 144
#pragma mark -
145
 
568 iacus 146
- (IBAction)loadRData:(id)sender
147
{
5729 urbaneks 148
 
149
	NSIndexSet *selectedRows = [RDataSource selectedRowIndexes];
150
 
151
	if(![selectedRows count]) return;
152
 
153
	NSInteger anIndex = [selectedRows firstIndex];
154
	NSMutableArray *data = [[NSMutableArray alloc] initWithCapacity:[selectedRows count]];
155
	NSMutableArray *pkgs = [[NSMutableArray alloc] initWithCapacity:[selectedRows count]];
156
	while(anIndex != NSNotFound) {
157
		[data addObject:[[filteredDatasets objectAtIndex:anIndex] objectForKey:kDataManagerData]];
158
		[pkgs addObject:[[filteredDatasets objectAtIndex:anIndex] objectForKey:kDataManagerPackage]];
159
		anIndex = [selectedRows indexGreaterThanIndex:anIndex];
160
	}
161
	[[REngine mainEngine] evaluateString:[NSString stringWithFormat:@"data(%@,package=c(\"%@\"))",
162
		[data componentsJoinedByString:@","], 
163
		[pkgs componentsJoinedByString:@"\",\""]]];
568 iacus 164
}
165
 
5729 urbaneks 166
- (IBAction)filterTable:(id)sender
167
{
168
 
169
	NSString *searchPattern = [searchField stringValue];
170
 
171
	if(![searchPattern length]) {
172
		[filteredDatasets setArray:datasets];
173
		[RDataSource deselectAll:nil];
174
	} else {
175
		NSPredicate *predicate = [NSPredicate predicateWithFormat:@"data CONTAINS[cd] %@ OR package CONTAINS[cd] %@ OR description CONTAINS[cd] %@", 
176
			searchPattern, searchPattern, searchPattern];
177
		[filteredDatasets setArray:[datasets filteredArrayUsingPredicate:predicate]];
178
	}
179
 
180
	if(sortedColumn) {
181
		[RDataSource setIndicatorImage:(sortMode == kSortModeAsc) ? [NSImage imageNamed:@"NSAscendingSortIndicator"] : [NSImage imageNamed:@"NSDescendingSortIndicator"] inTableColumn:[RDataSource tableColumnWithIdentifier:sortedColumn]];
182
		[RDataSource setHighlightedTableColumn:[RDataSource tableColumnWithIdentifier:sortedColumn]];
183
		NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortedColumn ascending:(sortMode == kSortModeAsc) 
184
			selector:@selector(localizedCaseInsensitiveCompare:)];
185
		[filteredDatasets sortUsingDescriptors:
186
			[NSArray arrayWithObjects:sortDescriptor, nil]];
187
		[sortDescriptor release];
188
	}
189
 
190
 
191
	[RDataSource reloadData];
192
}
193
 
194
- (IBAction)reloadDatasets:(id)sender
195
{
196
	[self enableGUIActions:NO];
197
	[[self window] display];
198
	[[REngine mainEngine] executeString:@"data.manager()"];
199
}
200
 
568 iacus 201
- (IBAction)showHelp:(id)sender
202
{
5729 urbaneks 203
 
204
	if([RDataSource numberOfSelectedRows] != 1) return;
205
 
206
	NSInteger row = [RDataSource selectedRow];
207
 
208
	NSDictionary *selectedItem = [filteredDatasets objectAtIndex:row];
209
 
210
	SLog(@"DataManager showHelp: %@", selectedItem);
211
 
5535 urbaneks 212
	NSString *urlText = nil;
213
	int port = [[RController sharedController] helpServerPort];
214
	if (port == 0) {
215
		NSRunInformationalAlertPanel(NLS(@"Cannot start HTML help server."), NLS(@"Help"), NLS(@"Ok"), nil, nil);
216
		return;
217
	}
5729 urbaneks 218
 
219
	NSString *topic = [selectedItem objectForKey:kDataManagerData];
5535 urbaneks 220
	NSRange r = [topic rangeOfString:@" ("];
221
	if (r.length > 0 && [topic length] - r.length > 3) // some datasets have the topic in parents
222
		topic = [topic substringWithRange: NSMakeRange(r.location + 2, [topic length] - r.location - 3)];
5729 urbaneks 223
 
7337 urbaneks 224
	urlText = [NSString stringWithFormat:@"http://localhost:%d/library/%@/html/%@.html", port, [selectedItem objectForKey:kDataManagerPackage], topic];
5729 urbaneks 225
 
568 iacus 226
	[[dataInfoView mainFrame] loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlText]]];
5729 urbaneks 227
 
568 iacus 228
}
229
 
5729 urbaneks 230
- (IBAction)printDocument:(id)sender
568 iacus 231
{
5729 urbaneks 232
 
233
	[NSObject cancelPreviousPerformRequestsWithTarget:self 
234
							selector:@selector(showHelp:) 
235
							object:RDataSource];
236
 
237
	NSPrintInfo *printInfo;
238
	NSPrintOperation *printOp;
239
 
240
	printInfo = [NSPrintInfo sharedPrintInfo];
241
	[printInfo setHorizontalPagination: NSFitPagination];
242
	[printInfo setVerticalPagination: NSAutoPagination];
243
	[printInfo setVerticallyCentered:NO];
244
 
245
	printOp = [NSPrintOperation printOperationWithView:[[[dataInfoView mainFrame] frameView] documentView] 
246
											 printInfo:printInfo];
247
	[printOp setShowPanels:YES];
248
	[printOp runOperationModalForWindow:[self window] 
249
							   delegate:self 
250
						 didRunSelector:@selector(sheetDidEnd:returnCode:contextInfo:) 
251
						    contextInfo:@""];
568 iacus 252
}
253
 
5737 urbaneks 254
- (IBAction)executeSelection:(id)sender
255
{
256
	DOMRange *dr = [dataInfoView selectedDOMRange];
257
	if (dr) { /* we don't do line-exec since we don't get the text outside the selection */
258
		NSString *stx = [dr markupString];
259
		// Ok, some simple processing here - it may not work in all cases
260
		stx = [stx stringByReplacingOccurrencesOfRegex:@"(?i)<br[^>]*?>" withString:@"\n"];
261
		stx = [stx stringByReplacingOccurrencesOfRegex:@"<[^>]*?>" withString:@""];
262
		stx = [stx stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
263
		stx = [stx stringByReplacingOccurrencesOfString:@"&gt;" withString:@">"];
264
		stx = [stx stringByReplacingOccurrencesOfString:@"&amp;" withString:@"&"];
265
		[[RController sharedController] sendInput:stx];
266
	}
267
}
268
 
5729 urbaneks 269
#pragma mark -
270
#pragma mark tableView delegates
271
 
272
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
688 urbaneks 273
{
5729 urbaneks 274
	return [filteredDatasets count];
688 urbaneks 275
}
276
 
5729 urbaneks 277
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex
278
{
279
	if([[tableColumn identifier] isEqualToString:kDataManagerPackage])
280
		return [[filteredDatasets objectAtIndex:rowIndex] objectForKey:kDataManagerPackage];
281
	else if([[tableColumn identifier] isEqualToString:kDataManagerData])
282
		return [[filteredDatasets objectAtIndex:rowIndex] objectForKey:kDataManagerData];
283
	else if([[tableColumn identifier] isEqualToString:kDataManagerDescription])
284
		return [[filteredDatasets objectAtIndex:rowIndex] objectForKey:kDataManagerDescription];
285
	return @"...";
286
}
287
 
288
- (BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
289
{
290
	return NO;
291
}
292
 
5705 urbaneks 293
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
294
{
295
	// Check our notification object is our table
296
	if ([aNotification object] != RDataSource) return;
297
 
298
	// Update Info delayed
299
	[NSObject cancelPreviousPerformRequestsWithTarget:self 
300
							selector:@selector(showHelp:) 
301
							object:RDataSource];
302
 
303
	[self performSelector:@selector(showHelp:) withObject:RDataSource afterDelay:0.5];
304
 
305
}
306
 
5729 urbaneks 307
- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)tableColumn
5705 urbaneks 308
{
5729 urbaneks 309
 
310
	[tableView deselectAll:nil];
311
 
312
	// Tri-state sorting none -> asc -> desc -> none -> ...
313
	if(!sortedColumn || (sortedColumn && [sortedColumn isEqualToString:[tableColumn identifier]])) {
314
		sortMode++;
315
		if (sortMode > kSortModeDesc) sortMode = kSortModeNone;
316
	} else {
317
		sortMode = kSortModeAsc;
318
	}
319
 
320
	// remove sort indicator of old column
321
	if(sortedColumn) {
322
		[self filterTable:nil];
323
		[tableView setIndicatorImage:nil inTableColumn:[tableView tableColumnWithIdentifier:sortedColumn]];
324
	}
325
 
326
	// remember last to be sorted column
327
	sortedColumn = [tableColumn identifier];
328
 
329
	NSSortDescriptor* sortDescriptor;
330
 
331
	switch(sortMode) {
332
		case kSortModeNone:
333
		[tableView setIndicatorImage:nil inTableColumn:tableColumn];
334
		[tableView setHighlightedTableColumn:nil];
335
		[filteredDatasets removeAllObjects];
336
		[filteredDatasets setArray:datasets];
337
		sortedColumn = nil;
338
		break;
339
		case kSortModeAsc:
340
		[tableView setIndicatorImage:[NSImage imageNamed:@"NSAscendingSortIndicator"] inTableColumn:tableColumn];
341
		[tableView setHighlightedTableColumn:tableColumn];
342
		sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortedColumn ascending:YES 
343
			selector:@selector(localizedCaseInsensitiveCompare:)];
344
		[filteredDatasets sortUsingDescriptors:
345
			[NSArray arrayWithObjects:sortDescriptor, nil]];
346
		[sortDescriptor release];
347
		break;
348
		case kSortModeDesc:
349
		[tableView setIndicatorImage:[NSImage imageNamed:@"NSDescendingSortIndicator"] inTableColumn:tableColumn];
350
		[tableView setHighlightedTableColumn:tableColumn];
351
		sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortedColumn ascending:NO 
352
			selector:@selector(localizedCaseInsensitiveCompare:)];
353
		[filteredDatasets sortUsingDescriptors:
354
			[NSArray arrayWithObjects:sortDescriptor, nil]];
355
		[sortDescriptor release];
356
		break;
357
	}
358
 
359
	[RDataSource reloadData];
360
 
5705 urbaneks 361
}
362
 
5729 urbaneks 363
#pragma mark -
364
 
365
- (void)sheetDidEnd:(id)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo
5705 urbaneks 366
{
367
 
5729 urbaneks 368
	SLog(@"DataManager: sheetDidEnd: returnCode: %d contextInfo: %@", returnCode, contextInfo);
5705 urbaneks 369
 
5729 urbaneks 370
	// Order out the sheet - could be a NSPanel or NSWindow
371
	if ([sheet respondsToSelector:@selector(orderOut:)]) {
372
		[sheet orderOut:nil];
373
	}
374
	else if ([sheet respondsToSelector:@selector(window)]) {
375
		[[sheet window] orderOut:nil];
376
	}
377
 
378
	[DataManagerWindow makeKeyAndOrderFront:nil];
379
 
5705 urbaneks 380
}
381
 
5737 urbaneks 382
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
383
{
384
	if ([menuItem action] == @selector(executeSelection:)) {
385
		return ([dataInfoView selectedDOMRange] == nil) ? NO : YES;
386
	}
387
 
388
	return YES;
389
}
390
 
568 iacus 391
@end