mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-10 20:57:11 +00:00
- Using more logical scheme for widget layout. bezel-inset is inset from frame to the bezel image. border-inset is the inset from the frame to the visible border (if any), which usually is the width of a focus ring. content-inset is the inset from the border rect to the content frame, including the width of the border. This scheme makes it much easier to visualize what is happening, and also makes it possible to ensure a consistent margin between the content and the surrounding bezel border. It also allowed me to remove the funky +1 pixel hack in [CPTextField becomeFirstResponder]. - CPTextField (square and rounded) and CPTokenField had their theme insets reworked to fit the new scheme. - Added missing disabled bezel for rounded textfield. - All textfield focus rings look much nicer now (more like Cocoa). Previously the actual border of a textfield would shrink when focused, now it stays the same. - In CPTokenField, wrapped all references to _inputElement in #if PLATFORM(DOM). - Placeholder state was not being set correctly because a recent change to [CPTextField _updatePlaceholderState] uses the cached _stringValue instead of [self stringValue]. CPTokenField has its own override now that checks the token count.
183 lines
5.8 KiB
Plaintext
183 lines
5.8 KiB
Plaintext
/*
|
|
* AppController.j
|
|
* CPTokenFieldTest
|
|
*
|
|
* Created by Alexander Ljungberg on October 2, 2010.
|
|
* Copyright 2010, WireLoad, LLC All rights reserved.
|
|
*/
|
|
|
|
@import <Foundation/CPObject.j>
|
|
|
|
var STATES = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'District of Columbia', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];
|
|
|
|
@implementation AppController : CPObject
|
|
{
|
|
CPTokenField tokenFieldD;
|
|
|
|
CPArray allPersons;
|
|
}
|
|
|
|
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
|
|
{
|
|
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
|
|
contentView = [theWindow contentView],
|
|
|
|
tokenFieldA = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 40, 500, 29)],
|
|
label = [[CPTextField alloc] initWithFrame:CGRectMake(15, 15, 500, 24)];
|
|
|
|
[label setStringValue:@"This token field has no auto suggestions and uses space to separate tokens."];
|
|
[contentView addSubview:label];
|
|
|
|
[tokenFieldA setEditable:YES];
|
|
[tokenFieldA setPlaceholderString:@"Type in a token!"];
|
|
|
|
[tokenFieldA setTokenizingCharacterSet:[CPCharacterSet characterSetWithCharactersInString:@" "]];
|
|
|
|
[contentView addSubview:tokenFieldA];
|
|
|
|
var tokenFieldB = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 110, 500, 29)],
|
|
labelB = [[CPTextField alloc] initWithFrame:CGRectMake(15, 80, 500, 24)];
|
|
|
|
[labelB setStringValue:@"This token field has no bezel, uses comma to separate tokens and has auto suggest."];
|
|
[contentView addSubview:labelB];
|
|
|
|
[tokenFieldB setEditable:YES];
|
|
[tokenFieldB setBezeled:NO];
|
|
[tokenFieldB setPlaceholderString:@"Edit me!"];
|
|
|
|
[tokenFieldB setObjectValue:["Missouri", "California"]];
|
|
[tokenFieldB setDelegate:self];
|
|
|
|
[tokenFieldB setAction:@selector(tokenFieldAction:)];
|
|
[tokenFieldB setTarget:self];
|
|
|
|
[contentView addSubview:tokenFieldB];
|
|
|
|
var tokenFieldC = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 170, 500, 29)],
|
|
labelC = [[CPTextField alloc] initWithFrame:CGRectMake(15, 150, 500, 24)];
|
|
|
|
[labelC setStringValue:@"This token field can't fit all its tokens."];
|
|
[contentView addSubview:labelC];
|
|
|
|
[tokenFieldC setEditable:YES];
|
|
[tokenFieldC setPlaceholderString:@"Edit me!"];
|
|
|
|
[tokenFieldC setObjectValue:['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado']];
|
|
[tokenFieldC setDelegate:self];
|
|
|
|
[contentView addSubview:tokenFieldC];
|
|
|
|
[tokenFieldC setSendsActionOnEndEditing:YES];
|
|
[tokenFieldC setAction:@selector(tokenFieldAction:)];
|
|
[tokenFieldC setTarget:self];
|
|
|
|
tokenFieldD = [[CPTokenField alloc] initWithFrame:CGRectMake(15, 230, 500, 29)],
|
|
labelD = [[CPTextField alloc] initWithFrame:CGRectMake(15, 210, 500, 24)];
|
|
|
|
[labelD setStringValue:@"This token field contains represented objects."];
|
|
[contentView addSubview:labelD];
|
|
|
|
[tokenFieldD setEditable:YES];
|
|
|
|
// Delegate must be set before objectValue
|
|
[tokenFieldD setDelegate:self];
|
|
|
|
allPersons = [
|
|
[Person personWithFirstName:@"Luc" lastName:@"Vauvillier"],
|
|
[Person personWithFirstName:@"John" lastName:@"Doe"],
|
|
[Person personWithFirstName:@"Amélie" lastName:@"Poulain"],
|
|
[Person personWithFirstName:@"Jean" lastName:@"Valjean"]
|
|
];
|
|
[tokenFieldD setObjectValue:[allPersons copy]];
|
|
|
|
[contentView addSubview:tokenFieldD];
|
|
|
|
var button = [[CPButton alloc] initWithFrame:CGRectMake(15, 270, 0, 0)];
|
|
[button setTitle:@"Get Object Values"];
|
|
[button sizeToFit];
|
|
[button setTarget:self];
|
|
[button setAction:@selector(getObjectValues:)];
|
|
[contentView addSubview:button];
|
|
|
|
[theWindow orderFront:self];
|
|
|
|
}
|
|
|
|
- (void)getObjectValues:(id)sender
|
|
{
|
|
alert([tokenFieldD objectValue]);
|
|
}
|
|
|
|
- (CPArray)tokenField:(CPTokenField)aTokenField completionsForSubstring:(CPString)substring indexOfToken:(int)tokenIndex indexOfSelectedItem:(int)selectedIndex
|
|
{
|
|
var r = [];
|
|
|
|
// Don't complete 'blank' - this would show all available matches which is excessive.
|
|
if (!substring)
|
|
return r;
|
|
|
|
|
|
if (aTokenField !== tokenFieldD)
|
|
{
|
|
for (var i = 0; i < STATES.length; i++)
|
|
if (STATES[i].toLowerCase().indexOf(substring.toLowerCase()) == 0)
|
|
r.push(STATES[i]);
|
|
}
|
|
else
|
|
{
|
|
for (var i = 0; i < allPersons.length; i++)
|
|
if ([allPersons[i] fullname].toLowerCase().indexOf(substring.toLowerCase()) == 0)
|
|
r.push(allPersons[i]);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
- (CPString)tokenField:(CPTokenField)tokenField displayStringForRepresentedObject:(id)representedObject
|
|
{
|
|
if ([representedObject isKindOfClass:Person])
|
|
{
|
|
return [representedObject fullname];
|
|
}
|
|
|
|
return representedObject;
|
|
}
|
|
|
|
- (@action)tokenFieldAction:(id)sender
|
|
{
|
|
CPLog.info("tokenFieldAction: " + sender);
|
|
}
|
|
|
|
@end
|
|
|
|
// A sample of a custom Object
|
|
|
|
@implementation Person : CPObject
|
|
{
|
|
CPString _firstName;
|
|
CPString _lastName;
|
|
}
|
|
|
|
+ (id)personWithFirstName:(CPString)aFirstName lastName:(CPString)aLastName
|
|
{
|
|
return [[self alloc] initWithFirstName:aFirstName lastName:aLastName];
|
|
}
|
|
|
|
- (id)initWithFirstName:(CPString)aFirstName lastName:(CPString)aLastName
|
|
{
|
|
self = [super init];
|
|
if (self)
|
|
{
|
|
_firstName = aFirstName;
|
|
_lastName = aLastName;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (CPString)fullname
|
|
{
|
|
return [CPString stringWithFormat:@"%@ %@", _firstName, _lastName];
|
|
}
|
|
|
|
@end
|