![]() |
API 0.9.5
|
00001 /* 00002 * CPSearchField.j 00003 * AppKit 00004 * 00005 * Created by cacaodev. 00006 * Copyright 2009. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 00024 CPSearchFieldRecentsTitleMenuItemTag = 1000; 00025 CPSearchFieldRecentsMenuItemTag = 1001; 00026 CPSearchFieldClearRecentsMenuItemTag = 1002; 00027 CPSearchFieldNoRecentsMenuItemTag = 1003; 00028 00029 var CPSearchFieldSearchImage = nil, 00030 CPSearchFieldFindImage = nil, 00031 CPSearchFieldCancelImage = nil, 00032 CPSearchFieldCancelPressedImage = nil; 00033 00034 var SEARCH_BUTTON_DEFAULT_WIDTH = 25.0, 00035 CANCEL_BUTTON_DEFAULT_WIDTH = 22.0, 00036 BUTTON_DEFAULT_HEIGHT = 22.0; 00037 00038 var CPAutosavedRecentsChangedNotification = @"CPAutosavedRecentsChangedNotification"; 00039 00040 var RECENT_SEARCH_PREFIX = @" "; 00041 00049 @implementation CPSearchField : CPTextField 00050 { 00051 CPButton _searchButton; 00052 CPButton _cancelButton; 00053 CPMenu _searchMenuTemplate; 00054 CPMenu _searchMenu; 00055 00056 CPString _recentsAutosaveName; 00057 CPArray _recentSearches; 00058 00059 int _maximumRecents; 00060 BOOL _sendsWholeSearchString; 00061 BOOL _sendsSearchStringImmediately; 00062 BOOL _canResignFirstResponder; 00063 CPTimer _partialStringTimer; 00064 } 00065 00066 + (CPString)defaultThemeClass 00067 { 00068 return @"searchfield" 00069 } 00070 00071 + (void)initialize 00072 { 00073 if (self != [CPSearchField class]) 00074 return; 00075 00076 var bundle = [CPBundle bundleForClass:self]; 00077 CPSearchFieldSearchImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldSearch.png"] size:_CGSizeMake(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)]; 00078 CPSearchFieldFindImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldFind.png"] size:_CGSizeMake(SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)]; 00079 CPSearchFieldCancelImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancel.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)]; 00080 CPSearchFieldCancelPressedImage = [[CPImage alloc] initWithContentsOfFile:[bundle pathForResource:@"CPSearchField/CPSearchFieldCancelPressed.png"] size:_CGSizeMake(CANCEL_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT)]; 00081 } 00082 00083 - (id)initWithFrame:(CGRect)frame 00084 { 00085 if (self = [super initWithFrame:frame]) 00086 { 00087 _maximumRecents = 10; 00088 _sendsWholeSearchString = NO; 00089 _sendsSearchStringImmediately = NO; 00090 _recentsAutosaveName = nil; 00091 00092 [self _init]; 00093 #if PLATFORM(DOM) 00094 _cancelButton._DOMElement.style.cursor = "default"; 00095 _searchButton._DOMElement.style.cursor = "default"; 00096 #endif 00097 } 00098 00099 return self; 00100 } 00101 00102 - (void)_init 00103 { 00104 _recentSearches = [CPArray array]; 00105 00106 [self setBezeled:YES]; 00107 [self setBezelStyle:CPTextFieldRoundedBezel]; 00108 [self setBordered:YES]; 00109 [self setEditable:YES]; 00110 [self setContinuous:YES]; 00111 00112 var bounds = [self bounds], 00113 cancelButton = [[CPButton alloc] initWithFrame:[self cancelButtonRectForBounds:bounds]], 00114 searchButton = [[CPButton alloc] initWithFrame:[self searchButtonRectForBounds:bounds]]; 00115 00116 [self setCancelButton:cancelButton]; 00117 [self resetCancelButton]; 00118 00119 [self setSearchButton:searchButton]; 00120 [self resetSearchButton]; 00121 00122 _canResignFirstResponder = YES; 00123 } 00124 00125 - (void)viewWillMoveToSuperview:(CPView)aView 00126 { 00127 [super viewWillMoveToSuperview:aView]; 00128 00129 // First we remove any observer that may have been in place to avoid memory leakage. 00130 [[CPNotificationCenter defaultCenter] removeObserver:self name:CPControlTextDidChangeNotification object:self]; 00131 00132 // Register the observe here if we need to. 00133 if (aView) 00134 [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_searchFieldTextDidChange:) name:CPControlTextDidChangeNotification object:self]; 00135 } 00136 00137 // Managing Buttons 00142 - (void)setSearchButton:(CPButton)button 00143 { 00144 if (button != _searchButton) 00145 { 00146 [_searchButton removeFromSuperview]; 00147 _searchButton = button; 00148 00149 [_searchButton setFrame:[self searchButtonRectForBounds:[self bounds]]]; 00150 [_searchButton setAutoresizingMask:CPViewMaxXMargin]; 00151 [self addSubview:_searchButton]; 00152 } 00153 } 00154 00159 - (CPButton)searchButton 00160 { 00161 return _searchButton; 00162 } 00163 00168 - (void)resetSearchButton 00169 { 00170 var button = [self searchButton], 00171 searchButtonImage = (_searchMenuTemplate === nil) ? CPSearchFieldSearchImage : CPSearchFieldFindImage; 00172 00173 [button setBordered:NO]; 00174 [button setImageScaling:CPScaleToFit]; 00175 [button setImage:searchButtonImage]; 00176 [button setAutoresizingMask:CPViewMaxXMargin]; 00177 } 00178 00183 - (void)setCancelButton:(CPButton)button 00184 { 00185 if (button != _cancelButton) 00186 { 00187 [_cancelButton removeFromSuperview]; 00188 _cancelButton = button; 00189 00190 [_cancelButton setFrame:[self cancelButtonRectForBounds:[self bounds]]]; 00191 [_cancelButton setAutoresizingMask:CPViewMinXMargin]; 00192 [_cancelButton setTarget:self]; 00193 [_cancelButton setAction:@selector(cancelOperation:)]; 00194 [self _updateCancelButtonVisibility]; 00195 [self addSubview:_cancelButton]; 00196 } 00197 } 00198 00203 - (CPButton)cancelButton 00204 { 00205 return _cancelButton; 00206 } 00207 00212 - (void)resetCancelButton 00213 { 00214 var button = [self cancelButton]; 00215 [button setBordered:NO]; 00216 [button setImageScaling:CPScaleToFit]; 00217 [button setImage:CPSearchFieldCancelImage]; 00218 [button setAlternateImage:CPSearchFieldCancelPressedImage]; 00219 [button setAutoresizingMask:CPViewMinXMargin]; 00220 [button setTarget:self]; 00221 [button setAction:@selector(cancelOperation:)]; 00222 } 00223 00224 // Custom Layout 00231 - (CGRect)searchTextRectForBounds:(CGRect)rect 00232 { 00233 var leftOffset = 0, 00234 width = _CGRectGetWidth(rect), 00235 bounds = [self bounds]; 00236 00237 if (_searchButton) 00238 { 00239 var searchBounds = [self searchButtonRectForBounds:bounds]; 00240 leftOffset = _CGRectGetMaxX(searchBounds) + 2; 00241 } 00242 00243 if (_cancelButton) 00244 { 00245 var cancelRect = [self cancelButtonRectForBounds:bounds]; 00246 width = _CGRectGetMinX(cancelRect) - leftOffset; 00247 } 00248 00249 return _CGRectMake(leftOffset, _CGRectGetMinY(rect), width, _CGRectGetHeight(rect)); 00250 } 00251 00257 - (CGRect)searchButtonRectForBounds:(CGRect)rect 00258 { 00259 return _CGRectMake(5, (_CGRectGetHeight(rect) - BUTTON_DEFAULT_HEIGHT) / 2, SEARCH_BUTTON_DEFAULT_WIDTH, BUTTON_DEFAULT_HEIGHT); 00260 } 00261 00267 - (CGRect)cancelButtonRectForBounds:(CGRect)rect 00268 { 00269 return _CGRectMake(_CGRectGetWidth(rect) - CANCEL_BUTTON_DEFAULT_WIDTH - 5, (_CGRectGetHeight(rect) - CANCEL_BUTTON_DEFAULT_WIDTH) / 2, BUTTON_DEFAULT_HEIGHT, BUTTON_DEFAULT_HEIGHT); 00270 } 00271 00272 // Managing Menu Templates 00277 - (CPMenu)searchMenuTemplate 00278 { 00279 return _searchMenuTemplate; 00280 } 00281 00287 - (void)setSearchMenuTemplate:(CPMenu)aMenu 00288 { 00289 _searchMenuTemplate = aMenu; 00290 00291 [self resetSearchButton]; 00292 [self _loadRecentSearchList]; 00293 [self _updateSearchMenu]; 00294 } 00295 00296 // Managing Search Modes 00301 - (BOOL)sendsWholeSearchString 00302 { 00303 return _sendsWholeSearchString; 00304 } 00305 00310 - (void)setSendsWholeSearchString:(BOOL)flag 00311 { 00312 _sendsWholeSearchString = flag; 00313 } 00314 00319 - (BOOL)sendsSearchStringImmediately 00320 { 00321 return _sendsSearchStringImmediately; 00322 } 00323 00328 - (void)setSendsSearchStringImmediately:(BOOL)flag 00329 { 00330 _sendsSearchStringImmediately = flag; 00331 } 00332 00333 // Managing Recent Search Strings 00338 - (int)maximumRecents 00339 { 00340 return _maximumRecents; 00341 } 00342 00347 - (void)setMaximumRecents:(int)max 00348 { 00349 if (max > 254) 00350 max = 254; 00351 else if (max < 0) 00352 max = 10; 00353 00354 _maximumRecents = max; 00355 } 00356 00361 - (CPArray)recentSearches 00362 { 00363 return _recentSearches; 00364 } 00365 00371 - (void)setRecentSearches:(CPArray)searches 00372 { 00373 var max = MIN([self maximumRecents], [searches count]), 00374 searches = [searches subarrayWithRange:CPMakeRange(0, max)]; 00375 00376 _recentSearches = searches; 00377 [self _autosaveRecentSearchList]; 00378 } 00379 00384 - (CPString)recentsAutosaveName 00385 { 00386 return _recentsAutosaveName; 00387 } 00388 00393 - (void)setRecentsAutosaveName:(CPString)name 00394 { 00395 if (_recentsAutosaveName != nil) 00396 [self _deregisterForAutosaveNotification]; 00397 00398 _recentsAutosaveName = name; 00399 00400 if (_recentsAutosaveName != nil) 00401 [self _registerForAutosaveNotification]; 00402 } 00403 00404 // Private methods and subclassing 00405 00406 - (CGRect)contentRectForBounds:(CGRect)bounds 00407 { 00408 var superbounds = [super contentRectForBounds:bounds]; 00409 return [self searchTextRectForBounds:superbounds]; 00410 } 00411 00412 + (double)_keyboardDelayForPartialSearchString:(CPString)string 00413 { 00414 return (6 - MIN([string length], 4)) / 10; 00415 } 00416 00417 - (CPMenu)menu 00418 { 00419 return _searchMenu; 00420 } 00421 00422 - (BOOL)isOpaque 00423 { 00424 return [super isOpaque] && [_cancelButton isOpaque] && [_searchButton isOpaque]; 00425 } 00426 00427 - (void)_updateCancelButtonVisibility 00428 { 00429 [_cancelButton setHidden:([[self stringValue] length] === 0)]; 00430 } 00431 00432 - (void)_searchFieldTextDidChange:(CPNotification)aNotification 00433 { 00434 if (![self sendsWholeSearchString]) 00435 { 00436 if ([self sendsSearchStringImmediately]) 00437 [self _sendPartialString]; 00438 else 00439 { 00440 [_partialStringTimer invalidate]; 00441 var timeInterval = [CPSearchField _keyboardDelayForPartialSearchString:[self stringValue]]; 00442 00443 _partialStringTimer = [CPTimer scheduledTimerWithTimeInterval:timeInterval 00444 target:self 00445 selector:@selector(_sendPartialString) 00446 userInfo:nil 00447 repeats:NO]; 00448 } 00449 } 00450 00451 [self _updateCancelButtonVisibility]; 00452 } 00453 00454 - (void)_sendAction:(id)sender 00455 { 00456 [self sendAction:[self action] to:[self target]]; 00457 } 00458 00459 - (void)sendAction:(SEL)anAction to:(id)anObject 00460 { 00461 [super sendAction:anAction to:anObject]; 00462 00463 [_partialStringTimer invalidate]; 00464 00465 [self _addStringToRecentSearches:[self stringValue]]; 00466 [self _updateCancelButtonVisibility]; 00467 } 00468 00469 - (void)_addStringToRecentSearches:(CPString)string 00470 { 00471 if (string === nil || string === @"" || [_recentSearches containsObject:string]) 00472 return; 00473 00474 var searches = [CPMutableArray arrayWithArray:_recentSearches]; 00475 [searches addObject:string]; 00476 [self setRecentSearches:searches]; 00477 [self _updateSearchMenu]; 00478 } 00479 00480 - (CPView)hitTest:(CGPoint)aPoint 00481 { 00482 // Make sure a hit anywhere within the search field returns the search field itself 00483 if (_CGRectContainsPoint([self frame], aPoint)) 00484 return self; 00485 else 00486 return nil; 00487 } 00488 00489 - (BOOL)resignFirstResponder 00490 { 00491 return _canResignFirstResponder && [super resignFirstResponder]; 00492 } 00493 00494 - (void)mouseDown:(CPEvent)anEvent 00495 { 00496 var location = [anEvent locationInWindow], 00497 point = [self convertPoint:location fromView:nil]; 00498 00499 if (_CGRectContainsPoint([self searchButtonRectForBounds:[self bounds]], point)) 00500 { 00501 if (_searchMenuTemplate == nil) 00502 [self _sendAction:self]; 00503 else 00504 [self _showMenu]; 00505 } 00506 else if (_CGRectContainsPoint([self cancelButtonRectForBounds:[self bounds]], point)) 00507 [_cancelButton mouseDown:anEvent]; 00508 else 00509 [super mouseDown:anEvent]; 00510 } 00511 00545 - (CPMenu)defaultSearchMenuTemplate 00546 { 00547 var template = [[CPMenu alloc] init], 00548 item; 00549 00550 item = [[CPMenuItem alloc] initWithTitle:@"Recent Searches" 00551 action:nil 00552 keyEquivalent:@""]; 00553 [item setTag:CPSearchFieldRecentsTitleMenuItemTag]; 00554 [item setEnabled:NO]; 00555 [template addItem:item]; 00556 00557 item = [[CPMenuItem alloc] initWithTitle:@"Recent search item" 00558 action:@selector(_searchFieldSearch:) 00559 keyEquivalent:@""]; 00560 [item setTag:CPSearchFieldRecentsMenuItemTag]; 00561 [item setTarget:self]; 00562 [template addItem:item]; 00563 00564 item = [[CPMenuItem alloc] initWithTitle:@"Clear Recent Searches" 00565 action:@selector(_searchFieldClearRecents:) 00566 keyEquivalent:@""]; 00567 [item setTag:CPSearchFieldClearRecentsMenuItemTag]; 00568 [item setTarget:self]; 00569 [template addItem:item]; 00570 00571 item = [[CPMenuItem alloc] initWithTitle:@"No Recent Searches" 00572 action:nil 00573 keyEquivalent:@""]; 00574 [item setTag:CPSearchFieldNoRecentsMenuItemTag]; 00575 [item setEnabled:NO]; 00576 [template addItem:item]; 00577 00578 return template; 00579 } 00580 00581 - (void)_updateSearchMenu 00582 { 00583 if (_searchMenuTemplate === nil) 00584 return; 00585 00586 var menu = [[CPMenu alloc] init], 00587 countOfRecents = [_recentSearches count], 00588 numberOfItems = [_searchMenuTemplate numberOfItems]; 00589 00590 for (var i = 0; i < numberOfItems; i++) 00591 { 00592 var item = [[_searchMenuTemplate itemAtIndex:i] copy]; 00593 00594 switch ([item tag]) 00595 { 00596 case CPSearchFieldRecentsTitleMenuItemTag: 00597 if (countOfRecents === 0) 00598 continue; 00599 00600 if ([menu numberOfItems] > 0) 00601 [self _addSeparatorToMenu:menu]; 00602 break; 00603 00604 case CPSearchFieldRecentsMenuItemTag: 00605 { 00606 var itemAction = @selector(_searchFieldSearch:); 00607 00608 for (var recentIndex = 0; recentIndex < countOfRecents; ++recentIndex) 00609 { 00610 // RECENT_SEARCH_PREFIX is a hack until CPMenuItem -setIndentationLevel works 00611 var recentItem = [[CPMenuItem alloc] initWithTitle:RECENT_SEARCH_PREFIX + [_recentSearches objectAtIndex:recentIndex] 00612 action:itemAction 00613 keyEquivalent:[item keyEquivalent]]; 00614 [item setTarget:self]; 00615 [menu addItem:recentItem]; 00616 } 00617 00618 continue; 00619 } 00620 00621 case CPSearchFieldClearRecentsMenuItemTag: 00622 if (countOfRecents === 0) 00623 continue; 00624 00625 if ([menu numberOfItems] > 0) 00626 [self _addSeparatorToMenu:menu]; 00627 00628 [item setAction:@selector(_searchFieldClearRecents:)]; 00629 [item setTarget:self]; 00630 break; 00631 00632 case CPSearchFieldNoRecentsMenuItemTag: 00633 if (countOfRecents !== 0) 00634 continue; 00635 00636 if ([menu numberOfItems] > 0) 00637 [self _addSeparatorToMenu:menu]; 00638 break; 00639 } 00640 00641 [item setEnabled:([item isEnabled] && [item action] != nil && [item target] != nil)]; 00642 [menu addItem:item]; 00643 } 00644 00645 [menu setDelegate:self]; 00646 00647 _searchMenu = menu; 00648 } 00649 00650 - (void)_addSeparatorToMenu:(CPMenu)aMenu 00651 { 00652 var separator = [CPMenuItem separatorItem]; 00653 [separator setEnabled:NO]; 00654 [aMenu addItem:separator]; 00655 } 00656 00657 - (void)menuWillOpen:(CPMenu)menu 00658 { 00659 _canResignFirstResponder = NO; 00660 } 00661 00662 - (void)menuDidClose:(CPMenu)menu 00663 { 00664 _canResignFirstResponder = YES; 00665 00666 [self becomeFirstResponder]; 00667 } 00668 00669 - (void)_showMenu 00670 { 00671 if (_searchMenu === nil || [_searchMenu numberOfItems] === 0 || ![self isEnabled]) 00672 return; 00673 00674 var aFrame = [[self superview] convertRect:[self frame] toView:nil], 00675 location = CPMakePoint(aFrame.origin.x + 10, aFrame.origin.y + aFrame.size.height - 4); 00676 00677 var anEvent = [CPEvent mouseEventWithType:CPRightMouseDown location:location modifierFlags:0 timestamp:[[CPApp currentEvent] timestamp] windowNumber:[[self window] windowNumber] context:nil eventNumber:1 clickCount:1 pressure:0]; 00678 00679 [self selectAll:nil]; 00680 [CPMenu popUpContextMenu:_searchMenu withEvent:anEvent forView:self]; 00681 } 00682 00683 - (void)_sendPartialString 00684 { 00685 [super sendAction:[self action] to:[self target]]; 00686 [_partialStringTimer invalidate]; 00687 } 00688 00689 - (void)cancelOperation:(id)sender 00690 { 00691 [self setObjectValue:@""]; 00692 [self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]]; 00693 00694 [self _updateCancelButtonVisibility]; 00695 } 00696 00697 - (void)_searchFieldSearch:(id)sender 00698 { 00699 var searchString = [[sender title] substringFromIndex:[RECENT_SEARCH_PREFIX length]]; 00700 00701 if ([sender tag] != CPSearchFieldRecentsMenuItemTag) 00702 [self _addStringToRecentSearches:searchString]; 00703 00704 [self setObjectValue:searchString]; 00705 [self _sendPartialString]; 00706 [self selectAll:nil]; 00707 00708 [self _updateCancelButtonVisibility]; 00709 } 00710 00711 - (void)_searchFieldClearRecents:(id)sender 00712 { 00713 [self setRecentSearches:[CPArray array]]; 00714 [self _updateSearchMenu]; 00715 [self setStringValue:@""]; 00716 [self _updateCancelButtonVisibility]; 00717 } 00718 00719 - (void)_registerForAutosaveNotification 00720 { 00721 [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(_updateAutosavedRecents:) name:CPAutosavedRecentsChangedNotification object:_recentsAutosaveName]; 00722 } 00723 00724 - (void)_deregisterForAutosaveNotification 00725 { 00726 [[CPNotificationCenter defaultCenter] removeObserver:self name:CPAutosavedRecentsChangedNotification object:_recentsAutosaveName]; 00727 } 00728 00729 - (void)_autosaveRecentSearchList 00730 { 00731 if (_recentsAutosaveName != nil) 00732 [[CPNotificationCenter defaultCenter] postNotificationName:CPAutosavedRecentsChangedNotification object:_recentsAutosaveName]; 00733 } 00734 00735 - (void)_updateAutosavedRecents:(id)notification 00736 { 00737 var name = [notification object]; 00738 [[CPUserDefaults standardUserDefaults] setObject:_recentSearches forKey:name]; 00739 } 00740 00741 - (void)_loadRecentSearchList 00742 { 00743 var name = [self recentsAutosaveName]; 00744 if (name === nil) 00745 return; 00746 00747 var list = [[CPUserDefaults standardUserDefaults] objectForKey:name]; 00748 00749 if (list !== nil) 00750 _recentSearches = list; 00751 } 00752 00753 @end 00754 00755 var CPRecentsAutosaveNameKey = @"CPRecentsAutosaveNameKey", 00756 CPSendsWholeSearchStringKey = @"CPSendsWholeSearchStringKey", 00757 CPSendsSearchStringImmediatelyKey = @"CPSendsSearchStringImmediatelyKey", 00758 CPMaximumRecentsKey = @"CPMaximumRecentsKey", 00759 CPSearchMenuTemplateKey = @"CPSearchMenuTemplateKey"; 00760 00761 @implementation CPSearchField (CPCoding) 00762 00763 - (void)encodeWithCoder:(CPCoder)coder 00764 { 00765 [_searchButton removeFromSuperview]; 00766 [_cancelButton removeFromSuperview]; 00767 00768 [super encodeWithCoder:coder]; 00769 00770 if (_searchButton) 00771 [self addSubview:_searchButton]; 00772 if (_cancelButton) 00773 [self addSubview:_cancelButton]; 00774 00775 [coder encodeBool:_sendsWholeSearchString forKey:CPSendsWholeSearchStringKey]; 00776 [coder encodeBool:_sendsSearchStringImmediately forKey:CPSendsSearchStringImmediatelyKey]; 00777 [coder encodeInt:_maximumRecents forKey:CPMaximumRecentsKey]; 00778 00779 if (_recentsAutosaveName) 00780 [coder encodeObject:_recentsAutosaveName forKey:CPRecentsAutosaveNameKey]; 00781 00782 if (_searchMenuTemplate) 00783 [coder encodeObject:_searchMenuTemplate forKey:CPSearchMenuTemplateKey]; 00784 } 00785 00786 - (id)initWithCoder:(CPCoder)coder 00787 { 00788 if (self = [super initWithCoder:coder]) 00789 { 00790 [self setRecentsAutosaveName:[coder decodeObjectForKey:CPRecentsAutosaveNameKey]]; 00791 _sendsWholeSearchString = [coder decodeBoolForKey:CPSendsWholeSearchStringKey]; 00792 _sendsSearchStringImmediately = [coder decodeBoolForKey:CPSendsSearchStringImmediatelyKey]; 00793 _maximumRecents = [coder decodeIntForKey:CPMaximumRecentsKey]; 00794 00795 var template = [coder decodeObjectForKey:CPSearchMenuTemplateKey]; 00796 00797 if (template) 00798 [self setSearchMenuTemplate:template]; 00799 00800 [self _init]; 00801 } 00802 00803 return self; 00804 } 00805 00806 @end