mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-27 05:57:04 +00:00
improved: manual test for treecontroller
This commit is contained in:
@@ -16,9 +16,11 @@
|
||||
|
||||
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
|
||||
{
|
||||
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
|
||||
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(0, 0, 850, 400) styleMask:CPTitledWindowMask | CPClosableWindowMask | CPMiniaturizableWindowMask],
|
||||
contentView = [theWindow contentView];
|
||||
|
||||
[theWindow setTitle:@"CPTreeController Bindings Test"];
|
||||
|
||||
// 1. Create the Data Model
|
||||
var root1 = [[Node alloc] initWithName:@"Root 1" children:[]],
|
||||
child1 = [[Node alloc] initWithName:@"Child 1.1" children:[]],
|
||||
@@ -32,36 +34,39 @@
|
||||
|
||||
// 2. Setup the Tree Controller
|
||||
treeController = [[CPTreeController alloc] init];
|
||||
[treeController setObjectClass:[Node class]];
|
||||
[treeController setChildrenKeyPath:@"children"];
|
||||
[treeController setContent:contentArray];
|
||||
|
||||
// 3. Setup the Outline View
|
||||
var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(20, 20, 250, 300)];
|
||||
[scrollView setAutohidesScrollers:YES];
|
||||
// 3. Setup Outline View 1 (Left)
|
||||
var scrollView1 = [[CPScrollView alloc] initWithFrame:CGRectMake(20, 20, 240, 300)];
|
||||
[scrollView1 setAutohidesScrollers:YES];
|
||||
|
||||
var outlineView = [[CPOutlineView alloc] initWithFrame:CGRectMake(0, 0, 250, 300)];
|
||||
var column = [[CPTableColumn alloc] initWithIdentifier:@"name"];
|
||||
[[column headerView] setStringValue:@"Node Name"];
|
||||
[column setWidth:240];
|
||||
[column setEditable:YES]; // Editable to test bidirectional bindings in the tree
|
||||
|
||||
[outlineView addTableColumn:column];
|
||||
[outlineView setOutlineTableColumn:column];
|
||||
[outlineView setAllowsMultipleSelection:YES];
|
||||
[scrollView setDocumentView:outlineView];
|
||||
[contentView addSubview:scrollView];
|
||||
var outlineView1 = [[CPOutlineView alloc] initWithFrame:CGRectMake(0, 0, 240, 300)],
|
||||
column1 = [[CPTableColumn alloc] initWithIdentifier:@"name"];
|
||||
[[column1 headerView] setStringValue:@"Outline View 1"];
|
||||
[column1 setWidth:230];
|
||||
[column1 setEditable:YES];
|
||||
|
||||
// 4. Establish Bindings for the Outline View
|
||||
[outlineView bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];
|
||||
[outlineView bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil];
|
||||
[outlineView1 addTableColumn:column1];
|
||||
[outlineView1 setOutlineTableColumn:column1];
|
||||
[outlineView1 setAllowsMultipleSelection:YES];
|
||||
[scrollView1 setDocumentView:outlineView1];
|
||||
[contentView addSubview:scrollView1];
|
||||
|
||||
var scrollView2 = [[CPScrollView alloc] initWithFrame:CGRectMake(300, 20, 250, 300)];
|
||||
// Bind Outline View 1 (Content & Selection)
|
||||
[outlineView1 bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];
|
||||
[outlineView1 bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil];
|
||||
|
||||
// 4. Setup Outline View 2 (Middle - Synced)
|
||||
var scrollView2 = [[CPScrollView alloc] initWithFrame:CGRectMake(280, 20, 240, 300)];
|
||||
[scrollView2 setAutohidesScrollers:YES];
|
||||
var outlineView2 = [[CPOutlineView alloc] initWithFrame:CGRectMake(0, 0, 250, 300)];
|
||||
var column2 = [[CPTableColumn alloc] initWithIdentifier:@"name"];
|
||||
[[column2 headerView] setStringValue:@"Node Name"];
|
||||
[column2 setWidth:240];
|
||||
[column2 setEditable:YES]; // Editable to test bidirectional bindings in the tree
|
||||
|
||||
var outlineView2 = [[CPOutlineView alloc] initWithFrame:CGRectMake(0, 0, 240, 300)],
|
||||
column2 = [[CPTableColumn alloc] initWithIdentifier:@"name"];
|
||||
[[column2 headerView] setStringValue:@"Outline View 2 (Synced)"];
|
||||
[column2 setWidth:230];
|
||||
[column2 setEditable:YES];
|
||||
|
||||
[outlineView2 addTableColumn:column2];
|
||||
[outlineView2 setOutlineTableColumn:column2];
|
||||
@@ -69,20 +74,68 @@
|
||||
[scrollView2 setDocumentView:outlineView2];
|
||||
[contentView addSubview:scrollView2];
|
||||
|
||||
// 4. Establish Bindings for the Outline View
|
||||
// Bind Outline View 2 (Content & Selection)
|
||||
[outlineView2 bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];
|
||||
[outlineView2 bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil];
|
||||
|
||||
// 5. Setup Inspector / Detail Controls (Right Panel)
|
||||
var panelX = 540;
|
||||
|
||||
// Label: Detail Inspector
|
||||
var detailLabel = [CPTextField labelWithTitle:@"Detail Binding (selection.name):"];
|
||||
[detailLabel setFrameOrigin:CGPointMake(panelX, 20)];
|
||||
[contentView addSubview:detailLabel];
|
||||
|
||||
// 2-Way Detail Binding TextField
|
||||
var nameField = [CPTextField textFieldWithStringValue:@"" placeholder:@"No Selection" width:260];
|
||||
[nameField setFrameOrigin:CGPointMake(panelX, 45)];
|
||||
[nameField setEditable:YES];
|
||||
[nameField bind:@"value" toObject:treeController withKeyPath:@"selection.name" options:nil];
|
||||
[contentView addSubview:nameField];
|
||||
|
||||
// Programmatic Selection Button
|
||||
var selectBtn = [CPButton buttonWithTitle:@"Select 'Child 1.2' [0, 1]"];
|
||||
[selectBtn setFrame:CGRectMake(panelX, 90, 260, 28)];
|
||||
[selectBtn setTarget:self];
|
||||
[selectBtn setAction:@selector(selectSpecificNode:)];
|
||||
[contentView addSubview:selectBtn];
|
||||
|
||||
// Add Child Button (Action + Enabled Binding)
|
||||
var addChildBtn = [CPButton buttonWithTitle:@"Add Child to Selection"];
|
||||
[addChildBtn setFrame:CGRectMake(panelX, 125, 260, 28)];
|
||||
[addChildBtn setTarget:treeController];
|
||||
[addChildBtn setAction:@selector(addChild:)];
|
||||
[addChildBtn bind:@"enabled" toObject:treeController withKeyPath:@"canAddChild" options:nil];
|
||||
[contentView addSubview:addChildBtn];
|
||||
|
||||
// Remove Selected Button
|
||||
var removeBtn = [CPButton buttonWithTitle:@"Remove Selected"];
|
||||
[removeBtn setFrame:CGRectMake(panelX, 160, 260, 28)];
|
||||
[removeBtn setTarget:treeController];
|
||||
[removeBtn setAction:@selector(remove:)];
|
||||
[contentView addSubview:removeBtn];
|
||||
|
||||
// Selection Log Label
|
||||
var logHeaderLabel = [CPTextField labelWithTitle:@"KVO selectionIndexPaths Log:"];
|
||||
[logHeaderLabel setFrameOrigin:CGPointMake(panelX, 210)];
|
||||
[contentView addSubview:logHeaderLabel];
|
||||
|
||||
logField = [CPTextField labelWithTitle:@"Selected: Root 1"];
|
||||
[logField setFrame:CGRectMake(panelX, 235, 260, 60)];
|
||||
[logField setLineBreakMode:CPLineBreakByWordWrapping];
|
||||
[contentView addSubview:logField];
|
||||
|
||||
// 6. Register Observer for Live Selection Log
|
||||
[treeController addObserver:self forKeyPath:@"selectionIndexPaths" options:CPKeyValueObservingOptionNew context:nil];
|
||||
|
||||
[theWindow center];
|
||||
[theWindow orderFront:self];
|
||||
}
|
||||
|
||||
- (void)selectSpecificNode:(id)sender
|
||||
{
|
||||
// Programmatically select index path [0, 1] which is "Child 1.2"
|
||||
// This tests the `_CPOutlineViewSelectionIndexPathsBinder` auto-expand logic.
|
||||
var path =[CPIndexPath indexPathWithIndexes:[0, 1]];
|
||||
var path = [CPIndexPath indexPathWithIndexes:[0, 1]];
|
||||
[treeController setSelectionIndexPath:path];
|
||||
}
|
||||
|
||||
@@ -94,12 +147,14 @@
|
||||
if ([selectedObjects count] > 0)
|
||||
{
|
||||
var names = [CPMutableArray array];
|
||||
for (var i = 0; i <[selectedObjects count]; i++)
|
||||
[names addObject:[selectedObjects[i] name]];[logField setStringValue:[names componentsJoinedByString:@", "]];
|
||||
for (var i = 0; i < [selectedObjects count]; i++)
|
||||
[names addObject:[selectedObjects[i] name]];
|
||||
|
||||
[logField setStringValue:[CPString stringWithFormat:@"Selected: %@", [names componentsJoinedByString:@", "]]];
|
||||
}
|
||||
else
|
||||
{
|
||||
[logField setStringValue:@"Nothing selected"];
|
||||
[logField setStringValue:@"Selected: (Nothing selected)"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,16 +176,21 @@
|
||||
if (self)
|
||||
{
|
||||
name = aName;
|
||||
children = someChildren;
|
||||
children = someChildren || [];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// Explicit accessors to ensure Key-Value Observing (KVO) works flawlessly.
|
||||
- (id)init
|
||||
{
|
||||
return [self initWithName:@"New Node" children:[]];
|
||||
}
|
||||
|
||||
- (void)setName:(CPString)aName
|
||||
{
|
||||
[self willChangeValueForKey:@"name"];
|
||||
name = aName;[self didChangeValueForKey:@"name"];
|
||||
name = aName;
|
||||
[self didChangeValueForKey:@"name"];
|
||||
}
|
||||
|
||||
- (CPString)name
|
||||
@@ -150,4 +210,9 @@
|
||||
return children;
|
||||
}
|
||||
|
||||
- (CPString)description
|
||||
{
|
||||
return [CPString stringWithFormat:@"<Node %@>", [self name]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user