44 CPMenu _searchMenuTemplate;
48 CPArray _recentSearches;
51 BOOL _sendsWholeSearchString;
52 BOOL _sendsSearchStringImmediately;
53 BOOL _canResignFirstResponder;
69 @"image-search-inset" : CGInsetMake(0, 0, 0, 5),
70 @"image-cancel-inset" : CGInsetMake(0, 5, 0, 0)
74 - (id)initWithFrame:(CGRect)frame
76 if (
self = [super initWithFrame:
frame])
79 _sendsWholeSearchString = NO;
80 _sendsSearchStringImmediately = NO;
81 _recentsAutosaveName = nil;
85 _cancelButton._DOMElement.style.cursor =
"default";
86 _searchButton._DOMElement.style.cursor =
"default";
95 _recentSearches = [CPArray array];
113 _canResignFirstResponder = YES;
118 #pragma mark Override observers 120 - (void)_removeObservers
125 [
super _removeObservers];
130 - (void)_addObservers
135 [
super _addObservers];
147 if (button != _searchButton)
149 [_searchButton removeFromSuperview];
150 _searchButton = button;
153 [_searchButton setAutoresizingMask:CPViewMaxXMargin];
164 return _searchButton;
174 searchButtonImage = (_searchMenuTemplate === nil) ? [
self valueForThemeAttribute:
@"image-search"] : [
self valueForThemeAttribute:
@"image-find"];
178 [button
setImage:searchButtonImage];
188 if (button != _cancelButton)
190 [_cancelButton removeFromSuperview];
191 _cancelButton = button;
194 [_cancelButton setAutoresizingMask:CPViewMinXMargin];
195 [_cancelButton setTarget:self];
196 [_cancelButton setAction:@selector(cancelOperation:)];
197 [_cancelButton setButtonType:CPMomentaryChangeButton];
198 [
self _updateCancelButtonVisibility];
209 return _cancelButton;
221 [button
setImage:[
self valueForThemeAttribute:@"image-cancel"]];
222 [button
setAlternateImage:[
self valueForThemeAttribute:@"image-cancel-pressed"]];
235 - (CGRect)searchTextRectForBounds:(CGRect)rect
238 width = CGRectGetWidth(rect),
244 leftOffset = CGRectGetMaxX(searchBounds) + 2;
250 width = CGRectGetMinX(cancelRect) - leftOffset;
253 return CGRectMake(leftOffset, CGRectGetMinY(rect),
width, CGRectGetHeight(rect));
261 - (CGRect)searchButtonRectForBounds:(CGRect)rect
263 var size = [[
self currentValueForThemeAttribute:@"image-search"] size] || CGSizeMakeZero(),
264 inset = [
self currentValueForThemeAttribute:@"image-search-inset"];
266 return CGRectMake(inset.left - inset.right, inset.top - inset.bottom + (CGRectGetHeight(rect) - size.height) / 2, size.width, size.height);
274 - (CGRect)cancelButtonRectForBounds:(CGRect)rect
276 var size = [[
self currentValueForThemeAttribute:@"image-cancel"] size] || CGSizeMakeZero(),
277 inset = [
self currentValueForThemeAttribute:@"image-cancel-inset"];
279 return CGRectMake(CGRectGetWidth(rect) - size.width + inset.left - inset.right, inset.top - inset.bottom + (CGRectGetHeight(rect) - size.width) / 2, size.height, size.height);
289 return _searchMenuTemplate;
297 - (void)setSearchMenuTemplate:(
CPMenu)aMenu
299 _searchMenuTemplate = aMenu;
302 [
self _loadRecentSearchList];
303 [
self _updateSearchMenu];
313 return _sendsWholeSearchString;
320 - (void)setSendsWholeSearchString:(BOOL)flag
322 _sendsWholeSearchString = flag;
331 return _sendsSearchStringImmediately;
338 - (void)setSendsSearchStringImmediately:(BOOL)flag
340 _sendsSearchStringImmediately = flag;
350 return _maximumRecents;
357 - (void)setMaximumRecents:(
int)max
364 _maximumRecents = max;
373 return _recentSearches;
381 - (void)setRecentSearches:(CPArray)searches
384 searches = [searches subarrayWithRange:CPMakeRange(0, max)];
386 _recentSearches = searches;
387 [
self _autosaveRecentSearchList];
396 return _recentsAutosaveName;
405 if (_recentsAutosaveName != nil)
406 [
self _deregisterForAutosaveNotification];
408 _recentsAutosaveName =
name;
410 if (_recentsAutosaveName != nil)
411 [
self _registerForAutosaveNotification];
416 - (CGRect)contentRectForBounds:(CGRect)bounds
422 + (double)_keyboardDelayForPartialSearchString:(
CPString)
string 424 return (6 - MIN([
string length], 4)) / 10;
434 return [
super isOpaque] && [_cancelButton isOpaque] && [_searchButton isOpaque];
437 - (void)_updateCancelButtonVisibility
447 [
self _sendPartialString];
450 [_partialStringTimer invalidate];
455 selector:@selector(_sendPartialString)
461 [
self _updateCancelButtonVisibility];
464 - (void)_sendAction:(
id)sender
469 - (BOOL)sendAction:(
SEL)anAction to:(
id)anObject
473 [_partialStringTimer invalidate];
475 [
self _addStringToRecentSearches:[
self stringValue]];
476 [
self _updateCancelButtonVisibility];
479 - (void)_addStringToRecentSearches:(
CPString)
string 481 if (
string === nil ||
string ===
@"" || [_recentSearches containsObject:
string])
485 [searches addObject:string];
487 [
self _updateSearchMenu];
493 if (CGRectContainsPoint([
self frame], aPoint))
509 if (CGRectContainsPoint([
self searchButtonRectForBounds:[
self bounds]], point))
511 if (_searchMenuTemplate == nil)
514 [_searchButton mouseDown:anEvent];
516 [
self _sendAction:self];
521 else if (CGRectContainsPoint([
self cancelButtonRectForBounds:[
self bounds]], point))
522 [_cancelButton mouseDown:anEvent];
568 [item setTag:CPSearchFieldRecentsTitleMenuItemTag];
569 [item setEnabled:NO];
570 [template addItem:item];
575 [item setTag:CPSearchFieldRecentsMenuItemTag];
576 [item setTarget:self];
577 [template addItem:item];
582 [item setTag:CPSearchFieldClearRecentsMenuItemTag];
583 [item setTarget:self];
584 [template addItem:item];
589 [item setTag:CPSearchFieldNoRecentsMenuItemTag];
590 [item setEnabled:NO];
591 [template addItem:item];
596 - (void)_updateSearchMenu
598 if (_searchMenuTemplate === nil)
602 countOfRecents = [_recentSearches count],
603 numberOfItems = [_searchMenuTemplate numberOfItems];
605 for (var i = 0; i < numberOfItems; i++)
607 var item = [[_searchMenuTemplate itemAtIndex:i] copy];
612 if (countOfRecents === 0)
615 if ([menu numberOfItems] > 0)
616 [
self _addSeparatorToMenu:menu];
621 var itemAction =
@selector(_searchFieldSearch:);
623 for (var recentIndex = 0; recentIndex < countOfRecents; ++recentIndex)
628 [recentItem setIndentationLevel:1];
629 [item setTarget:self];
630 [menu addItem:recentItem];
637 if (countOfRecents === 0)
640 if ([menu numberOfItems] > 0)
641 [
self _addSeparatorToMenu:menu];
643 [item setAction:@selector(_searchFieldClearRecents:)];
644 [item setTarget:self];
648 if (countOfRecents !== 0)
651 if ([menu numberOfItems] > 0)
652 [
self _addSeparatorToMenu:menu];
656 [item setEnabled:([item isEnabled] && [item action] != nil && [item target] != nil)];
660 [menu setDelegate:self];
665 - (void)_addSeparatorToMenu:(
CPMenu)aMenu
668 [separator setEnabled:NO];
674 _canResignFirstResponder = NO;
679 _canResignFirstResponder = YES;
686 if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![
self isEnabled])
690 location = CGPointMake(aFrame.origin.x + 10, aFrame.origin.y + aFrame.size.height - 4);
698 - (void)_sendPartialString
701 [_partialStringTimer invalidate];
704 - (void)cancelOperation:(
id)sender
709 [
self _updateCancelButtonVisibility];
712 - (void)_searchFieldSearch:(
id)sender
714 var searchString = [sender title];
717 [
self _addStringToRecentSearches:searchString];
720 [
self _sendPartialString];
723 [
self _updateCancelButtonVisibility];
726 - (void)_searchFieldClearRecents:(
id)sender
729 [
self _updateSearchMenu];
731 [
self _updateCancelButtonVisibility];
734 - (void)_registerForAutosaveNotification
739 - (void)_deregisterForAutosaveNotification
744 - (void)_autosaveRecentSearchList
746 if (_recentsAutosaveName != nil)
750 - (void)_updateAutosavedRecents:(
id)notification
752 var name = [notification object];
756 - (void)_loadRecentSearchList
765 _recentSearches = list;
780 [_searchButton removeFromSuperview];
781 [_cancelButton removeFromSuperview];
790 [coder encodeBool:_sendsWholeSearchString forKey:CPSendsWholeSearchStringKey];
791 [coder encodeBool:_sendsSearchStringImmediately forKey:CPSendsSearchStringImmediatelyKey];
792 [coder encodeInt:_maximumRecents forKey:CPMaximumRecentsKey];
794 if (_recentsAutosaveName)
795 [coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey];
797 if (_searchMenuTemplate)
798 [coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey];
803 if (
self = [super initWithCoder:coder])
806 _sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey];
807 _sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey];
808 _maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey];
810 var
template = [coder decodeObjectForKey:CPSearchMenuTemplateKey];
BOOL sendsWholeSearchString()
CPSearchFieldClearRecentsMenuItemTag
void setContinuous:(BOOL flag)
id mouseEventWithType:location:modifierFlags:timestamp:windowNumber:context:eventNumber:clickCount:pressure:(CPEventType anEventType, [location] CGPoint aPoint, [modifierFlags] unsigned modifierFlags, [timestamp] CPTimeInterval aTimestamp, [windowNumber] int aWindowNumber, [context] CPGraphicsContext aGraphicsContext, [eventNumber] int anEventNumber, [clickCount] int aClickCount, [pressure] float aPressure)
CPMenu searchMenuTemplate()
void setBezelStyle:(CPTextFieldBezelStyle aBezelStyle)
void addSubview:(CPView aSubview)
void encodeWithCoder:(CPCoder aCoder)
void setAction:(SEL anAction)
var CPSendsSearchStringImmediatelyKey
void textDidChange:(CPNotification note)
An object representation of nil.
void setTarget:(id aTarget)
BOOL becomeFirstResponder()
void addObserver:selector:name:object:(id anObserver, [selector] SEL aSelector, [name] CPString aNotificationName, [object] id anObject)
CGPoint locationInWindow()
void setCancelButton:(CPButton button)
void selectAll:(id sender)
BOOL resignFirstResponder()
void postNotificationName:object:(CPString aNotificationName, [object] id anObject)
void setImageScaling:(CPImageScaling scaling)
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
id standardUserDefaults()
void setEditable:(BOOL shouldBeEditable)
void setSearchButton:(CPButton button)
BOOL sendAction:to:(SEL anAction, [to] id anObject)
An immutable string (collection of characters).
CGPoint convertPoint:fromView:(CGPoint aPoint, [fromView] CPView aView)
var CPAutosavedRecentsChangedNotification
global CPApp CPSearchFieldRecentsTitleMenuItemTag
BOOL sendAction:to:(SEL anAction, [to] id anObject)
CGRect convertRect:toView:(CGRect aRect, [toView] CPView aView)
BOOL sendsSearchStringImmediately()
CGRect contentRectForBounds:(CGRect bounds)
CGRect searchButtonRectForBounds:(CGRect rect)
void setAutoresizingMask:(unsigned aMask)
CGRect searchTextRectForBounds:(CGRect rect)
void setStringValue:(CPString aString)
A notification that can be posted to a CPNotificationCenter.
CPTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:(CPTimeInterval seconds, [target] id aTarget, [selector] SEL aSelector, [userInfo] id userInfo, [repeats] BOOL shouldRepeat)
void setObjectValue:(id aValue)
void setSearchMenuTemplate:(CPMenu aMenu)
var CPSearchMenuTemplateKey
A timer object that can send a message after the given time interval.
Defines methods for use when archiving & restoring (enc/decoding).
var CPSendsWholeSearchStringKey
CPMenu defaultSearchMenuTemplate()
Sends messages (CPNotification) between objects.
var CPRecentsAutosaveNameKey
CPDictionary themeAttributes()
CPNotification notificationWithName:object:userInfo:(CPString aNotificationName, [object] id anObject, [userInfo] CPDictionary aUserInfo)
void setRecentsAutosaveName:(CPString name)
BOOL resignFirstResponder()
void mouseDown:(CPEvent anEvent)
void setBezeled:(BOOL shouldBeBezeled)
CPString recentsAutosaveName()
void setRecentSearches:(CPArray searches)
void removeObserver:name:object:(id anObserver, [name] CPString aNotificationName, [object] id anObject)
void setBordered:(BOOL shouldBeBordered)
CPString defaultThemeClass()
CPSearchFieldRecentsMenuItemTag
CGRect cancelButtonRectForBounds:(CGRect rect)
CPSearchFieldNoRecentsMenuItemTag