mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-25 06:21:09 +00:00
method only for the Space key. Fix key view loop of NSAlert panels and NSSavePanel so that all buttons become reachable with the Tab key. Make Escape key equivalent of the Cancel button of NSSavePanel. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27011 72102866-910b-0410-8b05-ffd578937521
578 lines
14 KiB
Objective-C
578 lines
14 KiB
Objective-C
/** <title>NSPopUpButton</title>
|
|
|
|
<abstract>Popup list class</abstract>
|
|
|
|
Copyright (C) 1996 Free Software Foundation, Inc.
|
|
|
|
Author: Scott Christley <scottc@net-community.com>
|
|
Date: 1996
|
|
Author: Michael Hanni <mhanni@sprintmail.com>
|
|
Date: June 1999
|
|
|
|
This file is part of the GNUstep GUI Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <Foundation/Foundation.h>
|
|
#include <Foundation/NSKeyValueObserving.h>
|
|
#include "AppKit/NSApplication.h"
|
|
#include "AppKit/NSEvent.h"
|
|
#include "AppKit/NSKeyValueBinding.h"
|
|
#include "AppKit/NSPopUpButton.h"
|
|
#include "AppKit/NSPopUpButtonCell.h"
|
|
#include "AppKit/NSMenu.h"
|
|
#include "AppKit/NSMenuItem.h"
|
|
#include "AppKit/NSMenuView.h"
|
|
|
|
/*
|
|
* class variables
|
|
*/
|
|
Class _nspopupbuttonCellClass = 0;
|
|
|
|
/*
|
|
* NSPopUpButton implementation
|
|
*/
|
|
|
|
@implementation NSPopUpButton
|
|
|
|
/*
|
|
* Class methods
|
|
*/
|
|
+ (void) initialize
|
|
{
|
|
if (self == [NSPopUpButton class])
|
|
{
|
|
// Initial version
|
|
[self setVersion: 1];
|
|
[self setCellClass: [NSPopUpButtonCell class]];
|
|
|
|
[self exposeBinding: NSSelectedIndexBinding];
|
|
}
|
|
}
|
|
|
|
+ (Class) cellClass
|
|
{
|
|
return _nspopupbuttonCellClass;
|
|
}
|
|
|
|
+ (void) setCellClass: (Class)classId
|
|
{
|
|
_nspopupbuttonCellClass = classId;
|
|
}
|
|
|
|
/*
|
|
* Initializing an NSPopUpButton
|
|
*/
|
|
- (id) init
|
|
{
|
|
return [self initWithFrame: NSZeroRect pullsDown: NO];
|
|
}
|
|
|
|
- (id) initWithFrame: (NSRect)frameRect
|
|
{
|
|
return [self initWithFrame: frameRect pullsDown: NO];
|
|
}
|
|
|
|
/** <p>Initialize and returns a new NSPopUpButton into the frame frameRect
|
|
and specified by flag if the NSPopUpButton is a pull-down list</p>
|
|
<p>See Also: -setPullsDown: [NSView-initWithFrame:]</p>
|
|
*/
|
|
- (id) initWithFrame: (NSRect)frameRect
|
|
pullsDown: (BOOL)flag
|
|
{
|
|
if ( ! ( self = [super initWithFrame: frameRect] ) )
|
|
return nil;
|
|
|
|
[self setPullsDown: flag];
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
/*
|
|
In NSView, -menuForEvent: returns [self menu] as the context menu of the
|
|
view. Since our -menu returns the menu for our pop-up, we need to override
|
|
this to return nil to indicate that we have no context menu.
|
|
*/
|
|
- (NSMenu *)menuForEvent:(NSEvent *)theEvent
|
|
{
|
|
return nil;
|
|
}
|
|
|
|
|
|
- (void) setMenu: (NSMenu*)menu
|
|
{
|
|
[_cell setMenu: menu];
|
|
}
|
|
|
|
- (NSMenu*) menu
|
|
{
|
|
return [_cell menu];
|
|
}
|
|
|
|
/**<p>Sets whether the NSPopUpButton's cell has a pulls-down list ( YES )
|
|
or a pop-up list (NO) </p> <p>See Also: -pullsDown
|
|
[NSPopUpButtonCell-setPullsDown:]</p>
|
|
*/
|
|
|
|
- (void) setPullsDown: (BOOL)flag
|
|
{
|
|
[_cell setPullsDown: flag];
|
|
}
|
|
/** <p>Returns whether the NSPopUpButton's cell has a pulls-down list ( YES )
|
|
or a pop-up list (NO) </p>
|
|
<p>See Also: -setPullsDown: [NSPopUpButtonCell-pullsDown]</p>
|
|
*/
|
|
- (BOOL) pullsDown
|
|
{
|
|
return [_cell pullsDown];
|
|
}
|
|
|
|
- (void) setAutoenablesItems: (BOOL)flag
|
|
{
|
|
[_cell setAutoenablesItems: flag];
|
|
}
|
|
|
|
- (BOOL) autoenablesItems
|
|
{
|
|
return [_cell autoenablesItems];
|
|
}
|
|
|
|
/** <p>Inserts a new item with title as its title at the end of the list and
|
|
synchronizes the NSPopUpButton's title with the title of the selected item.
|
|
</p><p>See Also: [NSPopUpButtonCell-addItemWithTitle:]
|
|
-synchronizeTitleAndSelectedItem</p>
|
|
*/
|
|
- (void) addItemWithTitle: (NSString *)title
|
|
{
|
|
[_cell addItemWithTitle: title];
|
|
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
/** <p>Inserts a new list of items with titles as titles at the end of the list
|
|
and synchronizes the NSPopUpButton's title with the title of the selected
|
|
item.</p><p>See Also: [NSPopUpButtonCell-addItemsWithTitles:]
|
|
-synchronizeTitleAndSelectedItem</p>
|
|
*/
|
|
- (void) addItemsWithTitles: (NSArray*)itemTitles
|
|
{
|
|
[_cell addItemsWithTitles: itemTitles];
|
|
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
/** <p>Inserts a new item with title as its title at the specified index
|
|
and synchronizes the NSPopUpButton's title with the title of the selected
|
|
item.</p><p>See Also: [NSPopUpButtonCell-insertItemWithTitle:atIndex:]
|
|
-synchronizeTitleAndSelectedItem</p>
|
|
*/
|
|
- (void) insertItemWithTitle: (NSString*)title
|
|
atIndex: (int)index
|
|
{
|
|
[_cell insertItemWithTitle: title
|
|
atIndex: index];
|
|
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
/** <p>Removes all items from the item list and synchronizes the
|
|
NSPopUpButton's title with the title of the selected</p>
|
|
<p>See Also: [NSPopUpButtonCell-removeAllItems] -removeItemWithTitle:
|
|
-synchronizeTitleAndSelectedItem</p>
|
|
*/
|
|
- (void) removeAllItems
|
|
{
|
|
[_cell removeAllItems];
|
|
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
/** <p>Removes the item specified with title as its title from the item list
|
|
and synchronizes the NSPopUpButton's title with the title of the selected
|
|
</p><p>See Also: [NSPopUpButtonCell-removeItemWithTitle:]
|
|
-removeAllItems -removeItemAtIndex: -synchronizeTitleAndSelectedItem</p>
|
|
*/
|
|
- (void) removeItemWithTitle: (NSString*)title
|
|
{
|
|
[_cell removeItemWithTitle: title];
|
|
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
/** <p>Removes the item at the specified index index from the item list
|
|
and synchronizes the NSPopUpButton's title with the title of the selected
|
|
</p><p>See Also: [NSPopUpButtonCell-removeItemAtIndex:]
|
|
-removeAllItems -removeItemWithTitle: -synchronizeTitleAndSelectedItem</p>
|
|
*/
|
|
- (void) removeItemAtIndex: (int)index
|
|
{
|
|
[_cell removeItemAtIndex: index];
|
|
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
/** <p>Returns the selected item</p>
|
|
<p>See Also: [NSPopUpButtonCell-selectedItem]</p>
|
|
*/
|
|
- (id <NSMenuItem>) selectedItem
|
|
{
|
|
return [_cell selectedItem];
|
|
}
|
|
|
|
/** <p>Returns the title of the selected item</p>
|
|
<p>See Also: [NSPopUpButtonCell-titleOfSelectedItem]</p>
|
|
*/
|
|
- (NSString*) titleOfSelectedItem
|
|
{
|
|
return [_cell titleOfSelectedItem];
|
|
}
|
|
|
|
/**<p>Returns the index of the selected item</p>
|
|
<p>See Also: [NSPopUpButtonCell-indexOfSelectedItem]</p>
|
|
*/
|
|
- (int) indexOfSelectedItem
|
|
{
|
|
return [_cell indexOfSelectedItem];
|
|
}
|
|
|
|
- (void) selectItem: (id <NSMenuItem>)anObject
|
|
{
|
|
[self willChangeValueForKey: NSSelectedIndexBinding];
|
|
[_cell selectItem: anObject];
|
|
[self didChangeValueForKey: NSSelectedIndexBinding];
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
/**<p>Select the item at index <var>index</var> and synchronizes the
|
|
NSPopUpButton's title with the title of the selected</p><p>See Also:
|
|
[NSPopUpButtonCell-selectItemAtIndex:] -synchronizeTitleAndSelectedItem</p>
|
|
*/
|
|
- (void) selectItemAtIndex: (int)index
|
|
{
|
|
[self willChangeValueForKey: NSSelectedIndexBinding];
|
|
[_cell selectItemAtIndex: index];
|
|
[self didChangeValueForKey: NSSelectedIndexBinding];
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
/**<p>Select the item with title <var>title</var> and synchronizes the
|
|
NSPopUpButton's title with the title of the selected</p><p>See Also:
|
|
[NSPopUpButtonCell-selectItemWithTitle:]
|
|
-synchronizeTitleAndSelectedItem</p>
|
|
*/
|
|
- (void) selectItemWithTitle: (NSString*)title
|
|
{
|
|
[self willChangeValueForKey: NSSelectedIndexBinding];
|
|
[_cell selectItemWithTitle: title];
|
|
[self didChangeValueForKey: NSSelectedIndexBinding];
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
- (BOOL) selectItemWithTag: (NSInteger)tag
|
|
{
|
|
int index = [self indexOfItemWithTag: tag];
|
|
|
|
if (index >= 0)
|
|
{
|
|
[self selectItemAtIndex: index];
|
|
return YES;
|
|
}
|
|
else
|
|
{
|
|
return NO;
|
|
}
|
|
}
|
|
|
|
|
|
/** <p>Returns the number of items in the item list</p>
|
|
<p>See Also: [NSPopUpButtonCell-numberOfItems]</p>
|
|
*/
|
|
- (int) numberOfItems
|
|
{
|
|
return [_cell numberOfItems];
|
|
}
|
|
|
|
- (NSArray*) itemArray
|
|
{
|
|
return [_cell itemArray];
|
|
}
|
|
|
|
/**<p>Returns the NSMenuItem at index index or nil if index is out of
|
|
range</p><p>See Also: [NSPopUpButtonCell-itemAtIndex:] </p>
|
|
*/
|
|
- (id <NSMenuItem>) itemAtIndex: (int)index
|
|
{
|
|
return [_cell itemAtIndex: index];
|
|
}
|
|
|
|
/** <p>Returns the item's title at index <var>index</var></p>
|
|
*/
|
|
- (NSString*) itemTitleAtIndex: (int)index
|
|
{
|
|
return [_cell itemTitleAtIndex: index];
|
|
}
|
|
|
|
/**<p>Returns an array containing the items's titles</p>
|
|
*/
|
|
- (NSArray*) itemTitles
|
|
{
|
|
return [_cell itemTitles];
|
|
}
|
|
|
|
/**<p>Returns the NSMenuItem with title as its title</p>
|
|
*/
|
|
- (id <NSMenuItem>) itemWithTitle: (NSString*)title
|
|
{
|
|
return [_cell itemWithTitle: title];
|
|
}
|
|
|
|
/**<p> Returns the last NSMenuItem of the list</p>
|
|
*/
|
|
- (id <NSMenuItem>) lastItem
|
|
{
|
|
return [_cell lastItem];
|
|
}
|
|
|
|
- (int) indexOfItem: (id <NSMenuItem>)anObject
|
|
{
|
|
return [_cell indexOfItem: anObject];
|
|
}
|
|
|
|
/**<p>Returns the index of the item with tag as its tag. Returns -1
|
|
if the cell is not found</p><p>See Also:
|
|
[NSPopUpButtonCell-indexOfItemWithTag:] -indexOfItemWithTitle:
|
|
-indexOfItemWithRepresentedObject:</p>
|
|
*/
|
|
- (int) indexOfItemWithTag: (int)tag
|
|
{
|
|
return [_cell indexOfItemWithTag: tag];
|
|
}
|
|
|
|
/**<p>Returns the index of the item with title as its title. Returns -1
|
|
if the cell is not found</p><p>See Also:
|
|
[NSPopUpButtonCell-indexOfItemWithTitle:] -indexOfItemWithTag:
|
|
-indexOfItemWithRepresentedObject:</p>
|
|
*/
|
|
- (int) indexOfItemWithTitle: (NSString*)title
|
|
{
|
|
return [_cell indexOfItemWithTitle: title];
|
|
}
|
|
|
|
- (int) indexOfItemWithRepresentedObject: (id)anObject
|
|
{
|
|
return [_cell indexOfItemWithRepresentedObject: anObject];
|
|
}
|
|
|
|
- (int) indexOfItemWithTarget: (id)target
|
|
andAction: (SEL)actionSelector
|
|
{
|
|
return [_cell indexOfItemWithTarget: target andAction: actionSelector];
|
|
}
|
|
|
|
- (void) setPreferredEdge: (NSRectEdge)edge
|
|
{
|
|
[_cell setPreferredEdge: edge];
|
|
}
|
|
|
|
- (NSRectEdge) preferredEdge
|
|
{
|
|
return [_cell preferredEdge];
|
|
}
|
|
|
|
- (void) setTitle: (NSString*)aString
|
|
{
|
|
[_cell setTitle: aString];
|
|
[self synchronizeTitleAndSelectedItem];
|
|
}
|
|
|
|
- (void) synchronizeTitleAndSelectedItem
|
|
{
|
|
[_cell synchronizeTitleAndSelectedItem];
|
|
[self setNeedsDisplay: YES];
|
|
}
|
|
|
|
- (BOOL) resignFirstResponder
|
|
{
|
|
[_cell dismissPopUp];
|
|
|
|
return [super resignFirstResponder];
|
|
}
|
|
|
|
- (BOOL) performKeyEquivalent: (NSEvent*)theEvent
|
|
{
|
|
NSMenu *m = [self menu];
|
|
NSMenuItem *oldSelectedItem = [_cell selectedItem];
|
|
|
|
if (m != nil)
|
|
{
|
|
if ([m performKeyEquivalent: theEvent])
|
|
{
|
|
// pullsDown does not change selected item
|
|
if ([_cell pullsDown])
|
|
{
|
|
[self selectItem: oldSelectedItem];
|
|
}
|
|
else
|
|
{
|
|
/* If the key equivalent was performed, redisplay ourselves
|
|
* to account for potential changes in the selected item.
|
|
*/
|
|
[self setNeedsDisplay: YES];
|
|
}
|
|
return YES;
|
|
}
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
- (void) mouseDown: (NSEvent*)theEvent
|
|
{
|
|
[_cell trackMouse: theEvent
|
|
inRect: [self bounds]
|
|
ofView: self
|
|
untilMouseUp: YES];
|
|
}
|
|
|
|
- (void) keyDown: (NSEvent*)theEvent
|
|
{
|
|
// FIXME: This method also handles the key events for the popup menu window,
|
|
// as menu windows cannot become key window.
|
|
if ([self isEnabled])
|
|
{
|
|
NSString *characters = [theEvent characters];
|
|
unichar character = 0;
|
|
|
|
if ([characters length] > 0)
|
|
{
|
|
character = [characters characterAtIndex: 0];
|
|
}
|
|
|
|
switch (character)
|
|
{
|
|
case NSNewlineCharacter:
|
|
case NSEnterCharacter:
|
|
case NSCarriageReturnCharacter:
|
|
/* Handle Enter and Return keys only when the menu is visible.
|
|
The button's action to pop up the menu is initiated only by
|
|
the Space key similar to other buttons. */
|
|
{
|
|
NSMenuView *menuView = [[_cell menu] menuRepresentation];
|
|
if ([[menuView window] isVisible] == NO)
|
|
break;
|
|
}
|
|
case ' ':
|
|
{
|
|
int selectedIndex;
|
|
NSMenuView *menuView;
|
|
|
|
// Beep, as on OS, and then return.
|
|
if ([[_cell menu] numberOfItems] == 0)
|
|
{
|
|
NSBeep();
|
|
return;
|
|
}
|
|
|
|
menuView = [[_cell menu] menuRepresentation];
|
|
if ([[menuView window] isVisible] == NO)
|
|
{
|
|
// Attach the popUp
|
|
[_cell attachPopUpWithFrame: _bounds
|
|
inView: self];
|
|
}
|
|
else
|
|
{
|
|
selectedIndex = [menuView highlightedItemIndex];
|
|
if (selectedIndex >= 0)
|
|
{
|
|
[[_cell menu] performActionForItemAtIndex: selectedIndex];
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
case '\e':
|
|
[_cell dismissPopUp];
|
|
return;
|
|
case NSUpArrowFunctionKey:
|
|
{
|
|
NSMenuView *menuView;
|
|
int selectedIndex, numberOfItems;
|
|
|
|
menuView = [[_cell menu] menuRepresentation];
|
|
selectedIndex = [menuView highlightedItemIndex];
|
|
numberOfItems = [self numberOfItems];
|
|
|
|
switch (selectedIndex)
|
|
{
|
|
case -1:
|
|
selectedIndex = numberOfItems - 1;
|
|
break;
|
|
case 0:
|
|
return;
|
|
default:
|
|
selectedIndex--;
|
|
break;
|
|
}
|
|
|
|
[menuView setHighlightedItemIndex: selectedIndex];
|
|
}
|
|
return;
|
|
case NSDownArrowFunctionKey:
|
|
{
|
|
NSMenuView *menuView;
|
|
int selectedIndex, numberOfItems;
|
|
|
|
menuView = [[_cell menu] menuRepresentation];
|
|
selectedIndex = [menuView highlightedItemIndex];
|
|
numberOfItems = [self numberOfItems];
|
|
|
|
if (selectedIndex < numberOfItems-1)
|
|
[menuView setHighlightedItemIndex: selectedIndex + 1];
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
[super keyDown: theEvent];
|
|
}
|
|
|
|
- (void) setValue: (id)anObject forKey: (NSString*)aKey
|
|
{
|
|
if ([aKey isEqual: NSSelectedIndexBinding])
|
|
{
|
|
[self selectItemAtIndex: [anObject intValue]];
|
|
}
|
|
else
|
|
{
|
|
[super setValue: anObject forKey: aKey];
|
|
}
|
|
}
|
|
|
|
- (id) valueForKey: (NSString*)aKey
|
|
{
|
|
if ([aKey isEqual: NSSelectedIndexBinding])
|
|
{
|
|
return [NSNumber numberWithInt: [self indexOfSelectedItem]];
|
|
}
|
|
else
|
|
{
|
|
return [super valueForKey: aKey];
|
|
}
|
|
}
|
|
|
|
@end
|