23 #import "../Foundation/CPRange.h"
24 #import "../Foundation/Ref.h"
30 var CPTokenFieldDOMInputElement = nil,
31 CPTokenFieldDOMPasswordInputElement = nil,
32 CPTokenFieldDOMStandardInputElement = nil,
33 CPTokenFieldInputOwner = nil,
34 CPTokenFieldTextDidChangeValue = nil,
35 CPTokenFieldInputResigning = NO,
36 CPTokenFieldInputDidBlur = NO,
37 CPTokenFieldInputIsActive = NO,
38 CPTokenFieldCachedSelectStartFunction = nil,
39 CPTokenFieldCachedDragFunction = nil,
40 CPTokenFieldFocusInput = NO,
42 CPTokenFieldBlurHandler = nil;
55 CPRange _selectedRange;
57 _CPAutocompleteMenu _autocompleteMenu;
60 CPTimeInterval _completionDelay;
66 BOOL _shouldNotifyTarget;
74 + (CPTimeInterval)defaultCompletionDelay
89 - (id)initWithFrame:(CPRect)frame
91 if (
self = [super initWithFrame:
frame])
93 _completionDelay = [[
self class] defaultCompletionDelay];
94 _tokenizingCharacterSet = [[
self class] defaultTokenizingCharacterSet];
109 _selectedRange = _CPMakeRange(0, 0);
111 var
frame = [
self frame];
114 [_tokenScrollView setHasHorizontalScroller:NO];
115 [_tokenScrollView setHasVerticalScroller:NO];
116 [_tokenScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
118 var contentView = [[
CPView alloc] initWithFrame:CGRectMakeZero()];
119 [contentView setAutoresizingMask:CPViewWidthSizable];
120 [_tokenScrollView setDocumentView:contentView];
122 [
self addSubview:_tokenScrollView];
125 - (_CPAutocompleteMenu)_autocompleteMenu
127 if (!_autocompleteMenu)
128 _autocompleteMenu = [[_CPAutocompleteMenu alloc] initWithTextField:self];
129 return _autocompleteMenu;
132 - (void)_complete:(_CPAutocompleteMenu)anAutocompleteMenu
134 [
self _autocompleteWithEvent:nil];
137 - (void)_autocompleteWithEvent:(
CPEvent)anEvent
142 [
self _hideCompletions];
144 var token = [_autocompleteMenu selectedItem],
145 shouldRemoveLastObject = token !==
@"" && [
self _editorValue] !==
@"";
148 token = [
self _editorValue];
153 if (!token || token ===
@"")
161 [[
self window] selectNextKeyView:self];
163 [[
self window] selectPreviousKeyView:self];
166 [[
self window] makeFirstResponder:nil];
170 var objectValue = [
self objectValue];
174 if (shouldRemoveLastObject)
175 [objectValue removeObjectAtIndex:_selectedRange.location];
178 token = [
self _representedObjectForEditingString:token];
181 var delegateApprovedObjects = [
self _shouldAddObjects:[
CPArray arrayWithObject:token] atIndex:_selectedRange.location],
182 delegateApprovedObjectsCount = [delegateApprovedObjects count];
184 if (delegateApprovedObjects)
186 for (var i = 0; i < delegateApprovedObjectsCount; i++)
188 [objectValue insertObject:[delegateApprovedObjects objectAtIndex:i] atIndex:_selectedRange.location + i];
193 var location = _selectedRange.location;
195 [
self setObjectValue:objectValue];
197 if (delegateApprovedObjectsCount)
198 location += delegateApprovedObjectsCount;
199 _selectedRange = _CPMakeRange(location, 0);
201 [
self _inputElement].value =
@"";
202 [
self setNeedsLayout];
204 [
self _controlTextDidChange];
207 - (void)_autocomplete
209 [
self _autocompleteWithEvent:nil];
212 - (void)_selectToken:(_CPTokenFieldToken)token byExtendingSelection:(BOOL)extend
214 var indexOfToken = [[
self _tokens] indexOfObject:token];
219 _selectedRange = _CPMakeRange([[
self _tokens] count], 0);
222 _selectedRange = CPUnionRange(_selectedRange, _CPMakeRange(indexOfToken, 1));
224 _selectedRange = _CPMakeRange(indexOfToken, 1);
226 [
self setNeedsLayout];
229 - (void)_deselectToken:(_CPTokenFieldToken)token
231 var indexOfToken = [[
self _tokens] indexOfObject:token];
233 if (CPLocationInRange(indexOfToken, _selectedRange))
234 _selectedRange = _CPMakeRange(MAX(indexOfToken, _selectedRange.location), MIN(_selectedRange.length, indexOfToken - _selectedRange.location));
236 [
self setNeedsLayout];
239 - (void)_deleteToken:(_CPTokenFieldToken)token
241 var indexOfToken = [[
self _tokens] indexOfObject:token],
242 objectValue = [
self objectValue];
246 if (indexOfToken < _selectedRange.location)
247 _selectedRange.location--;
249 [
self _deselectToken:token];
252 var selection = CPMakeRangeCopy(_selectedRange);
254 [objectValue removeObjectAtIndex:indexOfToken];
255 [
self setObjectValue:objectValue];
256 _selectedRange = selection;
258 [
self setNeedsLayout];
259 [
self _controlTextDidChange];
262 - (void)_controlTextDidChange
264 var binderClass = [[
self class] _binderClassForBinding:CPValueBinding],
265 theBinding = [binderClass getBinding:CPValueBinding forObject:self];
268 [theBinding reverseSetValueFor:@"objectValue"];
272 _shouldNotifyTarget = YES;
275 - (void)_removeSelectedTokens:(
id)sender
277 var tokens = [
self objectValue];
279 for (var i = _selectedRange.length - 1; i >= 0; i--)
280 [tokens removeObjectAtIndex:_selectedRange.location + i];
282 var collapsedSelection = _selectedRange.location;
284 [
self setObjectValue:tokens];
287 _selectedRange = _CPMakeRange(collapsedSelection, 0);
289 [
self _controlTextDidChange];
292 - (void)_updatePlaceholderState
295 [
self setThemeState:CPTextFieldStatePlaceholder];
297 [
self unsetThemeState:CPTextFieldStatePlaceholder];
304 - (BOOL)becomeFirstResponder
307 if (CPTokenFieldInputOwner && [CPTokenFieldInputOwner window] !== [
self window])
308 [[CPTokenFieldInputOwner window] makeFirstResponder:nil];
312 [
self _setObserveWindowKeyNotifications:YES];
314 if ([[
self window] isKeyWindow])
315 [
self _becomeFirstKeyResponder];
320 - (void)_becomeFirstKeyResponder
322 [
self setThemeState:CPThemeStateEditing];
324 [
self _updatePlaceholderState];
326 [
self setNeedsLayout];
330 var
string = [
self stringValue],
331 element = [
self _inputElement],
332 font = [
self currentValueForThemeAttribute:@"font"];
335 element.style.color = [[
self currentValueForThemeAttribute:@"text-color"] cssString];
336 element.style.font = [font cssString];
337 element.style.zIndex = 1000;
339 switch ([
self alignment])
345 default: element.style.textAlign =
"left";
348 var contentRect = [
self contentRectForBounds:[
self bounds]];
350 element.style.top = CGRectGetMinY(contentRect) + "px";
351 element.style.left = (CGRectGetMinX(contentRect) - 1) + "px";
352 element.style.width = CGRectGetWidth(contentRect) + "px";
353 element.style.height = [font defaultLineHeightForFont] + "px";
355 [_tokenScrollView documentView]._DOMElement.appendChild(element);
357 window.setTimeout(
function()
360 CPTokenFieldInputOwner =
self;
366 [[[
self window] platformWindow] _propagateCurrentDOMEvent:YES];
368 CPTokenFieldInputIsActive = YES;
370 if (document.attachEvent)
372 CPTokenFieldCachedSelectStartFunction = document.body.onselectstart;
373 CPTokenFieldCachedDragFunction = document.body.ondrag;
375 document.body.ondrag =
function () {};
376 document.body.onselectstart =
function () {};
382 - (BOOL)resignFirstResponder
384 [
self _autocomplete];
387 [
self _setObserveWindowKeyNotifications:NO];
389 [
self _resignFirstKeyResponder];
391 if (_shouldNotifyTarget)
393 _shouldNotifyTarget = NO;
396 if ([
self sendsActionOnEndEditing])
403 - (void)_resignFirstKeyResponder
405 [
self unsetThemeState:CPThemeStateEditing];
407 [
self _updatePlaceholderState];
408 [
self setNeedsLayout];
412 var element = [
self _inputElement];
414 CPTokenFieldInputResigning = YES;
417 if (!CPTokenFieldInputDidBlur)
418 CPTokenFieldBlurHandler();
420 CPTokenFieldInputDidBlur = NO;
421 CPTokenFieldInputResigning = NO;
423 if (element.parentNode == [_tokenScrollView documentView]._DOMElement)
424 element.parentNode.removeChild(element);
426 CPTokenFieldInputIsActive = NO;
428 if (document.attachEvent)
430 CPTokenFieldCachedSelectStartFunction = nil;
431 CPTokenFieldCachedDragFunction = nil;
433 document.body.ondrag = CPTokenFieldCachedDragFunction
434 document.body.onselectstart = CPTokenFieldCachedSelectStartFunction
442 _mouseDownEvent = anEvent;
444 [
self _selectToken:nil byExtendingSelection:NO];
451 _mouseDownEvent = nil;
454 - (void)_mouseDownOnToken:(_CPTokenFieldToken)aToken withEvent:(
CPEvent)anEvent
456 _mouseDownEvent = anEvent;
459 - (void)_mouseUpOnToken:(_CPTokenFieldToken)aToken withEvent:(
CPEvent)anEvent
461 if (_mouseDownEvent && _CGPointEqualToPoint([_mouseDownEvent locationInWindow], [anEvent locationInWindow]))
463 [
self _selectToken:aToken byExtendingSelection:[anEvent
modifierFlags] & CPShiftKeyMask];
464 [[
self window] makeFirstResponder:self];
466 _shouldScrollTo = aToken;
477 return [
super objectValue];
487 var objectValue = [];
489 for (var i = 0, count = [[
self _tokens] count]; i < count; i++)
491 var token = [[
self _tokens] objectAtIndex:i];
493 if ([token isKindOfClass:[
CPString class]])
496 [objectValue addObject:[token representedObject]];
501 if ([
self _editorValue])
503 var token = [
self _representedObjectForEditingString:[
self _editorValue]];
504 [objectValue insertObject:token atIndex:_selectedRange.location];
512 - (void)setObjectValue:(
id)aValue
514 if (aValue !== nil && ![aValue isKindOfClass:[
CPArray class]])
521 if (aValue === superValue || [aValue isEqualToArray:superValue])
524 var contentView = [_tokenScrollView documentView],
525 oldTokens = [
self _tokens],
531 for (var i = 0, count = [aValue count]; i < count; i++)
534 var tokenObject = aValue[i],
535 tokenValue = [
self _displayStringForRepresentedObject:tokenObject],
538 for (var j = 0, oldCount = [oldTokens count]; j < oldCount; j++)
540 var oldToken = oldTokens[j];
541 if ([oldToken representedObject] == tokenObject)
544 [oldTokens removeObjectAtIndex:j];
550 if (newToken === nil)
552 newToken = [[_CPTokenFieldToken alloc] init];
553 [newToken setTokenField:self];
554 [newToken setRepresentedObject:tokenObject];
555 [newToken setStringValue:tokenValue];
557 [contentView addSubview:newToken];
560 newTokens.push(newToken);
565 for (var j = 0, oldCount = [oldTokens count]; j < oldCount; j++)
566 [oldTokens[j] removeFromSuperview];
579 [
self _selectToken:nil byExtendingSelection:NO];
581 [
self _updatePlaceholderState];
588 - (void)setEnabled:(BOOL)shouldBeEnabled
593 for (var i = 0, count = [[
self _tokens] count]; i < count; i++)
595 var token = [[
self _tokens] objectAtIndex:i];
597 if ([token respondsToSelector:
@selector(setEnabled:)])
598 [token setEnabled:shouldBeEnabled];
602 - (void)setEditable:(BOOL)shouldBeEditable
606 [[
self _tokens] makeObjectsPerformSelector:@selector(setEditable:) withObject:shouldBeEditable];
609 - (void)sendAction:(
SEL)anAction to:(
id)anObject
611 _shouldNotifyTarget = NO;
617 - (void)_setStringValue:(
id)aValue
625 - (DOMElement)_inputElement
627 if (!CPTokenFieldDOMInputElement)
629 CPTokenFieldDOMInputElement = document.createElement(
"input");
630 CPTokenFieldDOMInputElement.style.position =
"absolute";
631 CPTokenFieldDOMInputElement.style.border =
"0px";
632 CPTokenFieldDOMInputElement.style.padding =
"0px";
633 CPTokenFieldDOMInputElement.style.margin =
"0px";
634 CPTokenFieldDOMInputElement.style.whiteSpace =
"pre";
635 CPTokenFieldDOMInputElement.style.background =
"transparent";
636 CPTokenFieldDOMInputElement.style.outline =
"none";
638 CPTokenFieldBlurHandler =
function(anEvent)
642 CPTokenFieldInputOwner,
643 [CPTokenFieldInputOwner._tokenScrollView documentView]._DOMElement,
644 CPTokenFieldDOMInputElement,
645 CPTokenFieldInputResigning,
646 AT_REF(CPTokenFieldInputDidBlur));
650 CPTokenFieldDOMInputElement.onblur = CPTokenFieldBlurHandler;
652 CPTokenFieldDOMStandardInputElement = CPTokenFieldDOMInputElement;
657 if ([CPTokenFieldInputOwner isSecure])
658 CPTokenFieldDOMInputElement.type =
"password";
660 CPTokenFieldDOMInputElement.type =
"text";
662 return CPTokenFieldDOMInputElement;
665 return CPTokenFieldDOMInputElement;
673 return [
self _inputElement].value;
676 - (void)moveUp:(
id)sender
678 [[
self _autocompleteMenu] selectPrevious];
682 - (void)moveDown:(
id)sender
684 [[
self _autocompleteMenu] selectNext];
688 - (void)insertNewline:(
id)sender
690 if ([
self hasThemeState:CPThemeStateAutocompleting])
692 [
self _autocompleteWithEvent:[CPApp currentEvent]];
701 - (void)insertTab:(
id)sender
703 var anEvent = [CPApp currentEvent];
704 if ([
self hasThemeState:CPThemeStateAutocompleting])
706 [
self _autocompleteWithEvent:anEvent];
723 if ([_tokenizingCharacterSet characterIsMember:[characters substringToIndex:1]])
725 [
self _autocompleteWithEvent:[CPApp currentEvent]];
730 if (_selectedRange.length)
732 [
self _removeSelectedTokens:self];
747 - (void)cancelOperation:(
id)sender
749 [
self _hideCompletions];
752 - (void)moveLeft:(
id)sender
755 if ((_selectedRange.location > 0 || _selectedRange.length) && [
self _editorValue] ==
"")
757 if (_selectedRange.length)
759 _selectedRange.length = 0;
761 _selectedRange.location--;
772 - (void)moveLeftAndModifySelection:(
id)sender
774 if (_selectedRange.location > 0 && [
self _editorValue] ==
"")
776 _selectedRange.location--;
778 _selectedRange.length++;
789 - (void)moveRight:(
id)sender
792 if ((_selectedRange.location < [[
self _tokens] count] || _selectedRange.length) && [
self _editorValue] ==
"")
794 if (_selectedRange.length)
797 _selectedRange.location = _CPMaxRange(_selectedRange);
798 _selectedRange.length = 0;
803 _selectedRange.location = MIN([[
self _tokens] count], _selectedRange.location + _selectedRange.length + 1);
816 - (void)moveRightAndModifySelection:(
id)sender
818 if (_CPMaxRange(_selectedRange) < [[
self _tokens] count] && [
self _editorValue] ==
"")
821 _selectedRange.length++;
832 - (void)deleteBackward:(
id)sender
836 if ([
self _editorValue] ==
@"")
838 [
self _hideCompletions];
840 if (CPEmptyRange(_selectedRange))
842 if (_selectedRange.location > 0)
844 var tokenView = [[
self _tokens] objectAtIndex:(_selectedRange.location - 1)];
845 [
self _selectToken:tokenView byExtendingSelection:NO];
849 [
self _removeSelectedTokens:nil];
858 - (void)deleteForward:(
id)sender
862 if ([
self _editorValue] ==
@"")
865 [
self _hideCompletions];
867 if (CPEmptyRange(_selectedRange))
869 if (_selectedRange.location < [[
self _tokens] count])
870 [
self _deleteToken:[[
self _tokens] objectAtIndex:[_selectedRange.location]]];
873 [
self _removeSelectedTokens:nil];
882 - (void)_selectText:(
id)sender immediately:(BOOL)immediately
891 if (([
self isEditable] || [
self isSelectable]))
893 [
super _selectText:sender immediately:immediately];
896 [
self _autocomplete];
897 _selectedRange = _CPMakeRange(0, [[
self _tokens] count]);
899 [
self setNeedsLayout];
905 CPTokenFieldTextDidChangeValue = [
self stringValue];
919 if ([
self stringValue] !== CPTokenFieldTextDidChangeValue)
929 if ([aNotification
object] !==
self)
935 [
self _delayedShowCompletions];
937 _selectedRange.length = 0;
950 - (void)setCompletionDelay:(CPTimeInterval)delay
952 _completionDelay = delay;
955 - (CPTimeInterval)completionDelay
957 return _completionDelay;
963 - (void)layoutSubviews
973 if (textFieldContentView)
974 [textFieldContentView setHidden:[
self stringValue] !== @""];
977 contentView = [_tokenScrollView documentView],
978 tokens = [
self _tokens];
981 if (![tokens isKindOfClass:[
CPArray class]])
985 var contentRect = _CGRectMakeCopy([contentView bounds]),
986 contentOrigin = contentRect.origin,
987 contentSize = contentRect.size,
988 offset =
CPPointMake(contentOrigin.x, contentOrigin.y),
991 tokenToken = [_CPTokenFieldToken new],
997 offset.y += CEIL(spaceBetweenTokens.height / 2.0);
1000 [tokenToken sizeToFit];
1002 var tokenHeight = _CGRectGetHeight([tokenToken bounds]);
1004 var fitAndFrame =
function(
width, height)
1006 var r = _CGRectMake(0, 0,
width, height);
1008 if (offset.x +
width >= contentSize.width && offset.x > contentOrigin.x)
1010 offset.x = contentOrigin.x;
1011 offset.y += height + spaceBetweenTokens.height;
1014 r.origin.x = offset.x;
1015 r.origin.y = offset.y;
1018 var scrollHeight = offset.y + tokenHeight + CEIL(spaceBetweenTokens.height / 2.0);
1019 if (_CGRectGetHeight([contentView bounds]) < scrollHeight)
1020 [contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
1022 offset.x +=
width + spaceBetweenTokens.width;
1027 var placeEditor =
function(useRemainingWidth)
1029 var element = [
self _inputElement],
1032 if (_selectedRange.length === 0)
1037 textWidth = [(element.value || @"") + "X" sizeWithFont:font].width;
1039 if (useRemainingWidth)
1040 textWidth = MAX(contentSize.width - offset.x - 1, textWidth);
1043 _inputFrame = fitAndFrame(textWidth, tokenHeight);
1045 _inputFrame.size.height = lineHeight;
1047 element.style.left = (_inputFrame.origin.x + editorInset.left) +
"px";
1048 element.style.top = (_inputFrame.origin.y + editorInset.top) +
"px";
1049 element.style.width = _inputFrame.size.width +
"px";
1050 element.style.height = _inputFrame.size.height +
"px";
1053 if (_selectedRange.length == 0)
1054 [[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, _inputFrame.origin.y)];
1057 for (var i = 0, count = [tokens count]; i < count; i++)
1059 if (isEditing && !_selectedRange.length && i == _CPMaxRange(_selectedRange))
1062 var tokenView = [tokens objectAtIndex:i];
1065 if ([tokenView isKindOfClass:[
CPString class]])
1068 [tokenView setHighlighted:CPLocationInRange(i, _selectedRange)];
1069 [tokenView sizeToFit];
1071 var size = [contentView bounds].size,
1072 tokenViewSize = [tokenView bounds].size,
1073 tokenFrame = fitAndFrame(tokenViewSize.width, tokenViewSize.height);
1075 [tokenView setFrame:tokenFrame];
1078 if (isEditing && !_selectedRange.length && _CPMaxRange(_selectedRange) >= [tokens count])
1083 if (isEditing && _selectedRange.length)
1086 var inputElement = [
self _inputElement];
1087 inputElement.style.display =
"none";
1091 var inputElement = [
self _inputElement];
1092 inputElement.style.display =
"block";
1093 if (document.activeElement !== inputElement)
1094 inputElement.focus();
1098 var scrollHeight = offset.y + tokenHeight;
1099 if (_CGRectGetHeight([contentView bounds]) > scrollHeight)
1100 [contentView setFrameSize:_CGSizeMake(_CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
1105 if (!(isEditing && _selectedRange.length == 0))
1107 var scrollToToken = _shouldScrollTo;
1110 scrollToToken = tokens[_selectedRange.location]
1112 scrollToToken = tokens[MAX(0, _CPMaxRange(_selectedRange) - 1)];
1113 [
self _scrollTokenViewToVisible:scrollToToken];
1120 - (BOOL)_scrollTokenViewToVisible:(_CPTokenFieldToken)aToken
1125 return [[_tokenScrollView documentView] scrollPoint:_CGPointMake(0, [aToken frameOrigin].y)];
1141 - (
CPArray)_completionsForSubstring:(
CPString)substring indexOfToken:(
int)tokenIndex indexOfSelectedItem:(
int)selectedIndex
1143 if ([[
self delegate] respondsToSelector:
@selector(tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:)])
1145 return [[
self delegate] tokenField:self completionsForSubstring:substring indexOfToken:tokenIndex indexOfSelectedItem:selectedIndex];
1154 - (CGPoint)_completionOrigin:(_CPAutocompleteMenu)anAutocompleteMenu
1156 var relativeFrame = _inputFrame ? [[_tokenScrollView documentView] convertRect:_inputFrame toView:self ] : [
self bounds];
1157 return _CGPointMake(_CGRectGetMinX(relativeFrame), _CGRectGetMaxY(relativeFrame));
1168 - (
CPString)_displayStringForRepresentedObject:(
id)representedObject
1170 if ([[
self delegate] respondsToSelector:
@selector(tokenField:displayStringForRepresentedObject:)])
1172 var stringForRepresentedObject = [[
self delegate] tokenField:self displayStringForRepresentedObject:representedObject];
1173 if (stringForRepresentedObject !== nil)
1175 return stringForRepresentedObject;
1179 return representedObject;
1193 var delegate = [
self delegate];
1194 if ([delegate respondsToSelector:
@selector(tokenField:shouldAddObjects:atIndex:)])
1196 var approvedObjects = [delegate tokenField:self shouldAddObjects:tokens atIndex:index];
1197 if (approvedObjects !== nil)
1198 return approvedObjects;
1213 - (id)_representedObjectForEditingString:(
CPString)aString
1215 var delegate = [
self delegate];
1216 if ([delegate respondsToSelector:
@selector(tokenField:representedObjectForEditingString:)])
1218 var token = [delegate tokenField:self representedObjectForEditingString:aString];
1219 if (token !== nil && token !== undefined)
1242 - (void)_delayedShowCompletions
1244 [[
self _autocompleteMenu] _delayedShowCompletions];
1247 - (void)_hideCompletions
1249 [_autocompleteMenu _hideCompletions];
1256 _CPTokenFieldTokenCloseButton _deleteButton;
1258 id _representedObject;
1263 return "tokenfield-token";
1266 - (BOOL)acceptsFirstResponder
1271 - (id)initWithFrame:(CPRect)frame
1273 if (
self = [super initWithFrame:frame])
1275 _deleteButton = [[_CPTokenFieldTokenCloseButton alloc] initWithFrame:CPRectMakeZero()];
1276 [
self addSubview:_deleteButton];
1278 [
self setEditable:NO];
1279 [
self setHighlighted:NO];
1280 [
self setBezeled:YES];
1293 _tokenField = tokenField;
1296 - (id)representedObject
1298 return _representedObject;
1301 - (void)setRepresentedObject:(
id)representedObject
1303 _representedObject = representedObject;
1306 - (void)setEditable:(BOOL)shouldBeEditable
1308 [
super setEditable:shouldBeEditable];
1309 [
self setNeedsLayout];
1314 var r = [
super setThemeState:aState];
1318 [_deleteButton setThemeState:aState];
1325 var r = [
super unsetThemeState:aState];
1329 [_deleteButton unsetThemeState:aState];
1334 - (CGSize)_minimumFrameSize
1336 var size = _CGSizeMakeZero(),
1337 minSize = [
self currentValueForThemeAttribute:@"min-size"],
1338 contentInset = [
self currentValueForThemeAttribute:@"content-inset"];
1341 size.height = minSize.height;
1342 size.width = MAX(minSize.width, [([
self stringValue] ||
@" ") sizeWithFont:[
self font]].width + contentInset.left + contentInset.right);
1347 - (void)layoutSubviews
1349 [
super layoutSubviews];
1351 var bezelView = [
self layoutEphemeralSubviewNamed:@"bezel-view"
1352 positioned:CPWindowBelow
1353 relativeToEphemeralSubviewNamed:@"content-view"];
1357 [_deleteButton setTarget:self];
1358 [_deleteButton setAction:@selector(_delete:)];
1359 [_deleteButton setEnabled:[
self isEditable]];
1361 var
frame = [bezelView frame],
1362 buttonOffset = [_deleteButton currentValueForThemeAttribute:@"offset"],
1363 buttonSize = [_deleteButton currentValueForThemeAttribute:@"min-size"];
1365 [_deleteButton setFrame:_CGRectMake(CPRectGetMaxX(frame) - buttonOffset.x, CPRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
1369 - (void)mouseDown:(
CPEvent)anEvent
1371 [_tokenField _mouseDownOnToken:self withEvent:anEvent];
1374 - (void)mouseUp:(
CPEvent)anEvent
1376 [_tokenField _mouseUpOnToken:self withEvent:anEvent];
1379 - (void)_delete:(
id)sender
1381 if ([
self isEditable])
1382 [_tokenField _deleteToken:self];
1390 @implementation _CPTokenFieldTokenCloseButton :
CPButton
1395 + (id)themeAttributes
1399 [attributes setObject:_CGPointMake(15, 5) forKey:@"offset"];
1406 return "tokenfield-token-close-button";
1423 _tokenizingCharacterSet = [aCoder decodeObjectForKey:CPTokenFieldTokenizingCharacterSetKey] || [[
self class] defaultTokenizingCharacterSet];
1424 _completionDelay = [aCoder decodeDoubleForKey:CPTokenFieldCompletionDelayKey] || [[
self class] defaultCompletionDelay];
1439 [aCoder encodeInt:_tokenizingCharacterSet forKey:CPTokenFieldTokenizingCharacterSetKey];
1440 [aCoder encodeDouble:_completionDelay forKey:CPTokenFieldCompletionDelayKey];
1452 return _tokenizingCharacterSet;
1460 _tokenizingCharacterSet = aValue;