mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-30 17:20:38 +00:00
Release 0.3.0.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@2347 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
f38b177296
commit
01b4994fb8
44 changed files with 2645 additions and 1101 deletions
836
Source/NSMenu.m
836
Source/NSMenu.m
|
@ -1,12 +1,11 @@
|
|||
/*
|
||||
NSMenu.m
|
||||
|
||||
The menu class
|
||||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Author: Scott Christley <scottc@net-community.com>
|
||||
Date: 1996
|
||||
Author: Ovidiu Predescu <ovidiu@net-community.com>
|
||||
Date: May 1997
|
||||
A completely rewritten version of the original source by Scott Christley.
|
||||
|
||||
This file is part of the GNUstep GUI Library.
|
||||
|
||||
|
@ -26,267 +25,710 @@
|
|||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <Foundation/NSLock.h>
|
||||
#include <Foundation/NSCoder.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <AppKit/NSMenu.h>
|
||||
#include <AppKit/NSMenuCell.h>
|
||||
#include <AppKit/NSMenuPrivate.h>
|
||||
#include <AppKit/NSApplication.h>
|
||||
#include <Foundation/NSProcessInfo.h>
|
||||
|
||||
#include <AppKit/NSMatrix.h>
|
||||
#include <AppKit/NSApplication.h>
|
||||
#include <AppKit/NSWindow.h>
|
||||
#include <AppKit/NSEvent.h>
|
||||
#include <AppKit/NSFont.h>
|
||||
#include <AppKit/NSMenu.h>
|
||||
|
||||
NSZone *gnustep_gui_nsmenu_zone = NULL;
|
||||
#define ASSIGN(variable, value) \
|
||||
[value retain]; \
|
||||
[variable release]; \
|
||||
variable = value;
|
||||
|
||||
@implementation NSMenu
|
||||
#ifdef MAX
|
||||
# undef MAX
|
||||
#endif
|
||||
# define MAX(a, b) \
|
||||
({typedef _ta = (a), _tb = (b); \
|
||||
_ta _a = (a); _tb _b = (b); \
|
||||
_a > _b ? _a : _b; })
|
||||
|
||||
//
|
||||
// Class methods
|
||||
//
|
||||
+ (void)initialize
|
||||
|
||||
@interface NSMenu (PrivateMethods2)
|
||||
- (void)_menuChanged;
|
||||
@end
|
||||
|
||||
|
||||
@implementation NSMenuMatrix
|
||||
|
||||
// Class variables
|
||||
static NSFont* menuFont = nil;
|
||||
|
||||
- initWithFrame:(NSRect)rect
|
||||
{
|
||||
if (self == [NSMenu class])
|
||||
{
|
||||
// Initial version
|
||||
[self setVersion:2];
|
||||
}
|
||||
}
|
||||
[super initWithFrame:rect];
|
||||
cells = [NSMutableArray new];
|
||||
|
||||
//
|
||||
// Controlling Allocation Zones
|
||||
//
|
||||
+ (NSZone *)menuZone
|
||||
{
|
||||
return gnustep_gui_nsmenu_zone;
|
||||
}
|
||||
|
||||
+ (void)setMenuZone:(NSZone *)zone
|
||||
{
|
||||
gnustep_gui_nsmenu_zone = zone;
|
||||
}
|
||||
|
||||
//
|
||||
// Instance methods
|
||||
//
|
||||
//
|
||||
// Initializing a New NSMenu
|
||||
//
|
||||
- init
|
||||
{
|
||||
return [self initWithTitle:@""];
|
||||
}
|
||||
|
||||
// Default initializer
|
||||
- (id)initWithTitle:(NSString *)aTitle
|
||||
{
|
||||
// NSApplication *theApp = [NSApplication sharedApplication];
|
||||
|
||||
// Init our superclass but skip any of its backend implementation
|
||||
[super init];
|
||||
|
||||
window_title = aTitle;
|
||||
menu_items = [NSMutableArray array];
|
||||
super_menu = nil;
|
||||
autoenables_items = NO;
|
||||
|
||||
menu_matrix = [[NSMatrix alloc] initWithFrame: NSZeroRect];
|
||||
[menu_matrix setCellClass: [NSMenuCell class]];
|
||||
[menu_matrix setIntercellSpacing: NSZeroSize];
|
||||
// [self setContentView: menu_matrix];
|
||||
|
||||
is_torn_off = NO;
|
||||
|
||||
// Register ourselves with the Application object
|
||||
// [theApp addWindowsItem:self title:window_title filename:NO];
|
||||
/* Don't initialize menuFont in +initialize since we don't know if the
|
||||
DGS process knows anything about the fonts yet. */
|
||||
if (!menuFont)
|
||||
menuFont = [[NSFont systemFontOfSize:0] retain];
|
||||
|
||||
cellSize = NSMakeSize (1, [menuFont pointSize] - [menuFont descender] + 4);
|
||||
return self;
|
||||
}
|
||||
|
||||
//
|
||||
// Setting Up the Menu Commands
|
||||
//
|
||||
- (id)addItemWithTitle:(NSString *)aString
|
||||
action:(SEL)aSelector
|
||||
keyEquivalent:(NSString *)charCode
|
||||
- (void)dealloc
|
||||
{
|
||||
NSMenuCell *m;
|
||||
NSDebugLog (@"NSMenuMatrix of menu '%@' dealloc", [menu title]);
|
||||
|
||||
m = [[NSMenuCell alloc] initTextCell:aString];
|
||||
[m setAction:aSelector];
|
||||
[menu_items addObject:m];
|
||||
|
||||
return m;
|
||||
[cells release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)insertItemWithTitle:(NSString *)aString
|
||||
action:(SEL)aSelector
|
||||
keyEquivalent:(NSString *)charCode
|
||||
atIndex:(unsigned int)index
|
||||
- (id)copyWithZone:(NSZone*)zone
|
||||
{
|
||||
NSMenuCell *m;
|
||||
NSMenuMatrix* copy = NSAllocateObject (isa, 0, zone);
|
||||
int i, count;
|
||||
|
||||
m = [[NSMenuCell alloc] initTextCell:aString];
|
||||
[m setAction:aSelector];
|
||||
[menu_items insertObject:m atIndex:index];
|
||||
NSDebugLog (@"copy menu matrix of menu with title '%@'", [menu title]);
|
||||
copy->cells = [[NSMutableArray alloc] initWithCapacity:[cells count]];
|
||||
for (i = 0, count = [cells count]; i < count; i++) {
|
||||
id aCell = [cells objectAtIndex:i];
|
||||
id cellCopy = [[aCell copyWithZone:zone] autorelease];
|
||||
|
||||
return m;
|
||||
[copy->cells addObject:cellCopy];
|
||||
}
|
||||
|
||||
copy->cellSize = cellSize;
|
||||
copy->menu = menu;
|
||||
if (selectedCell) {
|
||||
int index = [cells indexOfObject:selectedCell];
|
||||
|
||||
copy->selectedCell = [[cells objectAtIndex:index] retain];
|
||||
}
|
||||
copy->selectedCellRect = selectedCellRect;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (NSArray *)itemArray
|
||||
- (void)_resizeMenuForCellSize
|
||||
{
|
||||
return menu_items;
|
||||
/* Resize the frame to hold all the menu cells */
|
||||
[super setFrameSize:NSMakeSize (cellSize.width,
|
||||
(cellSize.height + INTERCELL_SPACE) * [cells count] - INTERCELL_SPACE)];
|
||||
}
|
||||
|
||||
- (NSMatrix *)itemMatrix
|
||||
- (id <NSMenuItem>)insertItemWithTitle:(NSString*)aString
|
||||
action:(SEL)aSelector
|
||||
keyEquivalent:(NSString*)charCode
|
||||
atIndex:(unsigned int)index
|
||||
{
|
||||
return menu_matrix;
|
||||
id menuCell = [[[NSMenu cellClass] new] autorelease];
|
||||
float titleWidth;
|
||||
|
||||
[menuCell setTitle:aString];
|
||||
[menuCell setAction:aSelector];
|
||||
[menuCell setKeyEquivalent:charCode];
|
||||
[menuCell setFont:menuFont];
|
||||
|
||||
titleWidth = [menuFont widthOfString:aString];
|
||||
cellSize = NSMakeSize (MAX(titleWidth + ADDITIONAL_WIDTH, cellSize.width),
|
||||
cellSize.height);
|
||||
[cells insertObject:menuCell atIndex:index];
|
||||
|
||||
[self _resizeMenuForCellSize];
|
||||
|
||||
return menuCell;
|
||||
}
|
||||
|
||||
- (void)setItemMatrix:(NSMatrix *)aMatrix
|
||||
- (void)removeItem:(id <NSMenuItem>)anItem
|
||||
{
|
||||
menu_matrix = aMatrix;
|
||||
int row = [cells indexOfObject:anItem];
|
||||
float titleWidth;
|
||||
int i, count;
|
||||
|
||||
if (row == -1)
|
||||
return;
|
||||
|
||||
[cells removeObjectAtIndex:row];
|
||||
|
||||
/* Compute the new width of the menu cells matrix */
|
||||
cellSize.width = 0;
|
||||
count = [cells count];
|
||||
for (i = 0; i < count; i++) {
|
||||
titleWidth = [menuFont widthOfString:[cells objectAtIndex:i]];
|
||||
cellSize.width = MAX(titleWidth + ADDITIONAL_WIDTH, cellSize.width);
|
||||
}
|
||||
|
||||
[self _resizeMenuForCellSize];
|
||||
}
|
||||
|
||||
//
|
||||
// Finding Menu Items
|
||||
//
|
||||
- (id)cellWithTag:(int)aTag
|
||||
- (NSArray*)itemArray { return cells; }
|
||||
|
||||
- (id <NSMenuItem>)itemWithTitle:(NSString*)aString
|
||||
{
|
||||
int i, j;
|
||||
NSMenuCell *m, *found;
|
||||
int i, count = [cells count];
|
||||
id menuCell;
|
||||
|
||||
// Recursively find the menu cell with the tag
|
||||
found = nil;
|
||||
j = [menu_items count];
|
||||
for (i = 0;i < j; ++i)
|
||||
{
|
||||
m = [menu_items objectAtIndex:i];
|
||||
if ([m tag] == aTag) return m;
|
||||
if ([m hasSubmenu])
|
||||
found = [[m submenu] cellWithTag:aTag];
|
||||
if (found) return found;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
//
|
||||
// Building Submenus
|
||||
//
|
||||
- (NSMenuCell *)setSubmenu:(NSMenu *)aMenu
|
||||
forItem:(NSMenuCell *)aCell
|
||||
{
|
||||
int i, j;
|
||||
NSMenuCell *m;
|
||||
|
||||
j = [menu_items count];
|
||||
for (i = 0;i < j; ++i)
|
||||
{
|
||||
m = [menu_items objectAtIndex:i];
|
||||
if (m == aCell)
|
||||
{
|
||||
// Set the menucell's submenu
|
||||
[m setSubmenu:aMenu];
|
||||
|
||||
// Tell the submenu we are its supermenu
|
||||
[aMenu setSupermenu: self];
|
||||
|
||||
// Return the menucell
|
||||
return m;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
menuCell = [cells objectAtIndex:i];
|
||||
if ([[menuCell title] isEqual:aString])
|
||||
return menuCell;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)submenuAction:(id)sender
|
||||
{}
|
||||
|
||||
//
|
||||
// Managing NSMenu Windows
|
||||
//
|
||||
- (NSMenu *)attachedMenu
|
||||
- (id <NSMenuItem>)itemWithTag:(int)aTag
|
||||
{
|
||||
int i, count = [cells count];
|
||||
id menuCell;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
menuCell = [cells objectAtIndex:i];
|
||||
if ([menuCell tag] == aTag)
|
||||
return menuCell;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSRect)cellFrameAtRow:(int)index
|
||||
{
|
||||
NSRect rect;
|
||||
|
||||
rect.origin.x = 0;
|
||||
rect.origin.y = ([cells count] - index - 1)
|
||||
* (cellSize.height + INTERCELL_SPACE);
|
||||
rect.size = cellSize;
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
{
|
||||
int i, count = [cells count];
|
||||
NSRect intRect = {{0, 0}, {0, 0}};
|
||||
|
||||
intRect.size = cellSize;
|
||||
for (i = count - 1; i >= 0; i--) {
|
||||
id aCell = [cells objectAtIndex:i];
|
||||
|
||||
[aCell drawWithFrame:intRect inView:self];
|
||||
intRect.origin.y += cellSize.height + INTERCELL_SPACE;
|
||||
}
|
||||
[[self window] flushWindow];
|
||||
}
|
||||
|
||||
- (NSSize)cellSize { return cellSize; }
|
||||
- (void)setMenu:(NSMenu*)anObject { menu = anObject; }
|
||||
- (void)setSelectedCell:(id)aCell { ASSIGN(selectedCell, aCell); }
|
||||
- (id)selectedCell { return selectedCell; }
|
||||
- (NSRect)selectedCellRect { return selectedCellRect; }
|
||||
|
||||
@end /* NSMenuMatrix */
|
||||
|
||||
|
||||
@implementation NSMenu
|
||||
|
||||
// Class variables
|
||||
static NSZone *menuZone = NULL;
|
||||
static Class menuCellClass = nil;
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
menuCellClass = [NSMenuItem class];
|
||||
}
|
||||
|
||||
+ (void)setMenuZone:(NSZone*)zone
|
||||
{
|
||||
menuZone = zone;
|
||||
}
|
||||
|
||||
+ (NSZone*)menuZone
|
||||
{
|
||||
return menuZone;
|
||||
}
|
||||
|
||||
+ (void)setCellClass:(Class)aClass
|
||||
{
|
||||
menuCellClass = aClass;
|
||||
}
|
||||
|
||||
+ (Class)cellClass
|
||||
{
|
||||
return menuCellClass;
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
return [self initWithTitle:
|
||||
[[[NSProcessInfo processInfo] processName] lastPathComponent]];
|
||||
}
|
||||
|
||||
- (id)initWithTitle:(NSString*)aTitle
|
||||
{
|
||||
// SUBCLASS to initialize other "instance variables"
|
||||
NSRect rect = {{0, 0}, {80, 20}};
|
||||
|
||||
ASSIGN(title, aTitle);
|
||||
menuCells = [[NSMenuMatrix alloc] initWithFrame:rect];
|
||||
[menuCells setMenu:self];
|
||||
menuChangedMessagesEnabled = YES;
|
||||
autoenablesItems = YES;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
NSDebugLog (@"NSMenu '%@' dealloc", title);
|
||||
|
||||
[title release];
|
||||
[menuCells release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone*)zone
|
||||
{
|
||||
NSMenu* copy = NSAllocateObject (isa, 0, zone);
|
||||
int i, count;
|
||||
NSArray* cells;
|
||||
|
||||
NSDebugLog (@"copy menu with title '%@'", [self title]);
|
||||
|
||||
copy->title = [title copyWithZone:zone];
|
||||
|
||||
copy->menuCells = [menuCells copyWithZone:zone];
|
||||
[copy->menuCells setMenu:copy];
|
||||
|
||||
/* Change the supermenu object of the new cells to the new menu */
|
||||
cells = [copy->menuCells itemArray];
|
||||
for (i = 0, count = [cells count]; i < count; i++) {
|
||||
id cell = [cells objectAtIndex:i];
|
||||
|
||||
if ([cell hasSubmenu]) {
|
||||
NSMenu* submenu = [cell target];
|
||||
|
||||
submenu->supermenu = copy;
|
||||
}
|
||||
}
|
||||
|
||||
[copy->menuCells setFrame:[menuCells frame]];
|
||||
|
||||
copy->supermenu = supermenu;
|
||||
copy->attachedMenu = nil;
|
||||
copy->autoenablesItems = autoenablesItems;
|
||||
copy->menuChangedMessagesEnabled = menuChangedMessagesEnabled;
|
||||
copy->menuHasChanged = menuHasChanged;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (id <NSMenuItem>)addItemWithTitle:(NSString*)aString
|
||||
action:(SEL)aSelector
|
||||
keyEquivalent:(NSString*)charCode
|
||||
{
|
||||
return [self insertItemWithTitle:aString
|
||||
action:aSelector
|
||||
keyEquivalent:charCode
|
||||
atIndex:[[menuCells itemArray] count]];
|
||||
}
|
||||
|
||||
- (id <NSMenuItem>)insertItemWithTitle:(NSString*)aString
|
||||
action:(SEL)aSelector
|
||||
keyEquivalent:(NSString*)charCode
|
||||
atIndex:(unsigned int)index
|
||||
{
|
||||
id menuCell = [menuCells insertItemWithTitle:aString
|
||||
action:aSelector
|
||||
keyEquivalent:charCode
|
||||
atIndex:index];
|
||||
[self _menuChanged];
|
||||
|
||||
return menuCell;
|
||||
}
|
||||
|
||||
- (void)removeItem:(id <NSMenuItem>)anItem
|
||||
{
|
||||
[menuCells removeItem:anItem];
|
||||
[self _menuChanged];
|
||||
}
|
||||
|
||||
- (NSArray*)itemArray
|
||||
{
|
||||
return [menuCells itemArray];
|
||||
}
|
||||
|
||||
- (id <NSMenuItem>)itemWithTag:(int)aTag
|
||||
{
|
||||
return [menuCells itemWithTag:aTag];
|
||||
}
|
||||
|
||||
- (id <NSMenuItem>)itemWithTitle:(NSString*)aString
|
||||
{
|
||||
return [menuCells itemWithTitle:aString];
|
||||
}
|
||||
|
||||
- (void)setSubmenu:(NSMenu*)aMenu forItem:(id <NSMenuItem>)anItem
|
||||
{
|
||||
NSString* itemTitle = [anItem title];
|
||||
|
||||
[anItem setTarget:aMenu];
|
||||
[anItem setAction:@selector(submenuAction:)];
|
||||
if (aMenu)
|
||||
aMenu->supermenu = self;
|
||||
|
||||
[itemTitle retain];
|
||||
// [aMenu->title release];
|
||||
aMenu->title = itemTitle;
|
||||
|
||||
[self _menuChanged];
|
||||
}
|
||||
|
||||
- (void)submenuAction:(id)sender
|
||||
{
|
||||
// SUBCLASS
|
||||
}
|
||||
|
||||
- (NSMenu*)attachedMenu
|
||||
{
|
||||
return attachedMenu;
|
||||
}
|
||||
|
||||
- (BOOL)isAttached
|
||||
{
|
||||
return !is_torn_off;
|
||||
return supermenu && [supermenu attachedMenu] == self;
|
||||
}
|
||||
|
||||
- (BOOL)isTornOff
|
||||
{
|
||||
return is_torn_off;
|
||||
// SUBCLASS
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSPoint)locationForSubmenu:(NSMenu *)aSubmenu
|
||||
- (NSPoint)locationForSubmenu:(NSMenu*)aSubmenu
|
||||
{
|
||||
// SUBCLASS
|
||||
return NSZeroPoint;
|
||||
}
|
||||
|
||||
- (void)sizeToFit
|
||||
{}
|
||||
|
||||
- (NSMenu *)supermenu
|
||||
- (NSMenu*)supermenu
|
||||
{
|
||||
return super_menu;
|
||||
}
|
||||
|
||||
//
|
||||
// Displaying the Menu
|
||||
//
|
||||
- (BOOL)autoenablesItems
|
||||
{
|
||||
return autoenables_items;
|
||||
return supermenu;
|
||||
}
|
||||
|
||||
- (void)setAutoenablesItems:(BOOL)flag
|
||||
{
|
||||
autoenables_items = flag;
|
||||
autoenablesItems = flag;
|
||||
}
|
||||
|
||||
//
|
||||
// NSCoding protocol
|
||||
//
|
||||
- (void)encodeWithCoder:aCoder
|
||||
- (BOOL)autoenablesItems
|
||||
{
|
||||
[aCoder encodeObject: menu_items];
|
||||
|
||||
// Version 2
|
||||
[aCoder encodeObject: window_title];
|
||||
#if 0
|
||||
[aCoder encodeObjectReference: super_menu withName: @"SuperMenu"];
|
||||
#else
|
||||
[aCoder encodeConditionalObject:super_menu];
|
||||
#endif
|
||||
[aCoder encodeValueOfObjCType:@encode(BOOL) at: &autoenables_items];
|
||||
[aCoder encodeObject: menu_matrix];
|
||||
[aCoder encodeValueOfObjCType:@encode(BOOL) at: &is_torn_off];
|
||||
return autoenablesItems;
|
||||
}
|
||||
|
||||
- initWithCoder:aDecoder
|
||||
- (void)update
|
||||
{
|
||||
menu_items = [aDecoder decodeObject];
|
||||
// SUBCLASS to redisplay the menu
|
||||
|
||||
// Version 2
|
||||
window_title = [aDecoder decodeObject];
|
||||
#if 0
|
||||
[aDecoder decodeObjectAt: &super_menu withName: NULL];
|
||||
#else
|
||||
super_menu = [aDecoder decodeObject];
|
||||
#endif
|
||||
[aDecoder decodeValueOfObjCType:@encode(BOOL) at: &autoenables_items];
|
||||
menu_matrix = [aDecoder decodeObject];
|
||||
[aDecoder decodeValueOfObjCType:@encode(BOOL) at: &is_torn_off];
|
||||
id cells;
|
||||
int i, count;
|
||||
|
||||
if (![[NSApp mainMenu] autoenablesItems])
|
||||
return;
|
||||
|
||||
cells = [menuCells itemArray];
|
||||
count = [cells count];
|
||||
|
||||
/* Temporary disable automatic displaying of menu */
|
||||
[self setMenuChangedMessagesEnabled:NO];
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
id<NSMenuItem> cell = [cells objectAtIndex:i];
|
||||
SEL action = [cell action];
|
||||
id target;
|
||||
NSWindow* keyWindow;
|
||||
NSWindow* mainWindow;
|
||||
id responder;
|
||||
id delegate;
|
||||
BOOL found = NO;
|
||||
|
||||
/* Update the submenu items if any */
|
||||
if ([cell hasSubmenu]) {
|
||||
[[cell target] update];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!action) {
|
||||
[cell setEnabled:NO];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Search the target */
|
||||
if ((target = [cell target])) {
|
||||
if ([target respondsToSelector:action]) {
|
||||
if ([target respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[target validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search the key window's responder chain */
|
||||
keyWindow = [NSApp keyWindow];
|
||||
responder = [keyWindow firstResponder];
|
||||
while (responder && !found) {
|
||||
if ([responder respondsToSelector:action]) {
|
||||
if ([responder respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[responder validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
found = YES;
|
||||
}
|
||||
responder = [responder nextResponder];
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
/* Search the key window */
|
||||
if ([keyWindow respondsToSelector:action]) {
|
||||
if ([keyWindow respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[keyWindow validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Search the key window's delegate */
|
||||
delegate = [keyWindow delegate];
|
||||
if ([delegate respondsToSelector:action]) {
|
||||
if ([delegate respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[delegate validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
continue;
|
||||
}
|
||||
|
||||
mainWindow = [NSApp mainWindow];
|
||||
if (mainWindow != keyWindow) {
|
||||
/* Search the main window's responder chain */
|
||||
responder = [mainWindow firstResponder];
|
||||
while (responder && !found) {
|
||||
if ([responder respondsToSelector:action]) {
|
||||
if ([responder respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[responder validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
found = YES;
|
||||
}
|
||||
|
||||
responder = [responder nextResponder];
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
/* Search the main window */
|
||||
if ([mainWindow respondsToSelector:action]) {
|
||||
if ([mainWindow respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[mainWindow validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Search the main window's delegate */
|
||||
delegate = [mainWindow delegate];
|
||||
if ([delegate respondsToSelector:action]) {
|
||||
if ([delegate respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[delegate validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search the NSApplication object */
|
||||
if ([NSApp respondsToSelector:action]) {
|
||||
if ([NSApp respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[NSApp validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Search the NSApplication object's delegate */
|
||||
delegate = [NSApp delegate];
|
||||
if ([delegate respondsToSelector:action]) {
|
||||
if ([delegate respondsToSelector:@selector(validateMenuItem:)])
|
||||
[cell setEnabled:[delegate validateMenuItem:cell]];
|
||||
else
|
||||
[cell setEnabled:YES];
|
||||
continue;
|
||||
}
|
||||
|
||||
[cell setEnabled:NO];
|
||||
}
|
||||
|
||||
/* Reenable displaying of menus */
|
||||
[self setMenuChangedMessagesEnabled:YES];
|
||||
|
||||
[self sizeToFit];
|
||||
}
|
||||
|
||||
- (void)performActionForItem:(id <NSMenuItem>)cell
|
||||
{
|
||||
SEL action;
|
||||
id target;
|
||||
NSWindow* keyWindow;
|
||||
NSWindow* mainWindow;
|
||||
id responder;
|
||||
id delegate;
|
||||
|
||||
if (![cell isEnabled])
|
||||
return;
|
||||
|
||||
action = [cell action];
|
||||
|
||||
/* Search the target */
|
||||
if ((target = [cell target]) && [target respondsToSelector:action]) {
|
||||
[target perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
|
||||
/* Search the key window's responder chain */
|
||||
keyWindow = [NSApp keyWindow];
|
||||
responder = [keyWindow firstResponder];
|
||||
while (responder) {
|
||||
if ([responder respondsToSelector:action]) {
|
||||
[responder perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
responder = [responder nextResponder];
|
||||
}
|
||||
|
||||
/* Search the key window */
|
||||
if ([keyWindow respondsToSelector:action]) {
|
||||
[keyWindow perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
|
||||
/* Search the key window's delegate */
|
||||
delegate = [keyWindow delegate];
|
||||
if ([delegate respondsToSelector:action]) {
|
||||
[delegate perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
|
||||
mainWindow = [NSApp mainWindow];
|
||||
if (mainWindow != keyWindow) {
|
||||
/* Search the main window's responder chain */
|
||||
responder = [mainWindow firstResponder];
|
||||
while (responder) {
|
||||
if ([responder respondsToSelector:action]) {
|
||||
[responder perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
responder = [responder nextResponder];
|
||||
}
|
||||
|
||||
/* Search the main window */
|
||||
if ([mainWindow respondsToSelector:action]) {
|
||||
[mainWindow perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
|
||||
/* Search the main window's delegate */
|
||||
delegate = [mainWindow delegate];
|
||||
if ([delegate respondsToSelector:action]) {
|
||||
[delegate perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Search the NSApplication object */
|
||||
if ([NSApp respondsToSelector:action]) {
|
||||
[NSApp perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
|
||||
/* Search the NSApplication object's delegate */
|
||||
delegate = [NSApp delegate];
|
||||
if ([delegate respondsToSelector:action]) {
|
||||
[delegate perform:action withObject:cell];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent
|
||||
{
|
||||
id cells = [menuCells itemArray];
|
||||
int i, count = [cells count];
|
||||
NSEventType type = [theEvent type];
|
||||
|
||||
if (type != NSKeyDown || type != NSKeyUp)
|
||||
return NO;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
id<NSMenuItem> cell = [cells objectAtIndex:i];
|
||||
|
||||
if ([cell hasSubmenu]) {
|
||||
if ([[cell target] performKeyEquivalent:theEvent])
|
||||
/* The event has been handled by a cell in submenu */
|
||||
return YES;
|
||||
}
|
||||
else {
|
||||
if ([[cell keyEquivalent] isEqual:[theEvent charactersIgnoringModifiers]]
|
||||
&& [cell keyEquivalentModifierMask] == [theEvent modifierFlags]) {
|
||||
[menuCells lockFocus];
|
||||
[(id)cell performClick:self];
|
||||
[menuCells unlockFocus];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setMenuChangedMessagesEnabled:(BOOL)flag
|
||||
{
|
||||
menuChangedMessagesEnabled = flag;
|
||||
}
|
||||
|
||||
- (BOOL)menuChangedMessagesEnabled
|
||||
{
|
||||
return menuChangedMessagesEnabled;
|
||||
}
|
||||
|
||||
- (void)sizeToFit
|
||||
{
|
||||
// SUBCLASS
|
||||
menuHasChanged = NO;
|
||||
}
|
||||
|
||||
- (NSString*)title
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
- (NSMenuMatrix*)menuCells
|
||||
{
|
||||
return menuCells;
|
||||
}
|
||||
|
||||
- initWithCoder:(NSCoder*)aDecoder
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSMenu (GNUstepPrivate)
|
||||
|
||||
- (void)setSupermenu:(NSMenu *)obj
|
||||
- (void)encodeWithCoder:(NSCoder*)aCoder
|
||||
{
|
||||
super_menu = obj;
|
||||
}
|
||||
|
||||
@end /* NSMenu */
|
||||
|
||||
|
||||
@implementation NSMenu (PrivateMethods2)
|
||||
- (void)_menuChanged
|
||||
{
|
||||
menuHasChanged = YES;
|
||||
if (menuChangedMessagesEnabled)
|
||||
[self sizeToFit];
|
||||
}
|
||||
@end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue