2020-12-12 18:18:29 +00:00
|
|
|
/*
|
2006-03-26 01:01:22 +00:00
|
|
|
NSSearchFieldCell.h
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
Text field cell class for text search
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
Copyright (C) 2004 Free Software Foundation, Inc.
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
Author: H. Nikolaus Schaller <hns@computer.org>
|
|
|
|
Date: Dec 2004
|
|
|
|
Author: Fred Kiefer <fredkiefer@gmx.de>
|
|
|
|
Date: Mar 2006
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
This file is part of the GNUstep GUI Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-10-29 21:16:17 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
2006-03-26 01:01:22 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-10 04:01:49 +00:00
|
|
|
version 2 of the License, or (at your option) any later version.
|
2007-10-29 21:16:17 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2007-10-29 21:16:17 +00:00
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
2006-03-26 01:01:22 +00:00
|
|
|
|
2007-10-29 21:16:17 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2006-03-26 01:01:22 +00:00
|
|
|
License along with this library; see the file COPYING.LIB.
|
2020-12-12 18:18:29 +00:00
|
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
2007-10-29 21:16:17 +00:00
|
|
|
Boston, MA 02110-1301, USA.
|
2020-12-12 18:18:29 +00:00
|
|
|
*/
|
2006-03-26 01:01:22 +00:00
|
|
|
|
2010-12-27 13:44:18 +00:00
|
|
|
#import <Foundation/NSArray.h>
|
|
|
|
#import <Foundation/NSException.h>
|
|
|
|
#import <Foundation/NSNotification.h>
|
|
|
|
#import <Foundation/NSString.h>
|
|
|
|
#import <Foundation/NSUserDefaults.h>
|
|
|
|
|
|
|
|
#import "AppKit/NSApplication.h"
|
|
|
|
#import "AppKit/NSButtonCell.h"
|
|
|
|
#import "AppKit/NSEvent.h"
|
|
|
|
#import "AppKit/NSImage.h"
|
|
|
|
#import "AppKit/NSMenu.h"
|
|
|
|
#import "AppKit/NSMenuView.h"
|
2011-01-20 00:06:01 +00:00
|
|
|
#import "AppKit/NSPopUpButtonCell.h"
|
|
|
|
#import "AppKit/NSSearchField.h"
|
2010-12-27 13:44:18 +00:00
|
|
|
#import "AppKit/NSSearchFieldCell.h"
|
|
|
|
#import "AppKit/NSWindow.h"
|
2006-03-26 01:01:22 +00:00
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
#import "GSGuiPrivate.h"
|
|
|
|
|
|
|
|
#define ICON_WIDTH 16
|
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
@interface NSSearchFieldCell (Private)
|
|
|
|
|
|
|
|
- (NSMenu *) _buildTemplate;
|
|
|
|
- (void) _openPopup: (id)sender;
|
|
|
|
- (void) _clearSearches: (id)sender;
|
|
|
|
- (void) _loadSearches;
|
|
|
|
- (void) _saveSearches;
|
|
|
|
|
|
|
|
@end /* NSSearchFieldCell Private */
|
|
|
|
|
|
|
|
|
|
|
|
@implementation NSSearchFieldCell
|
|
|
|
|
2013-05-06 22:58:46 +00:00
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (id) initTextCell: (NSString*)aString
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
self = [super initTextCell: aString];
|
|
|
|
if (self)
|
|
|
|
{
|
|
|
|
NSButtonCell *c;
|
|
|
|
|
|
|
|
c = [[NSButtonCell alloc] initImageCell: nil];
|
|
|
|
[self setCancelButtonCell: c];
|
|
|
|
RELEASE(c);
|
|
|
|
[self resetCancelButtonCell];
|
|
|
|
|
|
|
|
c = [[NSButtonCell alloc] initImageCell: nil];
|
|
|
|
[self setSearchButtonCell: c];
|
|
|
|
RELEASE(c);
|
|
|
|
[self resetSearchButtonCell];
|
|
|
|
|
2009-04-19 04:50:04 +00:00
|
|
|
/* Don't set the searchMenuTemplate unless it is explicitly set in code or by a nib connection
|
2020-12-13 19:38:35 +00:00
|
|
|
{
|
|
|
|
NSMenu *template;
|
|
|
|
template = [self _buildTemplate];
|
|
|
|
[self setSearchMenuTemplate: template];
|
|
|
|
}
|
2009-04-19 04:50:04 +00:00
|
|
|
*/
|
2006-03-26 01:01:22 +00:00
|
|
|
|
2009-04-19 04:50:04 +00:00
|
|
|
//_recent_searches = [[NSMutableArray alloc] init];
|
2006-03-26 01:01:22 +00:00
|
|
|
//_recents_autosave_name = nil;
|
|
|
|
_max_recents = 10;
|
2010-12-27 13:44:18 +00:00
|
|
|
[self _loadSearches];
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
RELEASE(_cancel_button_cell);
|
|
|
|
RELEASE(_search_button_cell);
|
|
|
|
RELEASE(_recent_searches);
|
|
|
|
RELEASE(_recents_autosave_name);
|
|
|
|
RELEASE(_menu_template);
|
|
|
|
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2023-11-20 21:43:49 +00:00
|
|
|
- (id) copyWithZone: (NSZone*)zone
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
NSSearchFieldCell *c = [super copyWithZone: zone];
|
|
|
|
|
|
|
|
c->_cancel_button_cell = [_cancel_button_cell copyWithZone: zone];
|
|
|
|
c->_search_button_cell = [_search_button_cell copyWithZone: zone];
|
2009-04-19 04:50:04 +00:00
|
|
|
c->_recent_searches = [_recent_searches mutableCopyWithZone: zone];
|
2006-03-26 01:01:22 +00:00
|
|
|
c->_recents_autosave_name = [_recents_autosave_name copyWithZone: zone];
|
|
|
|
c->_menu_template = [_menu_template copyWithZone: zone];
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) isOpaque
|
|
|
|
{
|
|
|
|
// only if all components are opaque
|
2020-12-12 18:18:29 +00:00
|
|
|
return [super isOpaque] && [_cancel_button_cell isOpaque] &&
|
2006-03-26 01:01:22 +00:00
|
|
|
[_search_button_cell isOpaque];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
[_search_button_cell drawWithFrame: [self searchButtonRectForBounds: cellFrame]
|
2006-03-26 01:01:22 +00:00
|
|
|
inView: controlView];
|
2020-12-12 18:18:29 +00:00
|
|
|
[super drawWithFrame: [self searchTextRectForBounds: cellFrame]
|
2006-03-26 01:01:22 +00:00
|
|
|
inView: controlView];
|
2011-01-20 00:06:01 +00:00
|
|
|
if ([[self stringValue] length] > 0)
|
2020-12-12 18:18:29 +00:00
|
|
|
[_cancel_button_cell drawWithFrame: [self cancelButtonRectForBounds: cellFrame]
|
2006-03-26 01:01:22 +00:00
|
|
|
inView: controlView];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) sendsWholeSearchString
|
2020-12-12 18:18:29 +00:00
|
|
|
{
|
|
|
|
return _sends_whole_search_string;
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setSendsWholeSearchString: (BOOL)flag
|
|
|
|
{
|
|
|
|
_sends_whole_search_string = flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) sendsSearchStringImmediately
|
2020-12-12 18:18:29 +00:00
|
|
|
{
|
|
|
|
return _sends_search_string_immediatly;
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setSendsSearchStringImmediately: (BOOL)flag
|
|
|
|
{
|
|
|
|
_sends_search_string_immediatly = flag;
|
|
|
|
}
|
|
|
|
|
2009-09-07 14:08:37 +00:00
|
|
|
- (NSInteger) maximumRecents
|
2020-12-12 18:18:29 +00:00
|
|
|
{
|
2006-03-26 01:01:22 +00:00
|
|
|
return _max_recents;
|
|
|
|
}
|
|
|
|
|
2009-09-07 14:08:37 +00:00
|
|
|
- (void) setMaximumRecents: (NSInteger)max
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
if (max > 254)
|
|
|
|
{
|
|
|
|
max = 254;
|
|
|
|
}
|
|
|
|
else if (max < 0)
|
|
|
|
{
|
|
|
|
max = 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
_max_recents = max;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *) recentSearches
|
|
|
|
{
|
|
|
|
return _recent_searches;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) recentsAutosaveName
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
return _recents_autosave_name;
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (void) setRecentsAutosaveName: (NSString*)name
|
2009-04-19 04:50:04 +00:00
|
|
|
{
|
|
|
|
ASSIGN(_recents_autosave_name, name);
|
|
|
|
[self _loadSearches];
|
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (void) setRecentSearches: (NSArray*)searches
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
NSInteger max;
|
2013-01-30 09:48:54 +00:00
|
|
|
NSMutableArray *mutableSearches;
|
2006-03-26 01:01:22 +00:00
|
|
|
|
|
|
|
max = [self maximumRecents];
|
|
|
|
if ([searches count] > max)
|
|
|
|
{
|
|
|
|
id buffer[max];
|
|
|
|
|
|
|
|
[searches getObjects: buffer range: NSMakeRange(0, max)];
|
2013-01-30 09:48:54 +00:00
|
|
|
mutableSearches = [[NSMutableArray alloc] initWithObjects: buffer count: max];
|
2009-04-19 04:50:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-01-30 09:48:54 +00:00
|
|
|
mutableSearches = [[NSMutableArray alloc] initWithArray: searches];
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
2013-01-30 09:48:54 +00:00
|
|
|
[_recent_searches release];
|
|
|
|
_recent_searches = mutableSearches;
|
2009-04-19 04:50:04 +00:00
|
|
|
[self _saveSearches];
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
2020-12-12 18:18:29 +00:00
|
|
|
|
|
|
|
- (void) addToRecentSearches: (NSString*)searchTerm
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
2009-04-19 04:50:04 +00:00
|
|
|
if (!_recent_searches)
|
|
|
|
{
|
|
|
|
ASSIGN(_recent_searches, [NSMutableArray array]);
|
|
|
|
}
|
|
|
|
if (searchTerm != nil && [searchTerm length] > 0
|
2010-12-27 13:44:18 +00:00
|
|
|
&& [_recent_searches indexOfObject: searchTerm] == NSNotFound)
|
2009-04-19 04:50:04 +00:00
|
|
|
{
|
2010-12-27 13:44:18 +00:00
|
|
|
[_recent_searches addObject: searchTerm];
|
2009-04-19 04:50:04 +00:00
|
|
|
[self _saveSearches];
|
|
|
|
}
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (NSMenu*) searchMenuTemplate
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
return _menu_template;
|
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (void) setSearchMenuTemplate: (NSMenu*)menu
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
ASSIGN(_menu_template, menu);
|
2009-04-19 04:50:04 +00:00
|
|
|
if (menu)
|
|
|
|
{
|
2010-12-27 13:44:18 +00:00
|
|
|
[[self searchButtonCell] setTarget: self];
|
|
|
|
[[self searchButtonCell] setAction: @selector(_openPopup:)];
|
|
|
|
[[self searchButtonCell] sendActionOn: NSLeftMouseDownMask];
|
2009-04-19 04:50:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[self resetSearchButtonCell];
|
|
|
|
}
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (NSButtonCell*) cancelButtonCell
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
return _cancel_button_cell;
|
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (void) setCancelButtonCell: (NSButtonCell*)cell
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
ASSIGN(_cancel_button_cell, cell);
|
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (NSButtonCell*) searchButtonCell
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
return _search_button_cell;
|
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (void) setSearchButtonCell: (NSButtonCell*)cell
|
2011-01-20 00:06:01 +00:00
|
|
|
{
|
2006-03-26 01:01:22 +00:00
|
|
|
ASSIGN(_search_button_cell, cell);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) resetCancelButtonCell
|
|
|
|
{
|
|
|
|
NSButtonCell *c;
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
c = [self cancelButtonCell];
|
|
|
|
// configure the button
|
|
|
|
[c setButtonType: NSMomentaryChangeButton];
|
|
|
|
[c setBezelStyle: NSRegularSquareBezelStyle];
|
|
|
|
[c setBordered: NO];
|
|
|
|
[c setBezeled: NO];
|
|
|
|
[c setEditable: NO];
|
|
|
|
[c setImagePosition: NSImageOnly];
|
|
|
|
[c setImage: [NSImage imageNamed: @"GSStop"]];
|
2011-01-04 18:57:26 +00:00
|
|
|
[c setAction: @selector(clearSearch:)];
|
|
|
|
[c setTarget: self];
|
2006-03-26 01:01:22 +00:00
|
|
|
[c setKeyEquivalent: @"\e"];
|
2009-11-15 18:04:17 +00:00
|
|
|
[c setKeyEquivalentModifierMask: 0];
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) resetSearchButtonCell
|
|
|
|
{
|
|
|
|
NSButtonCell *c;
|
|
|
|
|
|
|
|
c = [self searchButtonCell];
|
|
|
|
// configure the button
|
|
|
|
[c setButtonType: NSMomentaryChangeButton];
|
|
|
|
[c setBezelStyle: NSRegularSquareBezelStyle];
|
|
|
|
[c setBordered: NO];
|
|
|
|
[c setBezeled: NO];
|
|
|
|
[c setEditable: NO];
|
|
|
|
[c setImagePosition: NSImageOnly];
|
|
|
|
[c setImage: [NSImage imageNamed: @"GSSearch"]];
|
2009-04-19 04:50:04 +00:00
|
|
|
[c setAction: @selector(performClick:)];
|
|
|
|
[c setTarget: self];
|
2010-12-27 13:44:18 +00:00
|
|
|
[c sendActionOn: NSLeftMouseUpMask];
|
2006-03-26 01:01:22 +00:00
|
|
|
[c setKeyEquivalent: @"\r"];
|
2009-11-15 18:04:17 +00:00
|
|
|
[c setKeyEquivalentModifierMask: 0];
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRect) cancelButtonRectForBounds: (NSRect)rect
|
|
|
|
{
|
|
|
|
NSRect part, clear;
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
NSDivideRect(rect, &clear, &part, ICON_WIDTH, NSMaxXEdge);
|
|
|
|
return clear;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRect) searchTextRectForBounds: (NSRect)rect
|
|
|
|
{
|
|
|
|
NSRect search, text, clear, part;
|
|
|
|
|
|
|
|
if (!_search_button_cell)
|
|
|
|
{
|
|
|
|
// nothing to split off
|
|
|
|
part = rect;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSDivideRect(rect, &search, &part, ICON_WIDTH, NSMinXEdge);
|
|
|
|
}
|
|
|
|
|
2006-10-15 08:34:47 +00:00
|
|
|
if (!_cancel_button_cell)
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
// nothing to split off
|
|
|
|
text = part;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NSDivideRect(part, &clear, &text, ICON_WIDTH, NSMaxXEdge);
|
|
|
|
}
|
|
|
|
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
2023-11-20 21:43:49 +00:00
|
|
|
- (NSRect) searchButtonRectForBounds: (NSRect)rect
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
|
|
|
NSRect search, part;
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
NSDivideRect(rect, &search, &part, ICON_WIDTH, NSMinXEdge);
|
|
|
|
return search;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) editWithFrame: (NSRect)aRect
|
|
|
|
inView: (NSView*)controlView
|
|
|
|
editor: (NSText*)textObject
|
|
|
|
delegate: (id)anObject
|
|
|
|
event: (NSEvent*)theEvent
|
|
|
|
{
|
|
|
|
// constrain to visible text area
|
|
|
|
[super editWithFrame: [self searchTextRectForBounds: aRect]
|
|
|
|
inView: controlView
|
|
|
|
editor: textObject
|
|
|
|
delegate: anObject
|
|
|
|
event: theEvent];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) endEditing: (NSText *)editor
|
|
|
|
{
|
2010-12-27 13:44:18 +00:00
|
|
|
[self addToRecentSearches: [[[editor string] copy] autorelease]];
|
2006-03-26 01:01:22 +00:00
|
|
|
[super endEditing: editor];
|
2020-12-12 18:18:29 +00:00
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
removeObserver: self
|
|
|
|
name: NSTextDidChangeNotification
|
2006-03-26 01:01:22 +00:00
|
|
|
object: editor];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) selectWithFrame: (NSRect)aRect
|
|
|
|
inView: (NSView*)controlView
|
|
|
|
editor: (NSText*)textObject
|
|
|
|
delegate: (id)anObject
|
2013-01-30 09:48:54 +00:00
|
|
|
start: (NSInteger)selStart
|
|
|
|
length: (NSInteger)selLength
|
2020-12-12 18:18:29 +00:00
|
|
|
{
|
2006-03-26 01:01:22 +00:00
|
|
|
// constrain to visible text area
|
|
|
|
[super selectWithFrame: [self searchTextRectForBounds: aRect]
|
|
|
|
inView: controlView
|
|
|
|
editor: textObject
|
|
|
|
delegate: anObject
|
|
|
|
start: selStart
|
|
|
|
length: selLength];
|
2020-12-12 18:18:29 +00:00
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
addObserver: self
|
2010-03-20 20:57:15 +00:00
|
|
|
selector: @selector(textDidChange:)
|
2020-12-12 18:18:29 +00:00
|
|
|
name: NSTextDidChangeNotification
|
2010-03-20 20:57:15 +00:00
|
|
|
object: textObject];
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (BOOL) trackMouse: (NSEvent *)event
|
|
|
|
inRect: (NSRect)cellFrame
|
|
|
|
ofView: (NSView *)controlView
|
2006-03-26 01:01:22 +00:00
|
|
|
untilMouseUp: (BOOL)untilMouseUp
|
|
|
|
{
|
|
|
|
NSRect rect;
|
|
|
|
NSPoint thePoint;
|
|
|
|
NSPoint location = [event locationInWindow];
|
2011-03-28 13:48:29 +00:00
|
|
|
NSText *currentEditor;
|
2006-03-26 01:01:22 +00:00
|
|
|
|
|
|
|
thePoint = [controlView convertPoint: location fromView: nil];
|
|
|
|
|
|
|
|
// check if we are within the search/stop buttons
|
|
|
|
rect = [self searchButtonRectForBounds: cellFrame];
|
|
|
|
if ([controlView mouse: thePoint inRect: rect])
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
return [[self searchButtonCell] trackMouse: event
|
|
|
|
inRect: rect
|
|
|
|
ofView: controlView
|
2006-03-26 01:01:22 +00:00
|
|
|
untilMouseUp: untilMouseUp];
|
|
|
|
}
|
|
|
|
|
|
|
|
rect = [self cancelButtonRectForBounds: cellFrame];
|
|
|
|
if ([controlView mouse: thePoint inRect: rect])
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
return [[self cancelButtonCell] trackMouse: event
|
|
|
|
inRect: rect
|
|
|
|
ofView: controlView
|
2006-03-26 01:01:22 +00:00
|
|
|
untilMouseUp: untilMouseUp];
|
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
currentEditor = ([controlView isKindOfClass: [NSControl class]]
|
2011-03-28 13:48:29 +00:00
|
|
|
? [(NSControl *)controlView currentEditor]
|
|
|
|
: nil);
|
2011-01-24 17:39:24 +00:00
|
|
|
if (currentEditor)
|
|
|
|
{
|
|
|
|
[currentEditor mouseDown: event];
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
return [super trackMouse: event
|
2006-03-26 01:01:22 +00:00
|
|
|
inRect: [self searchTextRectForBounds: cellFrame]
|
2020-12-12 18:18:29 +00:00
|
|
|
ofView: controlView
|
2006-03-26 01:01:22 +00:00
|
|
|
untilMouseUp: untilMouseUp];
|
|
|
|
}
|
|
|
|
|
2013-05-06 22:58:46 +00:00
|
|
|
- (void) resetCursorRect: (NSRect)cellFrame inView: (NSView *)controlView
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
[super resetCursorRect: [self searchTextRectForBounds: cellFrame]
|
2013-05-06 22:58:46 +00:00
|
|
|
inView: controlView];
|
|
|
|
}
|
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
- (void) textDidChange: (NSNotification *)notification
|
2020-12-12 18:18:29 +00:00
|
|
|
{
|
2006-03-26 01:01:22 +00:00
|
|
|
NSText *textObject;
|
2020-12-12 18:18:29 +00:00
|
|
|
|
|
|
|
[_control_view setNeedsDisplay: YES];
|
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
// make textChanged send action (unless disabled)
|
|
|
|
if (_sends_whole_search_string)
|
|
|
|
{
|
|
|
|
// ignore
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
textObject = [notification object];
|
|
|
|
// copy the current NSTextEdit string so that it can be read from the NSSearchFieldCell!
|
|
|
|
[self setStringValue: [textObject string]];
|
2020-12-12 18:18:29 +00:00
|
|
|
[NSApp sendAction: [self action] to: [self target] from: _control_view];
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
2011-01-04 18:57:26 +00:00
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
- (void) clearSearch: (id)sender
|
2011-01-04 18:57:26 +00:00
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
[self setStringValue: @""];
|
|
|
|
[_control_view setNeedsDisplay: YES];
|
2020-12-13 19:38:35 +00:00
|
|
|
[NSApp sendAction: [self action] to: [self target] from: _control_view];
|
2011-01-04 18:57:26 +00:00
|
|
|
}
|
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
//
|
|
|
|
// NSCoding protocol
|
|
|
|
//
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
|
|
{
|
|
|
|
[super encodeWithCoder: aCoder];
|
|
|
|
|
2009-09-07 14:08:37 +00:00
|
|
|
if ([aCoder allowsKeyedCoding])
|
|
|
|
{
|
2021-01-08 16:18:36 +00:00
|
|
|
int max = [self maximumRecents];
|
|
|
|
|
2009-09-07 14:08:37 +00:00
|
|
|
[aCoder encodeObject: _search_button_cell forKey: @"NSSearchButtonCell"];
|
|
|
|
[aCoder encodeObject: _cancel_button_cell forKey: @"NSCancelButtonCell"];
|
|
|
|
[aCoder encodeObject: _recents_autosave_name forKey: @"NSRecentsAutosaveName"];
|
|
|
|
[aCoder encodeBool: _sends_whole_search_string forKey: @"NSSendsWholeSearchString"];
|
|
|
|
[aCoder encodeInt: max forKey: @"NSMaximumRecents"];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-02-12 18:47:50 +00:00
|
|
|
NSUInteger max = [self maximumRecents];
|
2021-01-08 16:18:36 +00:00
|
|
|
|
2009-09-07 14:08:37 +00:00
|
|
|
[aCoder encodeObject: _search_button_cell];
|
|
|
|
[aCoder encodeObject: _cancel_button_cell];
|
|
|
|
[aCoder encodeObject: _recents_autosave_name];
|
|
|
|
[aCoder encodeValueOfObjCType: @encode(BOOL)
|
|
|
|
at: &_sends_whole_search_string];
|
2021-02-12 18:47:50 +00:00
|
|
|
encode_NSUInteger(aCoder, &max);
|
2009-09-07 14:08:37 +00:00
|
|
|
}
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) initWithCoder: (NSCoder*)aDecoder
|
|
|
|
{
|
|
|
|
self = [super initWithCoder: aDecoder];
|
2009-04-12 23:13:02 +00:00
|
|
|
|
2009-09-07 14:08:37 +00:00
|
|
|
if (self != nil)
|
2006-03-26 01:01:22 +00:00
|
|
|
{
|
2009-04-12 23:13:02 +00:00
|
|
|
if ([aDecoder allowsKeyedCoding])
|
|
|
|
{
|
|
|
|
[self setSearchButtonCell: [aDecoder decodeObjectForKey: @"NSSearchButtonCell"]];
|
|
|
|
[self setCancelButtonCell: [aDecoder decodeObjectForKey: @"NSCancelButtonCell"]];
|
|
|
|
[self setRecentsAutosaveName: [aDecoder decodeObjectForKey: @"NSRecentsAutosaveName"]];
|
|
|
|
[self setSendsWholeSearchString: [aDecoder decodeBoolForKey: @"NSSendsWholeSearchString"]];
|
|
|
|
[self setMaximumRecents: [aDecoder decodeIntForKey: @"NSMaximumRecents"]];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-02-12 18:47:50 +00:00
|
|
|
NSUInteger max;
|
2009-09-07 14:08:37 +00:00
|
|
|
|
2009-04-12 23:13:02 +00:00
|
|
|
[self setSearchButtonCell: [aDecoder decodeObject]];
|
|
|
|
[self setCancelButtonCell: [aDecoder decodeObject]];
|
|
|
|
[self setRecentsAutosaveName: [aDecoder decodeObject]];
|
|
|
|
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &_sends_whole_search_string];
|
2021-02-12 18:47:50 +00:00
|
|
|
decode_NSUInteger(aDecoder, &max);
|
2009-09-07 14:08:37 +00:00
|
|
|
[self setMaximumRecents: max];
|
2009-04-12 23:13:02 +00:00
|
|
|
}
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2009-04-12 23:13:02 +00:00
|
|
|
[self resetCancelButtonCell];
|
|
|
|
[self resetSearchButtonCell];
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end /* NSSearchFieldCell */
|
|
|
|
|
|
|
|
|
|
|
|
@implementation NSSearchFieldCell (Private)
|
|
|
|
|
|
|
|
/* Set up a default template
|
|
|
|
*/
|
|
|
|
- (NSMenu *) _buildTemplate
|
|
|
|
{
|
|
|
|
NSMenu *template;
|
|
|
|
NSMenuItem *item;
|
|
|
|
|
|
|
|
template = [[NSMenu alloc] init];
|
2020-12-12 18:18:29 +00:00
|
|
|
|
|
|
|
item = [[NSMenuItem alloc] initWithTitle: _(@"Recent searches")
|
2006-03-26 01:01:22 +00:00
|
|
|
action: NULL
|
|
|
|
keyEquivalent: @""];
|
|
|
|
[item setTag: NSSearchFieldRecentsTitleMenuItemTag];
|
|
|
|
[template addItem: item];
|
|
|
|
RELEASE(item);
|
2020-12-12 18:18:29 +00:00
|
|
|
|
|
|
|
item = [[NSMenuItem alloc] initWithTitle: _(@"Recent search item")
|
2006-03-26 01:01:22 +00:00
|
|
|
action: @selector(search:)
|
|
|
|
keyEquivalent: @""];
|
|
|
|
[item setTag: NSSearchFieldRecentsMenuItemTag];
|
|
|
|
[template addItem: item];
|
|
|
|
RELEASE(item);
|
2020-12-12 18:18:29 +00:00
|
|
|
|
|
|
|
item = [[NSMenuItem alloc] initWithTitle: _(@"Clear recent searches")
|
2006-03-26 01:01:22 +00:00
|
|
|
action: @selector(_clearSearches:)
|
|
|
|
keyEquivalent: @""];
|
|
|
|
[item setTag: NSSearchFieldClearRecentsMenuItemTag];
|
|
|
|
[item setTarget: self];
|
|
|
|
[template addItem: item];
|
|
|
|
RELEASE(item);
|
2020-12-12 18:18:29 +00:00
|
|
|
|
|
|
|
item = [[NSMenuItem alloc] initWithTitle: _(@"No recent searches")
|
2006-03-26 01:01:22 +00:00
|
|
|
action: NULL
|
|
|
|
keyEquivalent: @""];
|
|
|
|
[item setTag: NSSearchFieldNoRecentsMenuItemTag];
|
|
|
|
[template addItem: item];
|
|
|
|
RELEASE(item);
|
2020-12-12 18:18:29 +00:00
|
|
|
|
|
|
|
return AUTORELEASE(template);
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _openPopup: (id)sender
|
|
|
|
{
|
|
|
|
NSMenu *template;
|
|
|
|
NSMenu *popupmenu;
|
|
|
|
NSMenuView *mr;
|
|
|
|
NSRect cellFrame;
|
2020-12-12 18:18:29 +00:00
|
|
|
NSInteger i;
|
|
|
|
NSInteger recentCount = [_recent_searches count];
|
|
|
|
NSPopUpButtonCell *pbcell = [[NSPopUpButtonCell alloc] initTextCell: nil pullsDown: NO];
|
2020-12-13 19:38:35 +00:00
|
|
|
NSInteger selectedItemIndex = -1;
|
|
|
|
NSInteger newSelectedItemIndex;
|
2020-12-12 18:18:29 +00:00
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
template = [self searchMenuTemplate];
|
|
|
|
popupmenu = [[NSMenu alloc] init];
|
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
// Fill the popup menu
|
2006-03-26 01:01:22 +00:00
|
|
|
for (i = 0; i < [template numberOfItems]; i++)
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
NSInteger tag;
|
2009-04-19 04:50:04 +00:00
|
|
|
NSMenuItem *item, *newItem = nil;
|
2006-03-26 01:01:22 +00:00
|
|
|
|
|
|
|
item = (NSMenuItem*)[template itemAtIndex: i];
|
2011-01-20 00:06:01 +00:00
|
|
|
if ([item state])
|
|
|
|
selectedItemIndex = [popupmenu numberOfItems]; // remember index of previously selected item
|
2006-03-26 01:01:22 +00:00
|
|
|
tag = [item tag];
|
2009-04-19 04:50:04 +00:00
|
|
|
if (tag == NSSearchFieldRecentsTitleMenuItemTag)
|
2011-01-20 00:06:01 +00:00
|
|
|
{
|
|
|
|
if (recentCount > 0) // only show items with this tag if there are recent searches
|
|
|
|
{
|
|
|
|
newItem = [[item copy] autorelease];
|
|
|
|
}
|
|
|
|
}
|
2009-04-19 04:50:04 +00:00
|
|
|
else if (tag == NSSearchFieldClearRecentsMenuItemTag)
|
2011-01-20 00:06:01 +00:00
|
|
|
{
|
|
|
|
if (recentCount > 0) // only show items with this tag if there are recent searches
|
|
|
|
{
|
|
|
|
newItem = [[item copy] autorelease];
|
2020-12-12 18:18:29 +00:00
|
|
|
[newItem setTarget: self];
|
|
|
|
[newItem setAction: @selector(_clearSearches:)];
|
2011-01-20 00:06:01 +00:00
|
|
|
}
|
|
|
|
}
|
2009-04-19 04:50:04 +00:00
|
|
|
else if (tag == NSSearchFieldNoRecentsMenuItemTag)
|
2020-12-12 18:18:29 +00:00
|
|
|
{
|
2011-01-20 00:06:01 +00:00
|
|
|
if (recentCount == 0) // only show items with this tag if there are NO recent searches
|
|
|
|
{
|
|
|
|
newItem = [[item copy] autorelease];
|
|
|
|
}
|
|
|
|
}
|
2006-03-26 01:01:22 +00:00
|
|
|
else if (tag == NSSearchFieldRecentsMenuItemTag)
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
NSInteger j;
|
2011-01-20 00:06:01 +00:00
|
|
|
|
|
|
|
for (j = 0; j < recentCount; j++)
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
id <NSMenuItem> searchItem = [popupmenu addItemWithTitle:
|
2011-01-20 00:06:01 +00:00
|
|
|
[_recent_searches objectAtIndex: j]
|
2020-12-12 18:18:29 +00:00
|
|
|
action:
|
2011-01-20 00:06:01 +00:00
|
|
|
@selector(_searchForRecent:)
|
2020-12-12 18:18:29 +00:00
|
|
|
keyEquivalent:
|
2011-01-20 00:06:01 +00:00
|
|
|
[item keyEquivalent]];
|
|
|
|
[searchItem setTarget: self];
|
|
|
|
}
|
|
|
|
}
|
2009-04-19 04:50:04 +00:00
|
|
|
else // copy all other items without special tags from the template into the popup
|
2011-01-20 00:06:01 +00:00
|
|
|
{
|
|
|
|
newItem = [[item copy] autorelease];
|
|
|
|
}
|
2009-04-19 04:50:04 +00:00
|
|
|
|
|
|
|
if (newItem != nil)
|
2011-01-20 00:06:01 +00:00
|
|
|
{
|
|
|
|
[popupmenu addItem: newItem];
|
|
|
|
}
|
2020-12-12 18:18:29 +00:00
|
|
|
}
|
2006-03-26 01:01:22 +00:00
|
|
|
|
2020-12-12 18:18:29 +00:00
|
|
|
[pbcell setMenu: popupmenu];
|
|
|
|
[pbcell selectItemAtIndex: selectedItemIndex];
|
2020-12-13 19:38:35 +00:00
|
|
|
[pbcell setPreferredEdge: NSMinYEdge];
|
2011-01-20 00:06:01 +00:00
|
|
|
|
2009-04-19 04:50:04 +00:00
|
|
|
cellFrame = [_control_view frame];
|
2006-03-26 01:01:22 +00:00
|
|
|
mr = [popupmenu menuRepresentation];
|
|
|
|
|
2020-12-13 19:38:35 +00:00
|
|
|
[pbcell attachPopUpWithFrame: cellFrame
|
|
|
|
inView: _control_view];
|
2006-03-26 01:01:22 +00:00
|
|
|
|
2010-12-27 13:44:18 +00:00
|
|
|
[mr mouseDown: [NSApp currentEvent]];
|
2011-01-20 00:06:01 +00:00
|
|
|
newSelectedItemIndex = [pbcell indexOfSelectedItem];
|
|
|
|
if (newSelectedItemIndex != selectedItemIndex && newSelectedItemIndex != -1
|
|
|
|
&& newSelectedItemIndex < [template numberOfItems])
|
|
|
|
{
|
2020-12-13 19:38:35 +00:00
|
|
|
NSInteger tag = [[template itemAtIndex: newSelectedItemIndex] tag];
|
2011-01-20 00:06:01 +00:00
|
|
|
if (tag != NSSearchFieldRecentsTitleMenuItemTag && tag != NSSearchFieldClearRecentsMenuItemTag
|
|
|
|
&& tag != NSSearchFieldNoRecentsMenuItemTag && tag != NSSearchFieldRecentsMenuItemTag
|
2020-12-13 19:38:35 +00:00
|
|
|
&& ![[template itemAtIndex: newSelectedItemIndex] isSeparatorItem])
|
2011-01-20 00:06:01 +00:00
|
|
|
{
|
|
|
|
//new selected item within the template that's not a template special item
|
2020-12-13 19:38:35 +00:00
|
|
|
[[template itemAtIndex: selectedItemIndex] setState: NSOffState];
|
|
|
|
[[template itemAtIndex: newSelectedItemIndex] setState: NSOnState];
|
2011-01-20 00:06:01 +00:00
|
|
|
}
|
|
|
|
}
|
2006-03-26 01:01:22 +00:00
|
|
|
AUTORELEASE(popupmenu);
|
2011-01-20 00:06:01 +00:00
|
|
|
AUTORELEASE(pbcell);
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:50:04 +00:00
|
|
|
- (void) _searchForRecent: (id)sender
|
|
|
|
{
|
|
|
|
NSString *searchTerm = [sender title];
|
2010-12-27 13:44:18 +00:00
|
|
|
|
2011-01-20 00:06:01 +00:00
|
|
|
[self setStringValue: searchTerm];
|
2010-12-27 13:44:18 +00:00
|
|
|
[self performClick: self]; // do the search
|
2011-01-20 00:06:01 +00:00
|
|
|
[(id)_control_view selectText: self];
|
2009-04-19 04:50:04 +00:00
|
|
|
}
|
|
|
|
|
2006-03-26 01:01:22 +00:00
|
|
|
- (void) _clearSearches: (id)sender
|
|
|
|
{
|
|
|
|
[self setRecentSearches: [NSArray array]];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _loadSearches
|
|
|
|
{
|
|
|
|
NSArray *list;
|
|
|
|
NSString *name = [self recentsAutosaveName];
|
2010-12-27 13:44:18 +00:00
|
|
|
|
2009-04-19 04:50:04 +00:00
|
|
|
if (name)
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
list = [[NSUserDefaults standardUserDefaults]
|
2009-04-19 04:50:04 +00:00
|
|
|
stringArrayForKey: name];
|
|
|
|
[self setRecentSearches: list];
|
|
|
|
}
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _saveSearches
|
|
|
|
{
|
|
|
|
NSArray *list = [self recentSearches];
|
|
|
|
NSString *name = [self recentsAutosaveName];
|
2010-12-27 13:44:18 +00:00
|
|
|
|
2009-04-19 04:50:04 +00:00
|
|
|
if (name && list)
|
|
|
|
{
|
2020-12-12 18:18:29 +00:00
|
|
|
[[NSUserDefaults standardUserDefaults]
|
2009-04-19 04:50:04 +00:00
|
|
|
setObject: list forKey: name];
|
|
|
|
}
|
2006-03-26 01:01:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end /* NSSearchFieldCell Private */
|