35 - (BOOL)tokenField:(
CPTokenField)tokenField hasMenuForRepresentedObject:(
id)representedObject;
36 - (CPArray)tokenField:(
CPTokenField)tokenField completionsForSubstring:(
CPString)substring indexOfToken:(CPInteger)tokenIndex indexOfSelectedItem:(CPInteger)selectedIndex;
37 - (CPArray)tokenField:(
CPTokenField)tokenField shouldAddObjects:(CPArray)tokens atIndex:(CPUInteger)index;
38 - (
CPMenu)tokenField:(
CPTokenField)tokenField menuForRepresentedObject:(
id)representedObject;
39 - (
CPString )tokenField:(
CPTokenField)tokenField displayStringForRepresentedObject:(
id)representedObject;
40 - (id)tokenField:(
CPTokenField)tokenField representedObjectForEditingString:(
CPString)editingString;
54 var CPTokenFieldDOMInputElement = nil,
55 CPTokenFieldDOMPasswordInputElement = nil,
56 CPTokenFieldDOMStandardInputElement = nil,
57 CPTokenFieldInputOwner = nil,
58 CPTokenFieldTextDidChangeValue = nil,
59 CPTokenFieldInputResigning = NO,
60 CPTokenFieldInputDidBlur = NO,
61 CPTokenFieldInputIsActive = NO,
62 CPTokenFieldCachedSelectStartFunction = nil,
63 CPTokenFieldCachedDragFunction = nil,
64 CPTokenFieldFocusInput = NO,
66 CPTokenFieldBlurHandler = nil;
82 CPRange _selectedRange;
84 _CPAutocompleteMenu _autocompleteMenu;
87 CPTimeInterval _completionDelay;
93 BOOL _shouldNotifyTarget;
97 id <CPTokenFieldDelegate> _tokenFieldDelegate;
98 unsigned _implementedTokenFieldDelegateMethods;
118 return @{
@"editor-inset": CGInsetMakeZero() };
121 - (id)initWithFrame:(CGRect)frame
123 if (
self = [super initWithFrame:
frame])
125 _completionDelay = [[
self class] defaultCompletionDelay];
126 _tokenizingCharacterSet = [[
self class] defaultTokenizingCharacterSet];
146 _tokenScrollView = [[
CPScrollView alloc] initWithFrame:CGRectMakeZero()];
147 [_tokenScrollView setHasHorizontalScroller:NO];
148 [_tokenScrollView setHasVerticalScroller:NO];
149 [_tokenScrollView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
151 var contentView = [[
CPView alloc] initWithFrame:CGRectMakeZero()];
152 [contentView setAutoresizingMask:CPViewWidthSizable];
153 [_tokenScrollView setDocumentView:contentView];
159 #pragma mark Delegate methods 166 if (_tokenFieldDelegate === aDelegate)
169 _tokenFieldDelegate = aDelegate;
170 _implementedTokenFieldDelegateMethods = 0;
172 if ([_tokenFieldDelegate respondsToSelector:
@selector(tokenField:hasMenuForRepresentedObject:)])
175 if ([_tokenFieldDelegate respondsToSelector:
@selector(tokenField:completionsForSubstring:indexOfToken:indexOfSelectedItem:)])
178 if ([_tokenFieldDelegate respondsToSelector:
@selector(tokenField:shouldAddObjects:atIndex:)])
181 if ([_tokenFieldDelegate respondsToSelector:
@selector(tokenField:menuForRepresentedObject:)])
184 if ([_tokenFieldDelegate respondsToSelector:
@selector(tokenField:displayStringForRepresentedObject:)])
187 if ([_tokenFieldDelegate respondsToSelector:
@selector(tokenField:representedObjectForEditingString:)])
193 - (_CPAutocompleteMenu)_autocompleteMenu
195 if (!_autocompleteMenu)
196 _autocompleteMenu = [[_CPAutocompleteMenu alloc] initWithTextField:self];
197 return _autocompleteMenu;
200 - (void)_complete:(_CPAutocompleteMenu)anAutocompleteMenu
202 [
self _autocompleteWithEvent:nil];
205 - (void)_autocompleteWithEvent:(
CPEvent)anEvent
210 [
self _hideCompletions];
212 var token = [_autocompleteMenu selectedItem],
213 shouldRemoveLastObject = token !==
@"" && [
self _editorValue] !==
@"";
216 token = [
self _editorValue];
221 if (!token || token ===
@"")
223 var character = [anEvent charactersIgnoringModifiers],
224 modifierFlags = [anEvent modifierFlags];
229 [[
self window] selectNextKeyView:
self];
242 if (shouldRemoveLastObject)
243 [objectValue removeObjectAtIndex:_selectedRange.location];
246 token = [
self _representedObjectForEditingString:token];
249 var delegateApprovedObjects = [
self _shouldAddObjects:[CPArray arrayWithObject:token] atIndex:_selectedRange.location],
250 delegateApprovedObjectsCount = [delegateApprovedObjects count];
252 if (delegateApprovedObjects)
254 for (var i = 0; i < delegateApprovedObjectsCount; i++)
256 [objectValue insertObject:[delegateApprovedObjects objectAtIndex:i] atIndex:_selectedRange.location + i];
261 var location = _selectedRange.location;
265 if (delegateApprovedObjectsCount)
266 location += delegateApprovedObjectsCount;
269 [
self _inputElement].value =
@"";
272 [
self _controlTextDidChange];
275 - (void)_autocomplete
277 [
self _autocompleteWithEvent:nil];
280 - (void)_selectToken:(_CPTokenFieldToken)token byExtendingSelection:(BOOL)extend
282 var indexOfToken = [[
self _tokens] indexOfObject:token];
287 _selectedRange =
CPMakeRange([[
self _tokens] count], 0);
297 - (void)_deselectToken:(_CPTokenFieldToken)token
299 var indexOfToken = [[
self _tokens] indexOfObject:token];
302 _selectedRange =
CPMakeRange(MAX(indexOfToken, _selectedRange.location), MIN(_selectedRange.length, indexOfToken - _selectedRange.location));
307 - (void)_deleteToken:(_CPTokenFieldToken)token
309 var indexOfToken = [[
self _tokens] indexOfObject:token],
314 if (indexOfToken < _selectedRange.location)
315 _selectedRange.location--;
317 [
self _deselectToken:token];
324 _selectedRange = selection;
327 [
self _controlTextDidChange];
330 - (void)_controlTextDidChange
332 var binderClass = [[
self class] _binderClassForBinding:CPValueBinding],
333 theBinding = [binderClass getBinding:CPValueBinding forObject:self];
336 [theBinding reverseSetValueFor:@"objectValue"];
340 _shouldNotifyTarget = YES;
343 - (void)_removeSelectedTokens:(
id)sender
347 for (var i = _selectedRange.length - 1; i >= 0; i--)
348 [tokens removeObjectAtIndex:_selectedRange.location + i];
350 var collapsedSelection = _selectedRange.location;
355 _selectedRange =
CPMakeRange(collapsedSelection, 0);
357 [
self _controlTextDidChange];
360 - (void)_updatePlaceholderState
362 if (([[
self _tokens] count] === 0) && ![
self hasThemeState:CPThemeStateEditing])
378 if (CPTokenFieldInputOwner && [CPTokenFieldInputOwner
window] !== [
self window])
379 [[CPTokenFieldInputOwner window] makeFirstResponder:nil];
383 [
self _setObserveWindowKeyNotifications:YES];
387 if ([[
self window] isKeyWindow])
388 return [
self _becomeFirstKeyResponder];
393 - (BOOL)_becomeFirstKeyResponder
397 if (![
self _isWithinUsablePlatformRect])
402 [
self _updatePlaceholderState];
409 element = [
self _inputElement],
410 font = [
self currentValueForThemeAttribute:@"font"];
413 element.style.color = [[
self currentValueForThemeAttribute:@"text-color"] cssString];
415 element.style.zIndex = 1000;
420 element.style.textAlign =
"center";
424 element.style.textAlign =
"right";
428 element.style.textAlign =
"left";
433 element.style.top = CGRectGetMinY(contentRect) +
"px";
434 element.style.left = (CGRectGetMinX(contentRect) - 1) +
"px";
435 element.style.width = CGRectGetWidth(contentRect) +
"px";
440 [_tokenScrollView documentView]._DOMElement.appendChild(element);
448 var previousScrollingOrigin = [
self _scrollToVisibleRectAndReturnPreviousOrigin];
452 [
self _restorePreviousScrollingOrigin:previousScrollingOrigin];
454 CPTokenFieldInputOwner = self;
462 CPTokenFieldInputIsActive = YES;
464 if (document.attachEvent)
466 CPTokenFieldCachedSelectStartFunction = document.body.onselectstart;
467 CPTokenFieldCachedDragFunction = document.body.ondrag;
469 document.body.ondrag =
function () {};
470 document.body.onselectstart =
function () {};
480 [
self _autocomplete];
483 [
self _setObserveWindowKeyNotifications:NO];
485 [
self _resignFirstKeyResponder];
487 if (_shouldNotifyTarget)
489 _shouldNotifyTarget = NO;
501 - (void)_resignFirstKeyResponder
505 [
self _updatePlaceholderState];
510 var element = [
self _inputElement];
512 CPTokenFieldInputResigning = YES;
515 if (!CPTokenFieldInputDidBlur)
516 CPTokenFieldBlurHandler();
518 CPTokenFieldInputDidBlur = NO;
519 CPTokenFieldInputResigning = NO;
521 if (element.parentNode == [_tokenScrollView documentView]._DOMElement)
522 element.parentNode.removeChild(element);
524 CPTokenFieldInputIsActive = NO;
526 if (document.attachEvent)
528 CPTokenFieldCachedSelectStartFunction = nil;
529 CPTokenFieldCachedDragFunction = nil;
531 document.body.ondrag = CPTokenFieldCachedDragFunction
532 document.body.onselectstart = CPTokenFieldCachedSelectStartFunction
540 _mouseDownEvent = anEvent;
542 [
self _selectToken:nil byExtendingSelection:NO];
549 _mouseDownEvent = nil;
552 - (void)_mouseDownOnToken:(_CPTokenFieldToken)aToken withEvent:(
CPEvent)anEvent
554 _mouseDownEvent = anEvent;
557 - (void)_mouseUpOnToken:(_CPTokenFieldToken)aToken withEvent:(
CPEvent)anEvent
559 if (_mouseDownEvent && CGPointEqualToPoint([_mouseDownEvent locationInWindow], [anEvent locationInWindow]))
561 [
self _selectToken:aToken byExtendingSelection:[anEvent
modifierFlags] & CPShiftKeyMask];
564 _shouldScrollTo = aToken;
580 return [[
self objectValue] componentsJoinedByString:@","];
587 for (var i = 0, count = [[
self _tokens] count]; i < count; i++)
589 var token = [[
self _tokens] objectAtIndex:i];
591 if ([token isKindOfClass:[
CPString class]])
599 if ([
self _editorValue])
601 var token = [
self _representedObjectForEditingString:[
self _editorValue]];
602 [
objectValue insertObject:token atIndex:_selectedRange.location];
610 - (void)setObjectValue:(
id)aValue
612 if (aValue !== nil && ![aValue isKindOfClass:[CPArray
class]])
619 if (aValue === superValue || [aValue isEqualToArray:superValue])
622 var contentView = [_tokenScrollView documentView],
623 oldTokens = [
self _tokens],
629 for (var i = 0, count = [aValue count]; i < count; i++)
632 var tokenObject = aValue[i],
633 tokenValue = [
self _displayStringForRepresentedObject:tokenObject],
636 for (var j = 0, oldCount = [oldTokens count]; j < oldCount; j++)
638 var oldToken = oldTokens[j];
639 if ([oldToken representedObject] == tokenObject)
642 [oldTokens removeObjectAtIndex:j];
648 if (newToken === nil)
650 newToken = [_CPTokenFieldToken new];
651 [newToken setTokenField:self];
652 [newToken setRepresentedObject:tokenObject];
653 [newToken setStringValue:tokenValue];
655 [contentView addSubview:newToken];
658 newTokens.push(newToken);
663 for (var j = 0, oldCount = [oldTokens count]; j < oldCount; j++)
677 [
self _selectToken:nil byExtendingSelection:NO];
679 [
self _updatePlaceholderState];
686 - (void)setEnabled:(BOOL)shouldBeEnabled
691 for (var i = 0, count = [[
self _tokens] count]; i < count; i++)
693 var token = [[
self _tokens] objectAtIndex:i];
695 if ([token respondsToSelector:
@selector(setEnabled:)])
696 [token setEnabled:shouldBeEnabled];
700 - (void)setEditable:(BOOL)shouldBeEditable
704 [[
self _tokens] makeObjectsPerformSelector:@selector(setEditable:) withObject:shouldBeEditable];
707 - (BOOL)sendAction:(
SEL)anAction to:(
id)anObject
709 _shouldNotifyTarget = NO;
715 - (BOOL)_setStringValue:(
CPString)aValue
723 - (DOMElement)_inputElement
725 if (!CPTokenFieldDOMInputElement)
727 CPTokenFieldDOMInputElement = document.createElement(
"input");
728 CPTokenFieldDOMInputElement.style.position =
"absolute";
729 CPTokenFieldDOMInputElement.style.border =
"0px";
730 CPTokenFieldDOMInputElement.style.padding =
"0px";
731 CPTokenFieldDOMInputElement.style.margin =
"0px";
732 CPTokenFieldDOMInputElement.style.whiteSpace =
"pre";
733 CPTokenFieldDOMInputElement.style.background =
"transparent";
734 CPTokenFieldDOMInputElement.style.outline =
"none";
736 CPTokenFieldBlurHandler =
function(anEvent)
740 CPTokenFieldInputOwner,
741 CPTokenFieldInputOwner ? [CPTokenFieldInputOwner._tokenScrollView documentView]._DOMElement : nil,
742 CPTokenFieldDOMInputElement,
743 CPTokenFieldInputResigning,
744 @ref(CPTokenFieldInputDidBlur));
748 CPTokenFieldDOMInputElement.onblur = CPTokenFieldBlurHandler;
750 CPTokenFieldDOMStandardInputElement = CPTokenFieldDOMInputElement;
755 if ([CPTokenFieldInputOwner
isSecure])
756 CPTokenFieldDOMInputElement.type =
"password";
758 CPTokenFieldDOMInputElement.type =
"text";
760 return CPTokenFieldDOMInputElement;
763 return CPTokenFieldDOMInputElement;
771 return [
self _inputElement].value;
774 - (void)moveUp:(
id)sender
776 [[
self _autocompleteMenu] selectPrevious];
780 - (void)moveDown:(
id)sender
782 [[
self _autocompleteMenu] selectNext];
786 - (void)insertNewline:(
id)sender
790 [
self _autocompleteWithEvent:[CPApp currentEvent]];
799 - (void)insertTab:(
id)sender
801 var anEvent = [CPApp currentEvent];
804 [
self _autocompleteWithEvent:anEvent];
810 [[
self window] selectNextKeyView:
self];
821 if ([_tokenizingCharacterSet characterIsMember:[characters substringToIndex:1]])
823 [
self _autocompleteWithEvent:[CPApp currentEvent]];
828 if (_selectedRange.length)
830 [
self _removeSelectedTokens:self];
845 - (void)cancelOperation:(
id)sender
847 [
self _hideCompletions];
850 - (void)moveLeft:(
id)sender
853 if ((_selectedRange.location > 0 || _selectedRange.length) && [
self _editorValue] ==
"")
855 if (_selectedRange.length)
857 _selectedRange.length = 0;
859 _selectedRange.location--;
870 - (void)moveLeftAndModifySelection:(
id)sender
872 if (_selectedRange.location > 0 && [
self _editorValue] ==
"")
874 _selectedRange.location--;
876 _selectedRange.length++;
887 - (void)moveRight:(
id)sender
890 if ((_selectedRange.location < [[
self _tokens] count] || _selectedRange.length) && [
self _editorValue] ==
"")
892 if (_selectedRange.length)
895 _selectedRange.location =
CPMaxRange(_selectedRange);
896 _selectedRange.length = 0;
901 _selectedRange.location = MIN([[
self _tokens] count], _selectedRange.location + _selectedRange.length + 1);
914 - (void)moveRightAndModifySelection:(
id)sender
916 if (
CPMaxRange(_selectedRange) < [[
self _tokens] count] && [
self _editorValue] ==
"")
919 _selectedRange.length++;
930 - (void)deleteBackward:(
id)sender
934 if ([
self _editorValue] ==
@"")
936 [
self _hideCompletions];
940 if (_selectedRange.location > 0)
942 var tokenView = [[
self _tokens] objectAtIndex:(_selectedRange.location - 1)];
943 [
self _selectToken:tokenView byExtendingSelection:NO];
947 [
self _removeSelectedTokens:nil];
956 - (void)deleteForward:(
id)sender
960 if ([
self _editorValue] ==
@"")
963 [
self _hideCompletions];
967 if (_selectedRange.location < [[
self _tokens] count])
968 [
self _deleteToken:[[
self _tokens] objectAtIndex:[_selectedRange.location]]];
971 [
self _removeSelectedTokens:nil];
980 - (void)_selectText:(
id)sender immediately:(BOOL)immediately
991 [
super _selectText:sender immediately:immediately];
994 [
self _autocomplete];
995 _selectedRange =
CPMakeRange(0, [[
self _tokens] count]);
1004 CPTokenFieldTextDidChangeValue = [
self stringValue];
1012 [
self interpretKeyEvents:[anEvent]];
1020 if ([
self stringValue] !== CPTokenFieldTextDidChangeValue)
1046 if ([aNotification
object] !==
self)
1052 [
self _delayedShowCompletions];
1054 _selectedRange.length = 0;
1067 - (void)setCompletionDelay:(CPTimeInterval)delay
1069 _completionDelay = delay;
1074 return _completionDelay;
1090 if (textFieldContentView)
1091 [textFieldContentView setHidden:[
self stringValue] !== @""];
1094 contentView = [_tokenScrollView documentView],
1095 tokens = [
self _tokens];
1098 if (![tokens isKindOfClass:[CPArray
class]])
1102 var contentRect = CGRectMakeCopy([contentView
bounds]),
1103 contentOrigin = contentRect.origin,
1104 contentSize = contentRect.size,
1105 offset = CGPointMake(contentOrigin.x, contentOrigin.y),
1106 spaceBetweenTokens = CGSizeMake(2.0, 2.0),
1108 tokenToken = [_CPTokenFieldToken new],
1109 font = [
self currentValueForThemeAttribute:@"font"],
1111 editorInset = [
self currentValueForThemeAttribute:@"editor-inset"];
1114 offset.y += CEIL(spaceBetweenTokens.height / 2.0);
1117 [tokenToken sizeToFit];
1119 var tokenHeight = CGRectGetHeight([tokenToken
bounds]);
1121 var fitAndFrame =
function(
width, height)
1123 var r = CGRectMake(0, 0,
width, height);
1125 if (offset.x +
width >= contentSize.width && offset.x > contentOrigin.x)
1127 offset.x = contentOrigin.x;
1128 offset.y += height + spaceBetweenTokens.height;
1131 r.origin.x = offset.x;
1132 r.origin.y = offset.y;
1135 var scrollHeight = offset.y + tokenHeight + CEIL(spaceBetweenTokens.height / 2.0);
1136 if (CGRectGetHeight([contentView
bounds]) < scrollHeight)
1137 [contentView setFrameSize:CGSizeMake(CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
1139 offset.x +=
width + spaceBetweenTokens.width;
1144 var placeEditor =
function(useRemainingWidth)
1146 var element = [
self _inputElement],
1149 if (_selectedRange.length === 0)
1154 textWidth = [(element.value || @"") + "X" sizeWithFont:font].width;
1156 if (useRemainingWidth)
1157 textWidth = MAX(contentSize.width - offset.x - 1, textWidth);
1160 _inputFrame = fitAndFrame(textWidth, tokenHeight);
1162 _inputFrame.size.height = lineHeight;
1164 element.style.left = (_inputFrame.origin.x + editorInset.left) +
"px";
1165 element.style.top = (_inputFrame.origin.y + editorInset.top) +
"px";
1166 element.style.width = _inputFrame.size.width +
"px";
1167 element.style.height = _inputFrame.size.height +
"px";
1170 if (_selectedRange.length == 0)
1171 [[_tokenScrollView documentView] scrollPoint:CGPointMake(0, _inputFrame.origin.y)];
1174 for (var i = 0, count = [tokens count]; i < count; i++)
1176 if (isEditing && !_selectedRange.length && i ==
CPMaxRange(_selectedRange))
1179 var tokenView = [tokens objectAtIndex:i];
1182 if ([tokenView isKindOfClass:[
CPString class]])
1185 [tokenView setHighlighted:CPLocationInRange(i, _selectedRange)];
1186 [tokenView sizeToFit];
1188 var size = [contentView bounds].size,
1189 tokenViewSize = [tokenView bounds].size,
1190 tokenFrame = fitAndFrame(tokenViewSize.width, tokenViewSize.height);
1192 [tokenView setFrame:tokenFrame];
1194 [tokenView setButtonType:_buttonType];
1197 if (isEditing && !_selectedRange.length &&
CPMaxRange(_selectedRange) >= [tokens count])
1202 if (isEditing && _selectedRange.length)
1205 var inputElement = [
self _inputElement];
1206 inputElement.style.display =
"none";
1210 var inputElement = [
self _inputElement];
1211 inputElement.style.display =
"block";
1212 if (document.activeElement !== inputElement)
1213 inputElement.focus();
1217 var scrollHeight = offset.y + tokenHeight;
1218 if (CGRectGetHeight([contentView
bounds]) > scrollHeight)
1219 [contentView setFrameSize:CGSizeMake(CGRectGetWidth([_tokenScrollView bounds]), scrollHeight)];
1224 if (!(isEditing && _selectedRange.length == 0))
1226 var scrollToToken = _shouldScrollTo;
1229 scrollToToken = tokens[_selectedRange.location]
1231 scrollToToken = tokens[MAX(0, CPMaxRange(_selectedRange) - 1)];
1232 [
self _scrollTokenViewToVisible:scrollToToken];
1239 - (BOOL)_scrollTokenViewToVisible:(_CPTokenFieldToken)aToken
1244 return [[_tokenScrollView documentView] scrollPoint:CGPointMake(0, [aToken frameOrigin].y)];
1260 - (CPArray)_completionsForSubstring:(
CPString)substring indexOfToken:(
int)tokenIndex indexOfSelectedItem:(
int)selectedIndex
1265 return [_tokenFieldDelegate tokenField:self completionsForSubstring:substring indexOfToken:tokenIndex indexOfSelectedItem:selectedIndex];
1271 - (CGPoint)_completionOrigin:(_CPAutocompleteMenu)anAutocompleteMenu
1273 var relativeFrame = _inputFrame ? [[_tokenScrollView documentView] convertRect:_inputFrame toView:self ] : [
self bounds];
1275 return CGPointMake(CGRectGetMinX(relativeFrame), CGRectGetMaxY(relativeFrame));
1286 - (
CPString)_displayStringForRepresentedObject:(
id)representedObject
1290 var stringForRepresentedObject = [_tokenFieldDelegate tokenField:self displayStringForRepresentedObject:representedObject];
1292 if (stringForRepresentedObject !== nil)
1293 return stringForRepresentedObject;
1296 return representedObject;
1308 - (CPArray)_shouldAddObjects:(CPArray)tokens atIndex:(int)index
1312 var approvedObjects = [_tokenFieldDelegate tokenField:self shouldAddObjects:tokens atIndex:index];
1314 if (approvedObjects !== nil)
1315 return approvedObjects;
1330 - (id)_representedObjectForEditingString:(
CPString)aString
1334 var token = [_tokenFieldDelegate tokenField:self representedObjectForEditingString:aString];
1336 if (token !== nil && token !== undefined)
1345 - (BOOL)_hasMenuForRepresentedObject:(
id)aRepresentedObject
1349 return [_tokenFieldDelegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
1354 - (
CPMenu)_menuForRepresentedObject:(
id)aRepresentedObject
1359 var hasMenu = [_tokenFieldDelegate tokenField:self hasMenuForRepresentedObject:aRepresentedObject];
1362 return [_tokenFieldDelegate tokenField:self menuForRepresentedObject:aRepresentedObject] || nil;
1382 - (void)_delayedShowCompletions
1384 [[
self _autocompleteMenu] _delayedShowCompletions];
1387 - (void)_hideCompletions
1389 [_autocompleteMenu _hideCompletions];
1393 - (void)setButtonType:(
int)aButtonType
1395 if (_buttonType === aButtonType)
1398 _buttonType = aButtonType;
1406 _CPTokenFieldTokenCloseButton _deleteButton;
1407 _CPTokenFieldTokenDisclosureButton _disclosureButton;
1409 id _representedObject;
1415 return "tokenfield-token";
1423 - (id)initWithFrame:(CGRect)
frame 1425 if (
self = [super initWithFrame:
frame])
1443 _tokenField = tokenField;
1446 - (id)representedObject
1448 return _representedObject;
1451 - (void)setRepresentedObject:(
id)representedObject
1453 _representedObject = representedObject;
1457 - (void)setEditable:(BOOL)shouldBeEditable
1470 [_disclosureButton setThemeState:CPThemeStateHovered];
1471 [_deleteButton setThemeState:CPThemeStateHovered];
1484 [_disclosureButton unsetThemeState:CPThemeStateHovered];
1485 [_deleteButton unsetThemeState:CPThemeStateHovered];
1491 - (CGSize)_minimumFrameSize
1493 var size = CGSizeMakeZero(),
1494 minSize = [
self currentValueForThemeAttribute:@"min-size"],
1495 contentInset = [
self currentValueForThemeAttribute:@"content-inset"];
1498 size.height = minSize.height;
1499 size.width = MAX(minSize.width, [([
self stringValue] ||
@" ") sizeWithFont:[
self font]].width + contentInset.left + contentInset.right);
1504 - (void)setButtonType:(
int)aButtonType
1506 if (_buttonType === aButtonType)
1509 _buttonType = aButtonType;
1515 [_deleteButton removeFromSuperview];
1516 _deleteButton = nil;
1519 if (!_disclosureButton)
1521 _disclosureButton = [[_CPTokenFieldTokenDisclosureButton alloc] initWithFrame:CGRectMakeZero()];
1527 if (_disclosureButton)
1529 [_disclosureButton removeFromSuperview];
1530 _disclosureButton = nil;
1535 _deleteButton = [[_CPTokenFieldTokenCloseButton alloc] initWithFrame:CGRectMakeZero()];
1537 [_deleteButton setTarget:self];
1538 [_deleteButton setAction:@selector(_delete:)];
1553 if (bezelView && _tokenField)
1555 switch (_buttonType)
1558 var shouldBeEnabled = [
self hasMenu];
1559 [_disclosureButton setHidden:!shouldBeEnabled];
1561 if (shouldBeEnabled)
1562 [_disclosureButton setMenu:[
self menu]];
1564 var
frame = [bezelView frame],
1565 buttonOffset = [_disclosureButton currentValueForThemeAttribute:@"offset"],
1566 buttonSize = [_disclosureButton currentValueForThemeAttribute:@"min-size"];
1568 [_disclosureButton setFrame:CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
1573 var frame = [bezelView frame],
1574 buttonOffset = [_deleteButton currentValueForThemeAttribute:@"offset"],
1575 buttonSize = [_deleteButton currentValueForThemeAttribute:@"min-size"];
1577 [_deleteButton setFrame:CGRectMake(CGRectGetMaxX(frame) - buttonOffset.x, CGRectGetMinY(frame) + buttonOffset.y, buttonSize.width, buttonSize.height)];
1583 - (void)mouseDown:(
CPEvent)anEvent
1585 [_tokenField _mouseDownOnToken:self withEvent:anEvent];
1588 - (void)mouseUp:(
CPEvent)anEvent
1590 [_tokenField _mouseUpOnToken:self withEvent:anEvent];
1593 - (void)_delete:(
id)sender
1596 [_tokenField _deleteToken:self];
1601 return [_tokenField _hasMenuForRepresentedObject:_representedObject];
1606 return [_tokenField _menuForRepresentedObject:_representedObject];
1610 @implementation _CPTokenFieldTokenCloseButton :
CPButton 1619 [attributes setObject:CGPointMake(15, 5) forKey:@"offset"];
1626 return "tokenfield-token-close-button";
1629 - (void)mouseEntered:(
CPEvent)anEvent
1634 - (void)mouseExited:(
CPEvent)anEvent
1640 @implementation _CPTokenFieldTokenDisclosureButton :
CPPopUpButton 1649 [attributes setObject:CGPointMake(15, 5) forKey:@"offset"];
1656 return "tokenfield-token-disclosure-button";
1659 - (id)initWithFrame:(CGRect)aFrame
1661 if (
self = [
self initWithFrame:aFrame pullsDown:YES])
1664 [
super setTitle:@""];
1675 - (void)synchronizeTitleAndSelectedItem
1680 - (void)mouseEntered:(
CPEvent)anEvent
1685 - (void)mouseExited:(
CPEvent)anEvent
1705 _tokenizingCharacterSet = [aCoder decodeObjectForKey:CPTokenFieldTokenizingCharacterSetKey] || [[
self class] defaultTokenizingCharacterSet];
1706 _completionDelay = [aCoder decodeDoubleForKey:CPTokenFieldCompletionDelayKey] || [[
self class] defaultCompletionDelay];
1722 [aCoder encodeInt:_tokenizingCharacterSet forKey:CPTokenFieldTokenizingCharacterSetKey];
1723 [aCoder encodeDouble:_completionDelay forKey:CPTokenFieldCompletionDelayKey];
1724 [aCoder encodeInt:_buttonType forKey:CPTokenFieldButtonTypeKey];
1736 return _tokenizingCharacterSet;
1744 _tokenizingCharacterSet = aValue;
1758 - (void)setButtonType:(
int)aValue
1760 _buttonType = aValue;
BOOL makeFirstResponder:(CPResponder aResponder)
void addSubview:(CPView aSubview)
function CPUnionRange(lhsRange, rhsRange)
void encodeWithCoder:(CPCoder aCoder)
float defaultLineHeightForFont()
void textDidChange:(CPNotification note)
BOOL setThemeState:(ThemeState aState)
var CPScrollDestinationRight
CPCharacterSet tokenizingCharacterSet()
CPDictionary themeAttributes()
BOOL becomeFirstResponder()
var CPTokenFieldDelegate_tokenField_menuForRepresentedObject_
The main run loop for the application.
CPThemeStateAutocompleting
void setEditable:(BOOL shouldBeEditable)
CPResponder firstResponder()
var CPTokenFieldTokenizingCharacterSetKey
var CPTokenFieldDelegate_tokenField_displayStringForRepresentedObject_
CPTextFieldDidBlurNotification
void removeFromSuperview()
var CPTokenFieldDelegate_tokenField_completionsForSubstring_indexOfToken_indexOfSelectedItem_
var CPTokenFieldCompletionDelayKey
var CPTokenFieldDelegate_tokenField_representedObjectForEditingString_
A mutable key-value pair collection.
id characterSetWithCharactersInString:(CPString aString)
CPString defaultThemeClass()
function ThemeState(stateNames)
void setEnabled:(BOOL shouldBeEnabled)
CPRunLoop currentRunLoop()
void setEditable:(BOOL shouldBeEditable)
void textDidBlur:(CPNotification note)
CPTimeInterval completionDelay()
BOOL sendsActionOnEndEditing()
function CPEmptyRange(aRange)
function CPMaxRange(aRange)
An immutable string (collection of characters).
void keyDown:(CPEvent anEvent)
void setButtonType:(int aValue)
BOOL sendAction:to:(SEL anAction, [to] id anObject)
function CPFeatureIsCompatible(aFeature)
void setObjectValue:(id aValue)
void performBlock:argument:order:modes:(Function aBlock, [argument] id anArgument, [order] int anOrder, [modes] CPArray modes)
BOOL acceptsFirstResponder()
void textDidBeginEditing:(CPNotification note)
CGRect contentRectForBounds:(CGRect bounds)
BOOL performKeyEquivalent:(CPEvent anEvent)
void setNeedsDisplay:(BOOL aFlag)
CGRect rectForEphemeralSubviewNamed:(CPString aName)
CPTextAlignment alignment()
var CPTokenFieldButtonTypeKey
A notification that can be posted to a CPNotificationCenter.
void setHighlighted:(BOOL isHighlighted)
CPDate limitDateForMode:(CPString aMode)
void setObjectValue:(id aValue)
CPTokenFieldDeleteButtonType
var CPTokenFieldDelegate_tokenField_hasMenuForRepresentedObject_
function CPMakeRangeCopy(aRange)
Defines methods for use when archiving & restoring (enc/decoding).
CPInputTypeCanBeChangedFeature
BOOL unsetThemeState:(ThemeState aState)
var CPScrollDestinationLeft
function CPLocationInRange(aLocation, aRange)
void selectPreviousKeyView:(id sender)
CPNotification notificationWithName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
void mouseDown:(CPEvent anEvent)
void setBezeled:(BOOL shouldBeBezeled)
void textDidEndEditing:(CPNotification note)
CPCarriageReturnCharacter
BOOL sendAction:to:(SEL anAction, [to] id anObject)
CPTextFieldStatePlaceholder
CPTimeInterval defaultCompletionDelay()
void setBordered:(BOOL shouldBeBordered)
BOOL resignFirstResponder()
CPCharacterSet defaultTokenizingCharacterSet()
var CPScrollDestinationNone
CPPlatformWindow platformWindow()
var CPTokenFieldDelegate_tokenField_shouldAddObjects_atIndex_
CPTokenFieldDisclosureButtonType
CPTextFieldDidFocusNotification
BOOL scrollRectToVisible:(CGRect aRect)
id initWithCoder:(CPCoder aCoder)
void setDelegate:(id< CPTextFieldDelegate > aDelegate)
void textDidFocus:(CPNotification note)
CPRange function CPMakeRange(location, length)
function CPTextFieldBlurFunction(anEvent, owner, domElement, inputElement, resigning, didBlurRef)
CPView layoutEphemeralSubviewNamed:positioned:relativeToEphemeralSubviewNamed:(CPString aViewName, [positioned] CPWindowOrderingMode anOrderingMode, [relativeToEphemeralSubviewNamed] CPString relativeToViewName)
void textDidChange:(CPNotification aNotification)