Created
July 3, 2010 06:37
-
-
Save Me1000/462368 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* AppController.j | |
* imdbdemo | |
* | |
* Created by Randy Luecke on July 2, 2010. | |
* Copyright 2010, RCLConcepts, LLC All rights reserved. | |
*/ | |
@import <Foundation/CPObject.j> | |
@import <AppKit/CPScrollView.j> | |
@import <AppKit/CPTableView.j> | |
@import <AppKit/CPTableColumn.j> | |
@implementation AppController : CPObject | |
{ | |
CPDictionary data; | |
} | |
- (void)applicationDidFinishLaunching:(CPNotification)aNotification | |
{ | |
// convert the data to make it easier to deal with | |
data = [ ]; | |
// loop through everything and create a dictionary in place of the JSObject adding it to the array | |
for (var i = 0; i < window.DATA.length; i++) | |
data[i] = [CPDictionary dictionaryWithJSObject:window.DATA[i] recursively:NO]; | |
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], | |
contentView = [theWindow contentView], | |
bounds = [contentView bounds]; | |
[contentView setBackgroundColor:[CPColor colorWithHexString:"d7d6d8"]]; | |
var label = [[CPTextField alloc] initWithFrame:CGRectMake(15, 15, 0,0)]; | |
[label setStringValue:"IMDB Ratings"]; | |
[label setFont:[CPFont boldSystemFontOfSize:24]]; | |
[label setTextColor:[CPColor whiteColor]]; | |
[label setTextShadowColor:[CPColor blackColor]]; | |
[label setTextShadowOffset:CGSizeMake(1,1)]; | |
[label sizeToFit]; | |
[contentView addSubview:label]; | |
// give the scrollview a 15px margin on all sides to conform with the HIG | |
var start = CGRectGetMaxY([label frame]) + 15, | |
scroll = [[CPScrollView alloc] initWithFrame:CGRectMake(0, start, bounds.size.width, bounds.size.height - start)], | |
table = [[CPTableView alloc] initWithFrame:CGRectMakeZero()]; | |
// the delegate is notified about behavior stuff | |
[table setDelegate:self]; | |
// the data source gives the tableview all it's data | |
[table setDataSource:self]; | |
[table setAllowsMultipleSelection:YES]; | |
[table setUsesAlternatingRowBackgroundColors:YES]; | |
// in order to use Drag and Drop we register for items of the type "myItems" | |
[table registerForDraggedTypes:["myItems"]]; | |
// We add columns like so | |
var column = [[CPTableColumn alloc] initWithIdentifier:"title"], | |
descriptor = [CPSortDescriptor sortDescriptorWithKey:"title" ascending:NO]; // this is used for sorting | |
[[column headerView] setStringValue:"Title"]; | |
[column setWidth:555.0]; // you can also set a min/max width if you want | |
// apply the sort descriptor to this column so it knows how to sort. | |
[column setSortDescriptorPrototype:descriptor]; | |
// finally add it to the table | |
[table addTableColumn:column]; | |
// we do this two more times | |
var column2 = [[CPTableColumn alloc] initWithIdentifier:"rating"], | |
descriptor = [CPSortDescriptor sortDescriptorWithKey:"rating" ascending:NO]; | |
[[column2 headerView] setStringValue:"Rating"]; | |
[column2 setWidth:150.0]; | |
[column2 setSortDescriptorPrototype:descriptor]; | |
[table addTableColumn:column2]; | |
var column3 = [[CPTableColumn alloc] initWithIdentifier:"votes"], | |
descriptor = [CPSortDescriptor sortDescriptorWithKey:"votes" ascending:NO]; | |
[[column3 headerView] setStringValue:"Votes"]; | |
[column3 setWidth:150.0]; | |
[column3 setSortDescriptorPrototype:descriptor]; | |
[table addTableColumn:column3]; | |
// when then tell the scrollview that it needs to scroll the tableview | |
[scroll setDocumentView:table]; | |
// and resize so that it fills the screen always | |
[scroll setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable]; | |
// and who wants scroll bars when they're not needed? | |
[scroll setAutohidesScrollers:YES]; | |
// finally add the scrollview to the window's contentview | |
[contentView addSubview:scroll]; | |
// bring the window to the front. | |
[theWindow orderFront:self]; | |
} | |
// since the app controller is the data source we must implement a couple of required data source methods | |
// first the data source is asked how many rows the tableview contains | |
- (int)numberOfRowsInTableView:(CPTableView)atableView | |
{ | |
return [data count]; | |
} | |
// Then the data source needs to supply the data to the tableview. | |
- (id)tableView:(CPTableView)aTableView objectValueForTableColumn:(CPTableColumn)aColumn row:(int)aRow | |
{ | |
// the key is the identifier we assigned to the column | |
var key = [aColumn identifier]; | |
// the object at our specific row is what we want, but we want a specific value from that dictionary. | |
return [data[aRow] objectForKey:key]; | |
} | |
// when the sort descriptor changes we need to sort our data | |
- (void)tableView:(CPTableView)aTableView sortDescriptorsDidChange:(CPArray)oldDescriptors | |
{ | |
// first we figure out how we're suppose to sort, then sort the data array | |
var newDescriptors = [aTableView sortDescriptors]; | |
[data sortUsingDescriptors:newDescriptors]; | |
// the reload the table data | |
[aTableView reloadData]; | |
} | |
// when you drag a row (or group of rows) the datasource writes the values to the pasteboard and returns wheter or not to allow the drag. | |
- (BOOL)tableView:(CPTableView)aTableView writeRowsWithIndexes:(CPIndexSet)rowIndexes toPasteboard:(CPPasteboard)pboard | |
{ | |
// using the keyed archiver we archive the data; in this case the row indexes we're dragging | |
var encodedData = [CPKeyedArchiver archivedDataWithRootObject:rowIndexes]; | |
// we then declare the pasteboard types | |
[pboard declareTypes:["myItems"] owner:self]; | |
// and then set the data to the pasteboard | |
[pboard setData:encodedData forType:"myItems"]; | |
// and return YES to allow the drag. | |
return YES; | |
} | |
// as you drag the tableview needs to validate the drop | |
- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id)info proposedRow:(CPInteger)row proposedDropOperation:(CPTableViewDropOperation)operation | |
{ | |
// with this method you can set whether you're dropping ABOVE or ON (as in on top of) the row of your choosing. | |
[aTableView setDropRow:row dropOperation:CPTableViewDropAbove]; | |
// you then return the drag operation (move, copy, none, etc) | |
return CPDragOperationMove; | |
} | |
// when you finally drop on the tableview this method is called | |
- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id)info row:(int)row dropOperation:(CPTableViewDropOperation)operation | |
{ | |
// get the data you added to your pasteboard | |
var pboard = [info draggingPasteboard], | |
rowData = [pboard dataForType:"myItems"]; | |
rowData = [CPKeyedUnarchiver unarchiveObjectWithData:rowData]; | |
// we're using the method we added via a category below to move items around the array | |
[data moveIndexes:rowData toIndex:row]; | |
// if the number of rows were to change (i.e. you dropped items onto the tablview from someowhere else, rather than reordering them) | |
// then you would want to call reloadData in order to select the correct indexes in the following methods | |
//[aTableView reloadData]; | |
// then we want to select the row indexes we just dropped | |
var destIndexes = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(row, [rowData count])]; | |
[aTableView selectRowIndexes:destIndexes byExtendingSelection:NO]; | |
// returning YES tells the tableview to reload the data and completes the drop. | |
return YES; | |
} | |
@end | |
// a simple helper extention to CPArray to make it easier to move indexes around. | |
@implementation CPArray (MoveIndexes) | |
- (void)moveIndexes:(CPIndexSet)indexes toIndex:(int)insertIndex | |
{ | |
var aboveCount = 0, | |
object, | |
removeIndex; | |
var index = [indexes lastIndex]; | |
while (index != CPNotFound) | |
{ | |
if (index >= insertIndex) | |
{ | |
removeIndex = index + aboveCount; | |
aboveCount ++; | |
} | |
else | |
{ | |
removeIndex = index; | |
insertIndex --; | |
} | |
object = [self objectAtIndex:removeIndex]; | |
[self removeObjectAtIndex:removeIndex]; | |
[self insertObject:object atIndex:insertIndex]; | |
index = [indexes indexLessThanIndex:index]; | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment