A miriad of changes, look at ChangeLogs.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@4497 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Michael Silva 1999-06-30 03:10:38 +00:00
parent 1e4b120ec7
commit 8c83ccf86e
19 changed files with 1658 additions and 561 deletions

View file

@ -1,3 +1,15 @@
1999-06-29 Michael Hanni <mhanni@sprintmail.com>
* Source/NSMenu.m: complete rewrite. Some work still required to
finish implementing obscure MacOSX methods, but otherwise functional.
* Source/NSMenuView.m: new file. Implementation of MacOSX menu
view class. Most classes implemented to provide basic
functionality. Some work required in event code to "forward"curse
to close/deselect menus in one case. I'll fix this ASAP.
* Source/NSMenuItemCell.m: new file. Implementation complete, plus
modifications to allow its use as an <NSMenuItem>.
* Source/*.m: compilation fixes.
Sun Jun 27 7:50:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Source/GNUmakefile: Install GSWraps.h

View file

@ -35,17 +35,22 @@
@class NSEvent;
@class NSMatrix;
@class NSMenuView;
@class NSMenuMatrix;
@class NSMenuWindow;
@interface NSMenu : NSObject <NSCoding, NSCopying>
{
NSString* title;
NSMenuMatrix* menuCells;
NSMenu* supermenu;
NSMenu* attachedMenu;
BOOL autoenablesItems;
BOOL menuChangedMessagesEnabled;
BOOL menuHasChanged;
NSString *menu_title;
NSMutableArray *menu_items;
NSMenuView *menu_view;
NSMenu *menu_supermenu;
NSMenu *menu_attached_menu;
id menu_rep;
BOOL menu_ChangedMessagesEnabled;
BOOL menu_autoenable;
BOOL menu_changed;
BOOL menu_is_tornoff;
// Reserved for back-end use
void *be_menu_reserved;
@ -107,7 +112,7 @@
- (NSString*)title;
/* Getting the menu cells matrix */
- (NSMenuMatrix*)menuCells;
- (NSMenuView *)menuView;
// non OS spec methods
- (void)_rightMouseDisplay;
@ -128,35 +133,6 @@
- (void)close;
@end
/* Private class used to display the menu cells and respond to user actions */
@interface NSMenuMatrix : NSControl <NSCopying>
{
NSMutableArray* cells;
NSSize cellSize;
NSMenu* menu;
id selectedCell;
NSRect selectedCellRect;
}
- initWithFrame:(NSRect)rect;
- (id <NSMenuItem>)insertItemWithTitle:(NSString*)aString
action:(SEL)aSelector
keyEquivalent:(NSString*)charCode
atIndex:(unsigned int)index;
- (void)removeItem:(id <NSMenuItem>)anItem;
- (NSArray*)itemArray;
- (id <NSMenuItem>)itemWithTitle:(NSString*)aString;
- (id <NSMenuItem>)itemWithTag:(int)aTag;
- (NSRect)cellFrameAtRow:(int)index;
- (NSSize)cellSize;
- (void)setMenu:(NSMenu*)menu;
- (void)setSelectedCell:(id)aCell;
- (id)selectedCell;
- (NSRect)selectedCellRect;
@end
extern NSString* const NSMenuDidSendActionNotification;
extern NSString* const NSMenuWillSendActionNotification;

View file

@ -0,0 +1,102 @@
/*
NSMenuItemCell.h
Copyright (C) 1996 Free Software Foundation, Inc.
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 Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _GNUstep_H_NSMenuItemCell
#define _GNUstep_H_NSMenuItemCell
#include <AppKit/NSActionCell.h>
#include <AppKit/NSButtonCell.h>
#include <AppKit/NSMenuItem.h>
@interface NSMenuItemCell : NSButtonCell <NSMenuItem>
{
id representedObject;
BOOL mcell_highlighted;
BOOL mcell_has_submenu;
// Not used is GS.
NSMenuItem *mcell_item;
BOOL mcell_needs_sizing;
float mcell_imageWidth;
float mcell_titleWidth;
float mcell_keyEqWidth;
float mcell_stateImgWidth;
}
// NSMenuItem Protocol demands these:
- (void)setTarget:(id)anObject;
- (void)setTitle:(NSString*)aString;
- (NSString*)title;
- (NSString*)keyEquivalent;
- (NSString*)userKeyEquivalent;
- (void)setRepresentedObject:(id)anObject;
- (id)representedObject;
// NSMenuItemCell from MacOSX API.
- (void)setHighlighted:(BOOL)flag;
- (BOOL)isHighlighted;
// These NSMenuItem calls are deprecated in GS. You should not use them
// under any circumstance (i.e. they don't do anything.)
- (void)setMenuItem:(NSMenuItem *)item;
- (NSMenuItem *)menuItem;
- (void)calcSize;
- (void)setNeedsSizing:(BOOL)flag;
- (BOOL)needsSizing;
- (float)imageWidth;
- (float)titleWidth;
- (float)keyEquivalentWidth;
- (float)stateImageWidth;
- (NSRect)imageRectForBounds:(NSRect)cellFrame;
- (NSRect)keyEquivalentRectForBounds:(NSRect)cellFrame;
- (NSRect)stateImageRectForBounds:(NSRect)cellFrame;
- (NSRect)titleRectForBounds:(NSRect)cellFrame;
- (void)drawBorderAndBackgroundWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView;
- (void)drawImageWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView;
- (void)drawKeyEquivalentWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView;
- (void)drawSeparatorItemWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView;
- (void)drawStateImageWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView;
- (void)drawTitleWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView;
@end
#endif

View file

@ -0,0 +1,111 @@
/*
NSMenuView.h
Copyright (C) 1996 Free Software Foundation, Inc.
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 Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _GNUstep_H_NSMenuView
#define _GNUstep_H_NSMenuView
#include <Foundation/NSCoder.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSException.h>
#include <Foundation/NSProcessInfo.h>
#include <Foundation/NSString.h>
#include <Foundation/NSNotification.h>
#include <AppKit/NSColor.h>
#include <AppKit/NSMenu.h>
#include <AppKit/NSMenuItemCell.h>
#include <AppKit/NSScreen.h>
#include <AppKit/NSView.h>
@class NSFont;
@interface NSMenuView : NSView
{
NSMenu *menuv_menu;
BOOL menuv_horizontal;
NSFont *menuv_font;
int menuv_highlightedItemIndex;
BOOL menuv_isAttached;
BOOL menuv_isTornOff;
float menuv_hEdgePad;
float menuv_stateImageOffset;
float menuv_stateImageWidth;
float menuv_imageAndTitleOffset;
float menuv_imageAndTitleWidth;
float menuv_keyEqOffset;
float menuv_keyEqWidth;
BOOL menuv_needsSizing;
NSSize cellSize;
}
+ (float)menuBarHeight;
- (void)setMenu:(NSMenu *)menu;
- (NSMenu *)menu;
- (void)setHorizontal:(BOOL)flag;
- (BOOL)isHorizontal;
- (void)setFont:(NSFont *)font;
- (NSFont *)font;
- (void)setHighlightedItemIndex:(int)index;
- (int)highlightedItemIndex;
- (void)setMenuItemCell:(NSMenuItemCell *)cell
forItemAtIndex:(int)index;
- (NSMenuItemCell *)menuItemCellForItemAtIndex:(int)index;
- (NSMenuView *)attachedMenuView;
- (NSMenu *)attachedMenu;
- (BOOL)isAttached;
- (BOOL)isTornOff;
- (void)setHorizontalEdgePadding:(float)pad;
- (float)horizontalEdgePadding;
- (void)itemChanged:(NSNotification *)notification;
- (void)itemAdded:(NSNotification *)notification;
- (void)itemRemoved:(NSNotification *)notification;
- (void)detachSubmenu;
- (void)attachSubmenuForItemAtIndex:(int)index;
- (void)update;
- (void)setNeedsSizing:(BOOL)flag;
- (BOOL)needsSizing;
- (void)sizeToFit;
- (float)stateImageOffset;
- (float)stateImageWidth;
- (float)imageAndTitleOffset;
- (float)imageAndTitleWidth;
- (float)keyEquivalentOffset;
- (float)keyEquivalentWidth;
- (NSRect)innerRect;
- (NSRect)rectOfItemAtIndex:(int)index;
- (int)indexOfItemAtPoint:(NSPoint)point;
- (void)setNeedsDisplayForItemAtIndex:(int)index;
- (NSPoint)locationForSubmenu:(NSMenu *)aSubmenu;
- (void)resizeWindowWithMaxHeight:(float)maxHeight;
- (void)setWindowFrameForAttachingToRect:(NSRect)screenRect
onScreen:(NSScreen *)screen
preferredEdge:(NSRectEdge)edge
popUpSelectedItem:(int)selectedItemIndex;
- (void)performActionWithHighlightingForItemAtIndex:(int)index;
- (BOOL)trackWithEvent:(NSEvent *)event;
@end
#endif

View file

@ -41,13 +41,32 @@
@class NSMatrix;
@class NSPopUpButton;
@interface NSPopUpButtonMatrix : NSMenuMatrix
@interface NSPopUpButtonMatrix : NSControl <NSCopying>
{
NSMutableArray* cells;
NSSize cellSize;
NSMenu* menu;
id selectedCell;
NSRect selectedCellRect;
BOOL pull_down;
int selected_cell;
NSPopUpButton *popup_button;
}
- (id) initWithFrame: (NSRect)rect;
- initWithFrame:(NSRect)rect;
- (id <NSMenuItem>)insertItemWithTitle:(NSString*)aString
action:(SEL)aSelector
keyEquivalent:(NSString*)charCode
atIndex:(unsigned int)index;
- (void)removeItem:(id <NSMenuItem>)anItem;
- (NSArray*)itemArray;
- (id <NSMenuItem>)itemWithTitle:(NSString*)aString;
- (id <NSMenuItem>)itemWithTag:(int)aTag;
- (NSRect)cellFrameAtRow:(int)index;
- (NSSize)cellSize;
- (void)setMenu:(NSMenu*)menu;
- (void)setSelectedCell:(id)aCell;
- (id)selectedCell;
- (NSRect)selectedCellRect;
- (void)setPopUpButton:(NSPopUpButton *)popb;
- (void) setIndexOfSelectedItem:(int)itemNum;
@end

View file

@ -30,7 +30,7 @@
#include <AppKit/NSTabView.h>
typedef enum {
NSSelectedTab,
NSSelectedTab = 0,
NSBackgroundTab,
NSPressedTab
} NSTabState;

Binary file not shown.

View file

@ -773,7 +773,7 @@ void __dummy_GMAppKit_functionForLinking() {}
@end /* NSMenu (GMArchiverMethods) */
#if 0
@implementation NSPopUpButton (GMArchiverMethods)
- (void)encodeWithModelArchiver:(GMArchiver*)archiver
@ -840,7 +840,7 @@ void __dummy_GMAppKit_functionForLinking() {}
}
@end /* NSPopUpButton (GMArchiverMethods) */
#endif
@implementation NSResponder (GMArchiverMethods)

View file

@ -79,17 +79,19 @@ NSImageView.m \
NSInterfaceStyle.m \
NSMatrix.m \
NSMenu.m \
NSMenuView.m \
NSMenuItem.m \
NSMenuItemCell.m \
NSOpenPanel.m \
NSPageLayout.m \
NSPanel.m \
NSParagraphStyle.m \
NSPopUpButton.m \
NSPopUpButtonCell.m \
NSPrinter.m \
NSPrintInfo.m \
NSPrintOperation.m \
NSPrintPanel.m \
NSPopUpButton.m \
NSPopUpButtonCell.m \
NSResponder.m \
NSSavePanel.m \
NSScreen.m \

View file

@ -34,7 +34,9 @@
#include <AppKit/NSTextFieldCell.h>
#include <AppKit/NSColor.h>
#include <AppKit/NSImage.h>
#include <AppKit/NSGraphics.h>
#include <AppKit/NSEvent.h>
#include <AppKit/NSWindow.h>
//
// Class variables

View file

@ -41,9 +41,9 @@
return [self initWithFrame: NSZeroRect];
}
- (id) initWithFrame: (NSRect)frame
- (id) initWithFrame: (NSRect)aFrame
{
[super initWithFrame: frame];
[super initWithFrame: aFrame];
// allocate the image cell
[self setCell: [[NSImageCell alloc] init]];

View file

@ -1,30 +1,3 @@
/*
NSMenu.m
Copyright (C) 1996 Free Software Foundation, Inc.
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.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <gnustep/gui/config.h>
#include <Foundation/NSCoder.h>
#include <Foundation/NSArray.h>
@ -39,463 +12,306 @@
#include <AppKit/NSEvent.h>
#include <AppKit/NSFont.h>
#include <AppKit/NSMenu.h>
#include <math.h>
#include <AppKit/NSMenuView.h>
#include <AppKit/NSMenuItemCell.h>
#ifdef MAX
# undef MAX
#endif
#define MAX(a, b) \
({typeof(a) _a = (a); typeof(b) _b = (b); \
_a > _b ? _a : _b; })
@interface NSMenu (PrivateMethods2)
- (void) _menuChanged;
@end
@interface NSMenuMatrix (PrivateMethods2)
- (void) _resizeMenuForCellSize;
@end
//*****************************************************************************
//
// NSMenuMatrix
//
//*****************************************************************************
@implementation NSMenuMatrix
// Class variables
static NSFont* menuFont = nil;
- (BOOL) acceptsFirstMouse: (NSEvent *)theEvent
{
return YES;
}
- (id) initWithFrame: (NSRect)rect
{
[super initWithFrame: rect];
cells = [NSMutableArray new];
/* 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] + 6);
return self;
}
- (void) dealloc
{
NSDebugLog (@"NSMenuMatrix of menu '%@' dealloc", [menu title]);
[cells release];
[super dealloc];
}
- (id) copyWithZone: (NSZone*)zone
{
NSMenuMatrix* copy = [[isa allocWithZone: zone] initWithFrame: [self frame]];
int i, count;
NSDebugLog (@"copy menu matrix of menu with title '%@'", [menu title]);
for (i = 0, count = [cells count]; i < count; i++)
{
id aCell = [cells objectAtIndex: i];
id cellCopy = [[aCell copyWithZone: zone] autorelease];
[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;
}
- (void) _resizeMenuForCellSize
{
int i, count;
float titleWidth;
/* 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] stringValue]];
cellSize.width = MAX(titleWidth + ADDITIONAL_WIDTH, cellSize.width);
}
cellSize.width = MAX([menuFont widthOfString: [menu title]]
+ ADDITIONAL_WIDTH,
cellSize.width);
/* Resize the frame to hold all the menu cells */
[super setFrameSize: NSMakeSize (cellSize.width,
count ? (cellSize.height + INTERCELL_SPACE)*count - INTERCELL_SPACE : 0)];
}
- (id <NSMenuItem>)insertItemWithTitle: (NSString*)aString
action: (SEL)aSelector
keyEquivalent: (NSString*)charCode
atIndex: (unsigned int)index
{
id menuCell = [[[NSMenu cellClass] new] autorelease];
[menuCell setFont: menuFont];
[menuCell setTitle: aString];
[menuCell setAction: aSelector];
[menuCell setKeyEquivalent: charCode];
[cells insertObject: menuCell atIndex: index];
return menuCell;
}
- (BOOL) performKeyEquivalent: (NSEvent*)theEvent
{
return [menu performKeyEquivalent: theEvent];
}
- (void) removeItem: (id <NSMenuItem>)anItem
{
int row = [cells indexOfObject: anItem];
if (row == -1)
return;
[cells removeObjectAtIndex: row];
}
- (NSArray*) itemArray
{
return cells;
}
- (id <NSMenuItem>) itemWithTitle: (NSString*)aString
{
unsigned i, count = [cells count];
id menuCell;
for (i = 0; i < count; i++)
{
menuCell = [cells objectAtIndex: i];
if ([[menuCell title] isEqual: aString])
return menuCell;
}
return nil;
}
- (id <NSMenuItem>) itemWithTag: (int)aTag
{
unsigned 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
{
unsigned count = [cells count];
NSRect rect;
NSAssert(index >= 0 && index < count+1, @"invalid row coordinate");
rect.origin.x = 0;
rect.origin.y = (count - index - 1)
* (cellSize.height + INTERCELL_SPACE);
rect.size = cellSize;
return rect;
}
- (void)drawRect: (NSRect)rect
{
unsigned i, count = [cells count];
int max, howMany;
NSRect intRect = {{0, 0}, {0, 0}};
// If there are no cells then just return
if (count == 0) return;
max = ceil((float)count - rect.origin.y / (cellSize.height + INTERCELL_SPACE));
howMany = ceil(rect.size.height / (cellSize.height + INTERCELL_SPACE));
intRect.origin.y = (count - max) * (cellSize.height + INTERCELL_SPACE);
intRect.size = cellSize;
for (i = max - 1; howMany > 0; i--, howMany--)
{
id aCell = [cells objectAtIndex: i];
[aCell drawWithFrame: intRect inView: self];
intRect.origin.y += cellSize.height + INTERCELL_SPACE;
}
}
- (NSSize) cellSize
{
return cellSize;
}
- (void) setMenu: (NSMenu*)anObject
{
menu = anObject;
}
- (void) setSelectedCell: (id)aCell
{
selectedCell = aCell;
}
- (id) selectedCell
{
return selectedCell;
}
- (NSRect) selectedCellRect
{
return selectedCellRect;
}
@end /* NSMenuMatrix */
//*****************************************************************************
//
// NSMenu
//
//*****************************************************************************
static NSZone *menuZone = NULL;
@implementation NSMenu
// Class variables
static NSZone *menuZone = NULL;
static Class menuCellClass = nil;
// Class Methods
+ (void) initialize
{
menuCellClass = [NSMenuItem class];
if (self == [NSMenu class])
{
[self setVersion: 1];
}
}
+ (void) setMenuZone: (NSZone*)zone
+ (void)setMenuZone:(NSZone *)zone
{
menuZone = zone;
}
+ (NSZone*) menuZone
// Methods.
- (id)init
{
return menuZone;
[self initWithTitle:@"Menu"];
}
+ (void) setCellClass: (Class)aClass
- (id)initWithTitle:(NSString *)aTitle
{
menuCellClass = aClass;
}
[super init];
+ (Class) cellClass
{
return menuCellClass;
}
// Keep the title.
ASSIGN(menu_title, aTitle);
- (id) init
{
return [self initWithTitle:
[[[NSProcessInfo processInfo] processName] lastPathComponent]];
}
// Create an array to store out cells.
menu_items = [NSMutableArray new];
- (id) initWithTitle: (NSString*)aTitle
{
// SUBCLASS to initialize other "instance variables"
NSRect rect = {{0, 0}, {80, 20}};
// Create a NSMenuView to draw our cells.
menu_view = [[NSMenuView alloc] initWithFrame:NSMakeRect(0,0,50,50)];
// Set ourself as the menu for this view.
[menu_view setMenu:self];
// We have no supermenu.
menu_supermenu = nil;
menu_is_tornoff = NO;
menu_changed = YES;
ASSIGN(title, aTitle);
menuCells = [[NSMenuMatrix alloc] initWithFrame: rect];
[menuCells setMenu: self];
menuChangedMessagesEnabled = YES;
autoenablesItems = YES;
return self;
}
- (void) dealloc
- (void)insertItem:(id <NSMenuItem>)newItem
atIndex:(int)index
{
NSDebugLog (@"NSMenu '%@' dealloc", title);
[title release];
[menuCells release];
[super dealloc];
if ([(NSMenuItemCell *)newItem isKindOfClass:[NSMenuItemCell class]])
[menu_items insertObject:newItem atIndex:index];
else
NSLog(@"You must use an NSMenuItemCell, or a derivative thereof.\n");
}
- (id) copyWithZone: (NSZone*)zone
- (id <NSMenuItem>)insertItemWithTitle:(NSString *)aString
action:(SEL)aSelector
keyEquivalent:(NSString *)charCode
atIndex:(unsigned int)index
{
NSMenu *copy = NSAllocateObject (isa, 0, zone);
unsigned i, count;
NSArray *cells;
id anItem = [NSMenuItemCell new];
[anItem setTitle:aString];
[anItem setAction:aSelector];
[anItem setKeyEquivalent:charCode];
NSDebugLog (@"copy menu with title '%@'", [self title]);
[menu_items insertObject:anItem atIndex:index];
copy->title = [title copyWithZone: zone];
menu_changed = YES;
copy->menuCells = [menuCells copyWithZone: zone];
[copy->menuCells setMenu: copy];
return anItem;
}
/* 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];
- (void)addItem:(id <NSMenuItem>)newItem
{
// The spec says we call [self insertItem]; but why waste the overhead?
if ([(NSMenuItemCell *)newItem isKindOfClass:[NSMenuItemCell class]])
[menu_items insertObject:newItem atIndex:[menu_items count]];
else
NSLog(@"You must use an NSMenuItemCell, or a derivative thereof.\n");
if ([cell hasSubmenu]) {
NSMenu* submenu = [cell target];
menu_changed = YES;
}
submenu->supermenu = copy;
}
- (id <NSMenuItem>)addItemWithTitle:(NSString *)aString
action:(SEL)aSelector
keyEquivalent:(NSString *)keyEquiv
{
return [self insertItemWithTitle:aString
action:aSelector
keyEquivalent:keyEquiv
atIndex:[menu_items count]];
}
- (void)removeItem:(id <NSMenuItem>)anItem
{
if ([(NSMenuItemCell *)anItem isKindOfClass:[NSMenuItemCell class]])
{
int _index = [menu_items indexOfObject:anItem];
if (_index == -1)
return;
[menu_items removeObjectAtIndex:_index];
} else {
NSLog(@"You must use an NSMenuItemCell, or a derivative thereof.\n");
}
[copy->menuCells setFrame: [menuCells frame]];
copy->supermenu = supermenu;
copy->attachedMenu = nil;
copy->autoenablesItems = autoenablesItems;
copy->menuChangedMessagesEnabled = menuChangedMessagesEnabled;
copy->menuHasChanged = menuHasChanged;
return copy;
menu_changed = YES;
}
- (id <NSMenuItem>) addItemWithTitle: (NSString*)aString
action: (SEL)aSelector
keyEquivalent: (NSString*)charCode
- (void)removeItemAtIndex:(int)index
{
return [self insertItemWithTitle: aString
action: aSelector
keyEquivalent: charCode
atIndex: [[menuCells itemArray] count]];
[menu_items removeObjectAtIndex:index];
menu_changed = YES;
}
- (id <NSMenuItem>) insertItemWithTitle: (NSString*)aString
action: (SEL)aSelector
keyEquivalent: (NSString*)charCode
atIndex: (unsigned int)index
- (void)itemChanged:(id <NSMenuItem>)anObject
{
id menuCell = [menuCells insertItemWithTitle: aString
action: aSelector
keyEquivalent: charCode
atIndex: index];
menuHasChanged = YES;
return menuCell;
}
- (void) removeItem: (id <NSMenuItem>)anItem
{
[menuCells removeItem: anItem];
menuHasChanged = YES;
}
- (NSArray*) itemArray
{
return [menuCells itemArray];
// another nebulous method in NSMenu.
}
- (id <NSMenuItem>) itemWithTag: (int)aTag
{
return [menuCells itemWithTag: aTag];
unsigned i, count = [menu_items count];
id menuCell;
for (i = 0; i < count; i++)
{
menuCell = [menu_items objectAtIndex:i];
if ([menuCell tag] == aTag)
return menuCell;
}
return nil;
}
- (id <NSMenuItem>) itemWithTitle: (NSString*)aString
{
return [menuCells itemWithTitle: aString];
unsigned i, count = [menu_items count];
id menuCell;
for (i = 0; i < count; i++)
{
menuCell = [menu_items objectAtIndex: i];
if ([[menuCell title] isEqual: aString])
return menuCell;
}
return nil;
}
- (void) setSubmenu: (NSMenu*)aMenu forItem: (id <NSMenuItem>)anItem
- (id <NSMenuItem>)itemAtIndex:(int)index
{
NSString *itemTitle = [anItem title];
// FIXME should raise an exception if out of range.
return [menu_items objectAtIndex:index];
}
[anItem setTarget: aMenu];
- (int)numberOfItems
{
return [menu_items count];
}
- (NSArray *)itemArray
{
return (NSArray *)menu_items;
}
- (int)indexOfItem:(id <NSMenuItem>)anObject
{
if (![(NSMenuItemCell *)anObject isKindOfClass:[NSMenuItemCell class]])
{
NSLog(@"You must use an NSMenuItemCell, or a derivative thereof.\n");
return -1;
}
return [menu_items indexOfObject:anObject];
}
- (int)indexOfItemWithTitle:(NSString *)aTitle
{
id anItem;
if ((anItem = [self itemWithTitle:aTitle]))
return [menu_items indexOfObject:anItem];
else
return -1;
}
- (int)indexOfItemWithTag:(int)aTag
{
id anItem;
if ((anItem = [self itemWithTag:aTag]))
return [menu_items indexOfObject:anItem];
else
return -1;
}
- (int)indexOfItemWithTarget:(id)anObject
andAction:(SEL)actionSelector
{
return -1;
}
- (int)indexOfItemWithRepresentedObject:(id)anObject
{
return -1;
}
- (int)indexOfItemWithSubmenu:(NSMenu *)anObject
{
return -1;
}
// Dealing with submenus.
- (void)setSubmenu:(NSMenu *)aMenu
forItem:(id <NSMenuItem>) anItem
{
[anItem setTarget:aMenu];
[anItem setAction: @selector(submenuAction:)];
if (aMenu)
aMenu->supermenu = self;
aMenu->menu_supermenu = self;
ASSIGN(aMenu->title, itemTitle);
[self _menuChanged];
ASSIGN(aMenu->menu_title, [anItem title]);
// notification that the menu has changed.
}
- (void) submenuAction: (id)sender
- (void)submenuAction:(id)sender
{
}
- (NSMenu*) attachedMenu
- (NSMenu *)attachedMenu
{
return attachedMenu;
return menu_attached_menu;
}
- (BOOL) isAttached
{
return supermenu && [supermenu attachedMenu] == self;
// eh?
return menu_supermenu && [menu_supermenu attachedMenu] == self;
}
- (BOOL) isTornOff
- (BOOL)isTornOff
{
// SUBCLASS
return NO;
return menu_is_tornoff;
}
- (NSPoint) locationForSubmenu: (NSMenu*)aSubmenu
- (NSPoint)locationForSubmenu:(NSMenu *)aSubmenu
{
// SUBCLASS
return NSZeroPoint;
}
- (NSMenu*) supermenu
- (NSMenu *)supermenu
{
return supermenu;
return menu_supermenu;
}
- (void) setAutoenablesItems: (BOOL)flag
- (void)setSupermenu:(NSMenu *)supermenu
{
autoenablesItems = flag;
ASSIGN(menu_supermenu, supermenu);
}
- (BOOL) autoenablesItems
- (void)setAutoenablesItems:(BOOL)flag
{
return autoenablesItems;
menu_autoenable = flag;
}
- (void) update
- (BOOL)autoenablesItems
{
// SUBCLASS to redisplay the menu if necessary
return menu_autoenable;
}
- (void)update
{
// FIXME: needs to be checked.
id cells;
int i, count;
id theApp = [NSApplication sharedApplication];
if (menu_changed)
[self sizeToFit];
if (![self autoenablesItems])
return;
cells = [menuCells itemArray];
count = [cells count];
count = [menu_items count];
/* Temporary disable automatic displaying of menu */
[self setMenuChangedMessagesEnabled: NO];
for (i = 0; i < count; i++)
{
id<NSMenuItem> cell = [cells objectAtIndex: i];
id<NSMenuItem> cell = [menu_items objectAtIndex: i];
SEL action = [cell action];
id target;
NSWindow* keyWindow;
@ -505,55 +321,92 @@ static Class menuCellClass = nil;
id validator = nil;
BOOL wasEnabled = [cell isEnabled];
BOOL shouldBeEnabled;
/* Update the submenu items if any */
if ([cell hasSubmenu])
[[cell target] update];
[[cell target] update];
/* If there is no action - there can be no validator for the cell */
if (action)
{
/* If there is a target use that for validation (or nil). */
if ((target = [cell target]))
{
if ([target respondsToSelector: action])
{
validator = target;
}
}
else
{
validator = [theApp targetForAction: action];
}
}
{
/* If there is a target use that for validation (or nil). */
if ((target = [cell target]))
{
if ([target respondsToSelector: action])
{
validator = target;
}
}
else
{
validator = [theApp targetForAction: action];
}
}
if (validator == nil)
{
shouldBeEnabled = NO;
}
else if ([validator respondsToSelector: @selector(validateMenuItem:)])
{
shouldBeEnabled = [validator validateMenuItem: cell];
}
{
shouldBeEnabled = NO;
}
else if ([validator respondsToSelector:@selector(validateMenuItem:)])
{
shouldBeEnabled = [validator validateMenuItem: cell];
}
else
{
shouldBeEnabled = YES;
}
{
shouldBeEnabled = YES;
}
if (shouldBeEnabled != wasEnabled)
{
[cell setEnabled: shouldBeEnabled];
[menuCells setNeedsDisplayInRect: [menuCells cellFrameAtRow: i]];
}
{
[cell setEnabled: shouldBeEnabled];
// FIXME
// [menuCells setNeedsDisplayInRect: [menuCells cellFrameAtRow: i]];
}
}
if (menuHasChanged)
if (menu_changed)
[self sizeToFit];
/* Reenable displaying of menus */
[self setMenuChangedMessagesEnabled: YES];
}
- (BOOL) performKeyEquivalent: (NSEvent*)theEvent
{
unsigned i;
unsigned count = [menu_items count];
NSEventType type = [theEvent type];
if (type != NSKeyDown && type != NSKeyUp)
return NO;
for (i = 0; i < count; i++)
{
id<NSMenuItem> cell = [menu_items 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]])
{
[menu_view lockFocus];
[(id)cell performClick: self];
[menu_view unlockFocus];
return YES;
}
}
}
return NO;
}
- (void) performActionForItem: (id <NSMenuItem>)cell
{
NSNotificationCenter *nc;
@ -561,7 +414,7 @@ static Class menuCellClass = nil;
if (![cell isEnabled])
return;
nc = [NSNotificationCenter defaultCenter];
d = [NSDictionary dictionaryWithObject: cell forKey: @"MenuItem"];
[nc postNotificationName: NSMenuWillSendActionNotification
@ -571,81 +424,56 @@ static Class menuCellClass = nil;
to: [cell target]
from: cell];
[nc postNotificationName: NSMenuDidSendActionNotification
object: self
userInfo: d];
object: self
userInfo: d];
}
- (BOOL) performKeyEquivalent: (NSEvent*)theEvent
- (void)setTitle: (NSString*)aTitle
{
id cells = [menuCells itemArray];
unsigned i;
unsigned 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]])
{
[menuCells lockFocus];
[(id)cell performClick: self];
[menuCells unlockFocus];
return YES;
}
}
}
return NO;
ASSIGN(menu_title, aTitle);
[self sizeToFit];
}
- (NSString*)title
{
return menu_title;
}
- (void) setMenuChangedMessagesEnabled: (BOOL)flag
- (void)setMenuRepresentation:(id)menuRep
{
menuChangedMessagesEnabled = flag;
ASSIGN(menu_rep, menuRep);
}
- (BOOL) menuChangedMessagesEnabled
- (id)menuRepresentation
{
return menuChangedMessagesEnabled;
return menu_rep;
}
- (void)setMenuChangedMessagesEnabled: (BOOL)flag
{
menu_ChangedMessagesEnabled = flag;
}
- (BOOL)menuChangedMessagesEnabled
{
return menu_ChangedMessagesEnabled;
}
- (void) sizeToFit
{
// SUBCLASS
[menuCells _resizeMenuForCellSize];
[menuCells setNeedsDisplay: YES];
menuHasChanged = NO;
{
// NSLog(@"- sizeToFit called in NSMenu\n");
//
// [menu_view sizeToFit];
// [menu_view setNeedsDisplay:YES];
// menu_changed = NO;
}
- (void) setTitle: (NSString*)aTitle
- (void)helpRequested:(NSEvent *)event
{
ASSIGN(title, aTitle);
[self sizeToFit];
}
- (NSString*) title
{
return title;
}
- (NSMenuMatrix*) menuCells
{
return menuCells;
// Won't be implemented until we have NSHelp*
}
// NSCoding
- (id) initWithCoder: (NSCoder*)aDecoder
{
return self;
@ -655,21 +483,9 @@ static Class menuCellClass = nil;
{
}
// non OS spec methods
- (void) _rightMouseDisplay
//NSCopying
- (id) copyWithZone: (NSZone*)zone
{
return self;
}
@end /* NSMenu */
@implementation NSMenu (PrivateMethods2)
- (void) _menuChanged
{
menuHasChanged = YES;
if (menuChangedMessagesEnabled)
[self sizeToFit];
}
@end

261
Source/NSMenuItemCell.m Normal file
View file

@ -0,0 +1,261 @@
#include <gnustep/gui/config.h>
#include <Foundation/NSString.h>
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSCoder.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSException.h>
#include <Foundation/NSProcessInfo.h>
#include <Foundation/NSString.h>
#include <Foundation/NSNotification.h>
#include <AppKit/NSColor.h>
#include <AppKit/NSFont.h>
#include <AppKit/NSGraphics.h>
#include <AppKit/NSImage.h>
#include <AppKit/NSMenu.h>
#include <AppKit/NSMenuItemCell.h>
#include <AppKit/PSOperators.h>
static BOOL usesUserKeyEquivalents = YES;
@implementation NSMenuItemCell
+ (void)initialize
{
if (self == [NSMenuItemCell class])
{
// Initial version
[self setVersion:2];
}
}
- (id)init
{
mcell_has_submenu = NO;
[super init];
[super setTarget:nil];
return self;
}
// NSMenuitem protocol
- (void)setTarget:(id)anObject
{
BOOL hadSubmenu = mcell_has_submenu;
mcell_has_submenu = anObject && [anObject isKindOfClass:[NSMenu class]];
if (mcell_has_submenu)
[anObject retain];
if (hadSubmenu)
[target release];
[super setTarget:anObject];
}
- (BOOL)hasSubmenu
{
return mcell_has_submenu;
}
- (void)setTitle:(NSString*)aString
{
[super setStringValue:aString];
}
- (NSString*)title
{
return [super stringValue];
}
- (NSString*)keyEquivalent
{
if (usesUserKeyEquivalents)
return [self userKeyEquivalent];
else
return [super keyEquivalent];
}
- (NSString*)userKeyEquivalent
{
NSString* userKeyEquivalent = [[[[NSUserDefaults standardUserDefaults]
persistentDomainForName:NSGlobalDomain]
objectForKey:@"NSCommandKeys"]
objectForKey:[self stringValue]];
if (!userKeyEquivalent)
userKeyEquivalent = [super keyEquivalent];
return userKeyEquivalent;
}
- (void)setRepresentedObject:(id)anObject
{
ASSIGN(representedObject, anObject);
}
- (id)representedObject
{
return representedObject;
}
// NSMenuItemCell methods as defined by MacOSX API.
- (void)setHighlighted:(BOOL)flag
{
mcell_highlighted = flag;
}
- (BOOL)isHighlighted
{
return mcell_highlighted;
}
- (void)setMenuItem:(NSMenuItem *)item
{
ASSIGN(mcell_item, item);
}
- (NSMenuItem *)menuItem
{
return mcell_item;
}
- (void)calcSize
{
//calc sizes of images, title, and cache.
// At the end we set sizing to NO.
mcell_needs_sizing = NO;
}
- (void)setNeedsSizing:(BOOL)flag
{
mcell_needs_sizing = flag;
}
- (BOOL)needsSizing
{
return mcell_needs_sizing;
}
- (float)imageWidth
{
if (mcell_needs_sizing)
[self calcSize];
return mcell_imageWidth;
}
- (float)titleWidth
{
if (mcell_needs_sizing)
[self calcSize];
// return mcell_titleWidth;
return [[NSFont systemFontOfSize:12] widthOfString:[self title]];
}
- (float)keyEquivalentWidth
{
if (mcell_needs_sizing)
[self calcSize];
return mcell_keyEqWidth;
}
- (float)stateImageWidth
{
if (mcell_needs_sizing)
[self calcSize];
return mcell_stateImgWidth;
}
// Drawing.
- (NSRect)imageRectForBounds:(NSRect)cellFrame
{
return NSZeroRect;
}
- (NSRect)keyEquivalentRectForBounds:(NSRect)cellFrame
{
return NSZeroRect;
}
- (NSRect)stateImageRectForBounds:(NSRect)cellFrame
{
return NSZeroRect;
}
- (NSRect)titleRectForBounds:(NSRect)cellFrame
{
return NSZeroRect;
}
// Real drawing,
- (void)drawBorderAndBackgroundWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView
{
}
- (void)drawImageWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView
{
}
- (void)drawKeyEquivalentWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView
{
}
- (void)drawSeparatorItemWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView
{
}
- (void)drawStateImageWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView
{
}
- (void)drawTitleWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView
{
}
- (void)drawWithFrame:(NSRect)cellFrame
inView:(NSView *)controlView
{
NSGraphicsContext *ctxt = GSCurrentContext();
NSRect floodRect = cellFrame;
NSDrawButton(cellFrame, cellFrame);
floodRect.origin.x += 1;
floodRect.origin.y += 2;
floodRect.size.height -= 3;
floodRect.size.width -= 2;
if (cell_highlighted) {
[[NSColor whiteColor] set];
NSRectFill(floodRect);
} else {
[[NSColor lightGrayColor] set];
NSRectFill(floodRect);
}
[[NSColor blackColor] set];
[[NSFont systemFontOfSize:12] set];
DPSmoveto(ctxt, cellFrame.origin.x + 5, cellFrame.origin.y + 6);
DPSshow(ctxt, [[self title] cString]);
if (mcell_has_submenu) {
floodRect.origin.x = cellFrame.size.width - 12;
floodRect.origin.y += 5;
floodRect.size.height = 7;
floodRect.size.width = 7;
[self _drawImage:[NSImage imageNamed:@"common_3DArrowRight"] inFrame:floodRect];
}
}
@end

603
Source/NSMenuView.m Normal file
View file

@ -0,0 +1,603 @@
#include <AppKit/NSApplication.h>
#include <AppKit/NSEvent.h>
#include <AppKit/NSMenuView.h>
#include <AppKit/NSWindow.h>
#include <AppKit/PSOperators.h>
static float GSMenuBarHeight = 25.0; // a guess.
@implementation NSMenuView
// Class methods.
+ (float)menuBarHeight
{
return GSMenuBarHeight;
}
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
return YES;
}
// Init methods.
- (id)init
{
return [self initWithFrame:NSZeroRect];
}
- (id)initWithFrame:(NSRect)aFrame
{
cellSize = NSMakeSize(110,20);
menuv_highlightedItemIndex = -1;
return [super initWithFrame:aFrame];
}
// Our menu.
- (void)setMenu:(NSMenu *)menu
{
ASSIGN(menuv_menu, menu);
}
- (NSMenu *)menu
{
return menuv_menu;
}
- (void)setHorizontal:(BOOL)flag
{
menuv_horizontal = flag;
}
- (BOOL)isHorizontal
{
return menuv_horizontal;
}
- (void)setFont:(NSFont *)font
{
ASSIGN(menuv_font, font);
}
- (NSFont *)font
{
return menuv_font;
}
/*
* - (void)setHighlightedItemIndex:(int)index
*
* MacOS-X defines this function as the central way of switching to a new
* highlighted item. The index value is == to the item you want
* highlighted. When used this method unhighlights the last item (if
* applicable) and selects the new item. If index == -1 highlighting is
* turned off.
*
* NOTES (Michael Hanni):
*
* I modified this method for GNUstep to take submenus into account. This
* way we get maximum performance while still using a method outside the
* loop.
*
*/
- (void)setHighlightedItemIndex:(int)index
{
NSArray *menu_items = [menuv_menu itemArray];
id anItem;
[self lockFocus];
if (index == -1) {
if (menuv_highlightedItemIndex != -1) {
anItem = [menu_items objectAtIndex:menuv_highlightedItemIndex];
[anItem highlight:NO
withFrame:[self rectOfItemAtIndex:menuv_highlightedItemIndex]
inView:self];
[anItem setState:0];
menuv_highlightedItemIndex = -1;
}
} else if (index >= 0) {
if ( menuv_highlightedItemIndex != -1 ) {
anItem = [menu_items objectAtIndex:menuv_highlightedItemIndex];
[anItem highlight:NO
withFrame:[self rectOfItemAtIndex:menuv_highlightedItemIndex]
inView:self];
if ([anItem hasSubmenu] && ![[anItem target] isTornOff])
[[anItem target] close];
[anItem setState:0];
}
anItem = [menu_items objectAtIndex:index];
[anItem highlight:YES
withFrame:[self rectOfItemAtIndex:index]
inView:self];
[anItem setState:1];
if ([anItem hasSubmenu])
[[anItem target] display];
// set view needs to be redrawn
[window flushWindow];
// set ivar to new index
menuv_highlightedItemIndex = index;
}
[self unlockFocus];
[window flushWindow];
}
- (int)highlightedItemIndex
{
return menuv_highlightedItemIndex;
}
- (void)setMenuItemCell:(NSMenuItemCell *)cell
forItemAtIndex:(int)index
{
// [menuv_items insertObject:cell atIndex:index];
// resize the cell
[cell setNeedsSizing:YES];
// resize menuview
[self setNeedsSizing:YES];
}
- (NSMenuItemCell *)menuItemCellForItemAtIndex:(int)index
{
return [[menuv_menu itemArray] objectAtIndex:index];
}
- (NSMenuView *)attachedMenuView
{
return [[menuv_menu attachedMenu] menuView];
}
- (NSMenu *)attachedMenu
{
return [menuv_menu attachedMenu];
}
- (BOOL)isAttached
{
return [menuv_menu isAttached];
}
- (BOOL)isTornOff
{
return [menuv_menu isTornOff];
}
- (void)setHorizontalEdgePadding:(float)pad
{
menuv_hEdgePad = pad;
}
- (float)horizontalEdgePadding
{
return menuv_hEdgePad;
}
- (void)itemChanged:(NSNotification *)notification
{
}
- (void)itemAdded:(NSNotification *)notification
{
}
- (void)itemRemoved:(NSNotification *)notification
{
}
// Submenus.
- (void)detachSubmenu
{
}
- (void)attachSubmenuForItemAtIndex:(int)index
{
// create rect to display submenu in.
// order window with submenu in it to front.
}
- (void)update
{
// [menuv_menu update];
if (menuv_needsSizing)
[self sizeToFit];
}
- (void)setNeedsSizing:(BOOL)flag
{
menuv_needsSizing = flag;
}
- (BOOL)needsSizing
{
return menuv_needsSizing;
}
- (void)sizeToFit
{
int i;
int howMany = [[menuv_menu itemArray] count];
int howHigh = (howMany * cellSize.height) + 21;
float neededWidth = 0;
for (i=0;i<[[menuv_menu itemArray] count];i++)
{
float aWidth;
NSMenuItemCell *anItem = [[menuv_menu itemArray] objectAtIndex:i];
aWidth = [anItem titleWidth];
if (aWidth > neededWidth)
neededWidth = aWidth;
}
cellSize.width = 7 + neededWidth + 7 + 7 + 5;
[[self window] setFrame:NSMakeRect(300,300,cellSize.width,howHigh) display:YES];
[self setFrame:NSMakeRect(0,0,cellSize.width,howHigh-21)];
}
- (float)stateImageOffset
{
if (menuv_needsSizing)
[self sizeToFit];
return menuv_stateImageOffset;
}
- (float)stateImageWidth
{
if (menuv_needsSizing)
[self sizeToFit];
return menuv_stateImageWidth;
}
- (float)imageAndTitleOffset
{
if (menuv_needsSizing)
[self sizeToFit];
return menuv_imageAndTitleOffset;
}
- (float)imageAndTitleWidth
{
if (menuv_needsSizing)
[self sizeToFit];
return menuv_imageAndTitleWidth;
}
- (float)keyEquivalentOffset
{
if (menuv_needsSizing)
[self sizeToFit];
return menuv_keyEqOffset;
}
- (float)keyEquivalentWidth
{
if (menuv_needsSizing)
[self sizeToFit];
return menuv_keyEqWidth;
}
- (NSRect)innerRect
{
return [self bounds];
// this could change if we drew menuitemcells as
// plain rects with no bezel like in macOSX. Talk to Michael Hanni if
// you would like to see this configurable.
}
- (NSRect)rectOfItemAtIndex:(int)index
{
NSRect theRect;
if (menuv_needsSizing)
[self sizeToFit];
if (index == 0)
theRect.origin.y = [self frame].size.height - cellSize.height;
else
theRect.origin.y = [self frame].size.height - (cellSize.height * (index + 1));
theRect.origin.x = 0;
theRect.size = cellSize;
return theRect;
}
- (int)indexOfItemAtPoint:(NSPoint)point
{
// The MacOSX API says that this method calls - rectOfItemAtIndex for
// *every* cell to figure this out. Well, instead we will just do some
// simple math.
NSRect aRect = [self rectOfItemAtIndex:0];
// this will need some finnessing but should be close.
return ([self frame].size.height - point.y) / aRect.size.height;
}
- (void)setNeedsDisplayForItemAtIndex:(int)index
{
[[[menuv_menu itemArray] objectAtIndex:index] setNeedsDisplay:YES];
}
- (NSPoint)locationForSubmenu:(NSMenu *)aSubmenu
{
if (menuv_needsSizing)
[self sizeToFit];
// find aSubmenu's parent
// position aSubmenu's window to be adjacent to its parent.
// return new origin of window.
return NSZeroPoint;
}
- (void)resizeWindowWithMaxHeight:(float)maxHeight
{
// set the menuview's window to max height in order to keep on screen?
}
- (void)setWindowFrameForAttachingToRect:(NSRect)screenRect
onScreen:(NSScreen *)screen
preferredEdge:(NSRectEdge)edge
popUpSelectedItem:(int)selectedItemIndex
{
// huh.
}
// Drawing.
- (void)drawRect:(NSRect)rect
{
int i;
NSArray *menuCells = [menuv_menu itemArray];
NSRect aRect = [self frame];
// This code currently doesn't take intercell spacing into account. I'll
// need to fix that.
aRect.origin.y = cellSize.height * ([menuCells count] - 1);
aRect.size = cellSize;
for (i=0;i<[menuCells count];i++)
{
id aCell = [menuCells objectAtIndex:i];
[aCell drawWithFrame:aRect inView:self];
aRect.origin.y -= cellSize.height;
}
}
// Event.
- (void)performActionWithHighlightingForItemAtIndex:(int)index
{
// for use with key equivalents.
}
- (BOOL)trackWithEvent:(NSEvent *)event
{
NSPoint lastLocation = [event locationInWindow];
float height = [self frame].size.height;
int index;
int lastIndex = 0;
unsigned eventMask = NSLeftMouseUpMask | NSLeftMouseDownMask
| NSRightMouseUpMask | NSRightMouseDraggedMask
| NSLeftMouseDraggedMask;
BOOL done = NO;
NSApplication *theApp = [NSApplication sharedApplication];
NSDate *theDistantFuture = [NSDate distantFuture];
int theCount = [[menuv_menu itemArray] count];
id selectedCell;
// These 3 BOOLs are misnomers. I'll rename them later. -Michael. FIXME.
BOOL weWereOut = NO;
BOOL weLeftMenu = NO;
BOOL weRightMenu = NO;
// Get our mouse location, regardless of where it may be it the event
// stream.
lastLocation = [[self window] mouseLocationOutsideOfEventStream];
index = (height - lastLocation.y) / cellSize.height;
if (index >= 0 && index < theCount) {
[self setHighlightedItemIndex:index];
lastIndex = index;
}
while (!done) {
event = [theApp nextEventMatchingMask: eventMask
untilDate: theDistantFuture
inMode: NSEventTrackingRunLoopMode
dequeue: YES];
switch ([event type])
{
case NSRightMouseUp:
case NSLeftMouseUp:
/* right mouse up or left mouse up means we're done */
done = YES;
break;
case NSRightMouseDragged:
case NSLeftMouseDragged:
lastLocation = [[self window] mouseLocationOutsideOfEventStream];
#ifdef 0
NSLog (@"location = (%f, %f, %f)", lastLocation.x, [[self window]
frame].origin.x, [[self window] frame].size.width);
#endif
if (lastLocation.x > 0
&& lastLocation.x < [[self window] frame].size.width) {
lastLocation = [self convertPoint: lastLocation fromView:nil];
index = (height - lastLocation.y) / cellSize.height;
#ifdef 0
NSLog (@"location = (%f, %f)", lastLocation.x, lastLocation.y);
NSLog (@"index = %d\n", index);
#endif
if (index >= 0 && index < theCount) {
if (index != lastIndex) {
[self setHighlightedItemIndex:index];
lastIndex = index;
} else {
if (weWereOut) {
[self setHighlightedItemIndex:index];
lastIndex = index;
weWereOut = NO;
}
}
}
} else if (lastLocation.x > [[self window] frame].size.width) {
NSRect aRect = [self rectOfItemAtIndex:lastIndex];
if (lastLocation.y > aRect.origin.y && lastLocation.y <
aRect.origin.y + aRect.size.height && [[[menuv_menu itemArray] objectAtIndex:lastIndex] hasSubmenu]) {
weLeftMenu = YES;
done = YES;
}
} else if (lastLocation.x < 0) {
if ([menuv_menu supermenu]) {
weRightMenu = YES;
done = YES;
}
} else {
// FIXME, Michael. This might be needed... or not?
/*
NSLog(@"This is the final else... its evil\n");
if (lastIndex >= 0 && lastIndex < theCount) {
[self setHighlightedItemIndex:-1];
lastIndex = index;
weWereOut = YES;
[window flushWindow];
}
*/
}
[window flushWindow];
default:
break;
}
}
if (!weLeftMenu && !weRightMenu) {
if (![[[menuv_menu itemArray] objectAtIndex:menuv_highlightedItemIndex] hasSubmenu]) {
BOOL finished = NO;
NSMenu *aMenu = menuv_menu;
selectedCell = [[menuv_menu itemArray] objectAtIndex:index];
[self setHighlightedItemIndex:-1];
if ([selectedCell action])
[menuv_menu performActionForItem:[[menuv_menu itemArray] objectAtIndex:index]];
if ([selectedCell hasSubmenu])
[[selectedCell target] close];
while (!finished) { // Recursive menu close & deselect.
if ([aMenu supermenu] && ![aMenu isTornOff]) {
[[[aMenu supermenu] menuView] setHighlightedItemIndex:-1];
[aMenu close];
aMenu = [aMenu supermenu];
}
else
finished = YES;
[window flushWindow];
}
}
} else if (weRightMenu) {
NSPoint cP = [[self window] convertBaseToScreen:lastLocation];
[self setHighlightedItemIndex:-1];
if ([menuv_menu supermenu] && ![menuv_menu isTornOff]) {
[self mouseUp:
[NSEvent mouseEventWithType:NSLeftMouseUp
location:cP
modifierFlags:[event modifierFlags]
timestamp:[event timestamp]
windowNumber:[[self window] windowNumber]
context:[event context]
eventNumber:[event eventNumber]
clickCount:[event clickCount]
pressure:[event pressure]]];
[[[menuv_menu supermenu] menuView] mouseDown:
[NSEvent mouseEventWithType:NSLeftMouseDragged
location:cP
modifierFlags:[event modifierFlags]
timestamp:[event timestamp]
windowNumber:[[[[menuv_menu supermenu] menuView] window] windowNumber]
context:[event context]
eventNumber:[event eventNumber]
clickCount:[event clickCount]
pressure:[event pressure]]];
}
} else /* The weLeftMenu case */ {
NSPoint cP = [[self window] convertBaseToScreen:lastLocation];
NSLog(@"Urph.\n");
selectedCell = [[menuv_menu itemArray] objectAtIndex:lastIndex];
if ([selectedCell hasSubmenu]) {
[self mouseUp:
[NSEvent mouseEventWithType:NSLeftMouseUp
location:cP
modifierFlags:[event modifierFlags]
timestamp:[event timestamp]
windowNumber:[[self window] windowNumber]
context:[event context]
eventNumber:[event eventNumber]
clickCount:[event clickCount]
pressure:[event pressure]]];
[[[selectedCell target] menuView] mouseDown:
[NSEvent mouseEventWithType:NSLeftMouseDragged
location:cP
modifierFlags:[event modifierFlags]
timestamp:[event timestamp]
windowNumber:[[[[selectedCell target] menuView] window] windowNumber]
context:[event context]
eventNumber:[event eventNumber]
clickCount:[event clickCount]
pressure:[event pressure]]];
}
}
return YES;
}
- (void)mouseDown:(NSEvent *)theEvent
{
[self trackWithEvent:theEvent];
}
@end

View file

@ -29,7 +29,7 @@
*/
#include <gnustep/gui/config.h>
#include <Foundation/NSArray.h>
#import <Foundation/Foundation.h>
#include <AppKit/NSPopUpButton.h>
#include <AppKit/NSPopUpButtonCell.h>
#include <AppKit/NSApplication.h>
@ -37,18 +37,83 @@
#include <AppKit/NSFont.h>
@implementation NSPopUpButtonMatrix
// Class variables
static NSFont* menuFont = nil;
- (BOOL) acceptsFirstMouse: (NSEvent *)theEvent
{
return YES;
}
- (id) initWithFrame: (NSRect)rect
{
[super initWithFrame: rect];
cells = [NSMutableArray new];
selected_cell = 0;
cellSize = NSMakeSize (rect.size.width, rect.size.height);
return self;
}
- (void) dealloc
{
NSDebugLog (@"NSMenuMatrix of menu '%@' dealloc", [menu title]);
[cells release];
[super dealloc];
}
- (id) copyWithZone: (NSZone*)zone
{
NSPopUpButtonMatrix* copy = [[isa allocWithZone: zone] initWithFrame: [self frame]];
int i, count;
NSDebugLog (@"copy menu matrix of menu with title '%@'", [menu title]);
for (i = 0, count = [cells count]; i < count; i++)
{
id aCell = [cells objectAtIndex: i];
id cellCopy = [[aCell copyWithZone: zone] autorelease];
[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;
}
- (void) _resizeMenuForCellSize
{
int i, count;
float titleWidth;
/* 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] stringValue]];
cellSize.width = MAX(titleWidth + ADDITIONAL_WIDTH, cellSize.width);
}
cellSize.width = MAX([menuFont widthOfString: [menu title]]
+ ADDITIONAL_WIDTH,
cellSize.width);
/* Resize the frame to hold all the menu cells */
[super setFrameSize: NSMakeSize (cellSize.width,
count ? (cellSize.height + INTERCELL_SPACE)*count - INTERCELL_SPACE : 0)];
}
- (id <NSMenuItem>)insertItemWithTitle: (NSString*)aString
@ -92,6 +157,115 @@
{
return pull_down;
}
- (BOOL) performKeyEquivalent: (NSEvent*)theEvent
{
return [menu performKeyEquivalent: theEvent];
}
- (void) removeItem: (id <NSMenuItem>)anItem
{
int row = [cells indexOfObject: anItem];
if (row == -1)
return;
[cells removeObjectAtIndex: row];
}
- (NSArray*) itemArray
{
return cells;
}
- (id <NSMenuItem>) itemWithTitle: (NSString*)aString
{
unsigned i, count = [cells count];
id menuCell;
for (i = 0; i < count; i++)
{
menuCell = [cells objectAtIndex: i];
if ([[menuCell title] isEqual: aString])
return menuCell;
}
return nil;
}
- (id <NSMenuItem>) itemWithTag: (int)aTag
{
unsigned 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
{
unsigned count = [cells count];
NSRect rect;
NSAssert(index >= 0 && index < count+1, @"invalid row coordinate");
rect.origin.x = 0;
rect.origin.y = (count - index - 1)
* (cellSize.height + INTERCELL_SPACE);
rect.size = cellSize;
return rect;
}
- (void)drawRect: (NSRect)rect
{
unsigned i = 0, count = [cells count];
int max, howMany;
NSRect aRect = [self frame];
// If there are no cells then just return
if (count == 0) return;
aRect.origin.y = cellSize.height * (count - 1);
aRect.size = cellSize;
for (i=0;i<count;i++)
{
id aCell = [cells objectAtIndex:i];
[aCell drawWithFrame:aRect inView:self];
aRect.origin.y -= cellSize.height;
}
}
- (NSSize) cellSize
{
return cellSize;
}
- (void) setMenu: (NSMenu*)anObject
{
menu = anObject;
}
- (void) setSelectedCell: (id)aCell
{
selectedCell = aCell;
}
- (id) selectedCell
{
return selectedCell;
}
- (NSRect) selectedCellRect
{
return selectedCellRect;
}
@end
//

View file

@ -1,6 +1,7 @@
#include <gnustep/gui/config.h>
#include <AppKit/NSColor.h>
#include <AppKit/NSFont.h>
#include <AppKit/NSGraphics.h>
#include <AppKit/NSImage.h>
#include <AppKit/NSMatrix.h>
#include <AppKit/NSPopUpButton.h>
@ -29,9 +30,9 @@
NSDrawButton(cellFrame, cellFrame);
arect.size.width -= 4;
arect.size.height -= 4;
arect.origin.x += 2;
arect.size.width -= 3;
arect.size.height -= 3;
arect.origin.x += 1;
arect.origin.y += 2;
if (cell_highlighted) {

View file

@ -976,7 +976,7 @@ NSLog(@"did set font");
_GNULineLayoutInfo *currentInfo;
NSRect retRect=NSMakeRect(0,0,0,0);
for(lineEnum=[linesToDraw objectEnumerator]; currentInfo=[lineEnum nextObject];)
for((lineEnum=[linesToDraw objectEnumerator]); (currentInfo=[lineEnum nextObject]);)
{ retRect=NSUnionRect(retRect,[currentInfo lineRect]);
} return retRect;
}
@ -1021,7 +1021,7 @@ NSLog(@"did set font");
[[lineLayoutInformation lastObject] lineRect].size.height) {
newY = currentCursorY - tRect.size.height +
([[lineLayoutInformation lastObject] lineRect].size.height * 2);
[[self superview] scrollToPoint:NSMakePoint(sizeToRect.origin.x,newY)];
[(NSClipView *)[self superview] scrollToPoint:NSMakePoint(sizeToRect.origin.x,newY)];
}
else
NSLog(@"=========> Oops!\n");
@ -1150,7 +1150,7 @@ rectForCharacterIndex:[self selectedRange].location],
if([lineLayoutInformation count] && anIndex>= NSMaxRange([[lineLayoutInformation lastObject] lineRange]))
return [lineLayoutInformation count]-1;
for(lineEnum=[lineLayoutInformation objectEnumerator]; currentInfo=[lineEnum nextObject];)
for((lineEnum=[lineLayoutInformation objectEnumerator]); (currentInfo=[lineEnum nextObject]);)
{ NSRange lineRange=[currentInfo lineRange];
if(lineRange.location<= anIndex && anIndex<= NSMaxRange(lineRange)-([currentInfo type] == LineLayoutInfoType_Paragraph? 1:0))
return [lineLayoutInformation indexOfObject:currentInfo];
@ -1432,7 +1432,7 @@ NSLog(NSStringFromRange(redrawLineRange));
{ unsigned short keyCode;
if(!is_editable) return; // If not editable then don't recognize the key down
if(keyCode=[theEvent keyCode])
if((keyCode=[theEvent keyCode]))
switch(keyCode)
{ case NSUpArrowFunctionKey: //NSUpArrowFunctionKey:
[self moveCursorUp:self];
@ -1609,7 +1609,7 @@ NSLog(@"keycode:%x",keyCode);
point.x=MAX(0,point.x); point.y=MAX(0,point.y);
for(i=0,lineEnum=[lineLayoutInformation objectEnumerator]; currentInfo=[lineEnum nextObject];i++)
for(i=0,(lineEnum=[lineLayoutInformation objectEnumerator]);(currentInfo=[lineEnum nextObject]);i++)
{ NSRect rect=[currentInfo lineRect];
if(NSMaxY(rect)>=point.y && rect.origin.y<point.y && rect.origin.x< point.x && point.x >= NSMaxX(rect) ) return NSMaxRange([currentInfo lineRange]);
if(NSPointInRect(point,rect)) // this loop holds some optimization potential (linear search)
@ -1648,7 +1648,7 @@ NSLog(@"keycode:%x",keyCode);
return NSMakeRect(NSMaxX(rect), rect.origin.y,[self frame].size.width-NSMaxX(rect),rect.size.height);
}
for(i=0,lineEnum=[lineLayoutInformation objectEnumerator]; currentInfo=[lineEnum nextObject];i++)
for(i=0,(lineEnum=[lineLayoutInformation objectEnumerator]);(currentInfo=[lineEnum nextObject]);i++)
{ NSRange range=[currentInfo lineRange];
if(NSLocationInRange(index,range))
{ NSRect rect=[currentInfo lineRect];
@ -1677,7 +1677,7 @@ NSLog(@"keycode:%x",keyCode);
point.x=MAX(0,point.x); point.y=MAX(0,point.y);
for(i=0,lineEnum=[lineLayoutInformation objectEnumerator]; currentInfo=[lineEnum nextObject];i++)
for(i=0,(lineEnum=[lineLayoutInformation objectEnumerator]); (currentInfo=[lineEnum nextObject]);i++)
{ NSRect rect=[currentInfo lineRect];
if(NSMaxY(rect)> point.y && rect.origin.y<= point.y && rect.origin.x< point.x && point.x >= NSMaxX(rect) )
return [lineLayoutInformation indexOfObject:currentInfo];
@ -1743,7 +1743,7 @@ static unsigned _relocLayoutArray(NSMutableArray *lineLayoutInformation,NSArray
if(![relocArray count]) return ret;
for(relocEnum=[relocArray objectEnumerator]; currReloc=[relocEnum nextObject];)
for((relocEnum=[relocArray objectEnumerator]); (currReloc=[relocEnum nextObject]);)
{ NSRange range=[currReloc lineRange];
[currReloc setLineRange:NSMakeRange(range.location+relocOffset,range.length)];
if(yReloc)
@ -2018,7 +2018,7 @@ NSLog(@"opti hook 2");
_GNULineLayoutInfo *currentInfo;
NSDictionary *attributes=[self defaultTypingAttributes];
for(lineEnum=[linesToDraw objectEnumerator]; currentInfo=[lineEnum nextObject];)
for((lineEnum=[linesToDraw objectEnumerator]);(currentInfo=[lineEnum nextObject]);)
{ if([currentInfo isDontDisplay] || [currentInfo type]== LineLayoutInfoType_Paragraph) continue; // e.g. for nl
[[plainContent substringWithRange:[currentInfo lineRange]] drawAtPoint:[currentInfo lineRect].origin withAttributes:attributes];
// <!> make this use drawInRect:withAttributes: in the future (for proper adoption of layout information [e.g. centering])
@ -2034,7 +2034,7 @@ NSLog(@"opti hook 2");
NSEnumerator *lineEnum;
_GNULineLayoutInfo *currentInfo;
for(lineEnum=[linesToDraw objectEnumerator]; currentInfo=[lineEnum nextObject];)
for((lineEnum=[linesToDraw objectEnumerator]);(currentInfo=[lineEnum nextObject]);)
{ if([currentInfo isDontDisplay] || [currentInfo type] == LineLayoutInfoType_Paragraph) continue; // e.g. for nl
[rtfContent drawRange:[currentInfo lineRange] atPoint:[currentInfo lineRect].origin];
// <!> make this use drawRange: inRect: in the future (for proper adoption of layout information [e.g. centering])

View file

@ -43,9 +43,27 @@
// This variant will create the text network (textStorage, layoutManager, and a container).
- initWithFrame:(NSRect)frameRect
{ return [self initWithFrame:frameRect textContainer:nil];
{ return [self initWithFrame:frameRect textContainer:nil];
}
#ifdef 0
- initWithFrame:(NSRect)frameRect
{
textStorage = [NSTextStorage new];
// layoutManager = [NSLayoutManager new];
// [textStorage addLayoutManager:layoutManager];
// [layoutManager release];
textContainer = [[NSTextContainer alloc]
initWithContainerSize:frameRect];
// [layoutManager addTextContainer:textContainer];
[textContainer release];
return [self initWithFrame:frameRect textContainer:textContainer];
}
#endif
/***************** Get/Set the container and other stuff *****************/
-(NSTextContainer*) textContainer

View file

@ -1474,12 +1474,12 @@ static Class responderClass;
*/
if (content_view == nil)
[self setContentView: nil];
[[content_view superView] registerForDraggedTypes: newTypes];
[[content_view superview] registerForDraggedTypes: newTypes];
}
- (void) unregisterDraggedTypes
{
[[content_view superView] unregisterDraggedTypes];
[[content_view superview] unregisterDraggedTypes];
}
/*