mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-22 13:10:59 +00:00
Almost total reimplementation of the menuing code.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@5207 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
021c583cd3
commit
198c3258a1
11 changed files with 2207 additions and 1245 deletions
|
@ -44,8 +44,12 @@
|
|||
@class NSMatrix;
|
||||
@class NSMenuView;
|
||||
@class NSMenuWindow;
|
||||
@class NSPopUpButton;
|
||||
|
||||
@interface NSMenuWindow : NSPanel
|
||||
|
||||
- (void)moveToPoint:(NSPoint)aPoint;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSMenu : NSObject <NSCoding, NSCopying>
|
||||
|
@ -54,19 +58,20 @@
|
|||
NSMutableArray *menu_items;
|
||||
NSMenuView *menu_view;
|
||||
NSMenu *menu_supermenu;
|
||||
NSMenu *menu_attached_menu;
|
||||
id menu_rep;
|
||||
BOOL menu_ChangedMessagesEnabled;
|
||||
NSMenu *menu_attachedMenu;
|
||||
BOOL menu_changedMessagesEnabled;
|
||||
NSMutableArray *menu_notifications;
|
||||
BOOL menu_autoenable;
|
||||
BOOL menu_changed;
|
||||
BOOL menu_is_tornoff;
|
||||
|
||||
id menu_popb;
|
||||
|
||||
// Private.
|
||||
// GNUstepExtra category
|
||||
BOOL menu_is_beholdenToPopUpButton;
|
||||
BOOL menu_follow_transient;
|
||||
BOOL menu_is_visible;
|
||||
BOOL menu_isPartlyOffScreen;
|
||||
|
||||
// Reserved for back-end use
|
||||
void *be_menu_reserved;
|
||||
|
@ -75,35 +80,40 @@
|
|||
NSMenuWindow *aWindow;
|
||||
NSMenuWindow *bWindow;
|
||||
id titleView;
|
||||
NSMenu *_oldAttachedMenu;
|
||||
}
|
||||
|
||||
/* Controlling allocation zones */
|
||||
+ (void)setMenuZone:(NSZone*)zone;
|
||||
+ (NSZone*)menuZone;
|
||||
/* Controlling Allocation Zones */
|
||||
+ (void) setMenuZone: (NSZone*)zone;
|
||||
+ (NSZone*) menuZone;
|
||||
|
||||
/* Setting the menu cell class */
|
||||
+ (void)setCellClass:(Class)aClass;
|
||||
+ (Class)cellClass;
|
||||
/* Creating an NSMenu */
|
||||
- (id) initWithTitle: (NSString*)aTitle;
|
||||
- (id) initWithPopUpButton: (NSPopUpButton*)popb;
|
||||
|
||||
/* Initializing a new NSMenu */
|
||||
- (id)initWithTitle:(NSString*)aTitle;
|
||||
|
||||
/* Setting up the menu commands */
|
||||
/* Setting Up the Menu Commands */
|
||||
- (void) addItem: (id <NSMenuItem>)newItem;
|
||||
- (id <NSMenuItem>) addItemWithTitle: (NSString *)aString
|
||||
action: (SEL)aSelector
|
||||
keyEquivalent: (NSString *)keyEquiv;
|
||||
- (void) insertItem: (id <NSMenuItem>)newItem
|
||||
atIndex: (int)index;
|
||||
- (id <NSMenuItem>) insertItemWithTitle: (NSString *)aString
|
||||
action: (SEL)aSelector
|
||||
keyEquivalent: (NSString *)charCode
|
||||
atIndex: (unsigned int)index;
|
||||
- (void) addItem: (id <NSMenuItem>)newItem;
|
||||
- (id <NSMenuItem>) addItemWithTitle: (NSString *)aString
|
||||
action: (SEL)aSelector
|
||||
keyEquivalent: (NSString *)keyEquiv;
|
||||
- (void) itemChanged: (id <NSMenuItem>)anObject;
|
||||
- (void) removeItem: (id <NSMenuItem>)anItem;
|
||||
- (void) removeItemAtIndex: (int)index;
|
||||
|
||||
- (NSArray*)itemArray;
|
||||
/* Finding menu items */
|
||||
- (NSArray*) itemArray;
|
||||
- (id <NSMenuItem>) itemAtIndex: (int)index;
|
||||
- (id <NSMenuItem>) itemWithTag: (int)aTag;
|
||||
- (id <NSMenuItem>) itemWithTitle: (NSString*)aString;
|
||||
- (int) numberOfItems;
|
||||
|
||||
/* Finding Indices of Menu Items */
|
||||
- (int) indexOfItem: (id <NSMenuItem>)anObject;
|
||||
- (int) indexOfItemWithTitle: (NSString *)aTitle;
|
||||
- (int) indexOfItemWithTag: (int)aTag;
|
||||
|
@ -112,79 +122,90 @@
|
|||
- (int) indexOfItemWithRepresentedObject: (id)anObject;
|
||||
- (int) indexOfItemWithSubmenu: (NSMenu *)anObject;
|
||||
|
||||
/* Finding menu items */
|
||||
- (id <NSMenuItem>)itemWithTag:(int)aTag;
|
||||
- (id <NSMenuItem>)itemWithTitle:(NSString*)aString;
|
||||
|
||||
/* Managing submenus */
|
||||
- (void)setSubmenu:(NSMenu*)aMenu forItem:(id <NSMenuItem>)anItem;
|
||||
- (void)submenuAction:(id)sender;
|
||||
- (NSMenu*)attachedMenu;
|
||||
- (BOOL)isAttached;
|
||||
- (BOOL)isTornOff;
|
||||
- (NSPoint)locationForSubmenu:(NSMenu*)aSubmenu;
|
||||
- (NSMenu*)supermenu;
|
||||
- (void) setSubmenu: (NSMenu*)aMenu forItem: (id <NSMenuItem>)anItem;
|
||||
- (void) submenuAction: (id)sender;
|
||||
- (NSMenu*) attachedMenu;
|
||||
- (BOOL) isAttached;
|
||||
- (BOOL) isTornOff;
|
||||
- (NSPoint) locationForSubmenu:(NSMenu*)aSubmenu;
|
||||
- (NSMenu*) supermenu;
|
||||
- (void) setSupermenu: (NSMenu *)supermenu;
|
||||
|
||||
/* Enabling and disabling menu items */
|
||||
- (void)setAutoenablesItems:(BOOL)flag;
|
||||
- (BOOL)autoenablesItems;
|
||||
- (void)update;
|
||||
|
||||
/* Perform a menu item action (not an OpenStep method) */
|
||||
- (void)performActionForItem:(id <NSMenuItem>)anItem;
|
||||
- (BOOL) autoenablesItems;
|
||||
- (void) setAutoenablesItems: (BOOL)flag;
|
||||
- (void) update;
|
||||
|
||||
/* Handling keyboard equivalents */
|
||||
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
|
||||
- (BOOL) performKeyEquivalent: (NSEvent*)theEvent;
|
||||
|
||||
/* Updating menu layout */
|
||||
- (void)setMenuChangedMessagesEnabled:(BOOL)flag;
|
||||
- (BOOL)menuChangedMessagesEnabled;
|
||||
- (void)sizeToFit;
|
||||
/* Simulating Mouse Clicks */
|
||||
- (void) performActionForItemAtIndex: (int)index;
|
||||
|
||||
/* Getting and setting the menu title */
|
||||
- (void)setTitle:(NSString*)aTitle;
|
||||
- (NSString*)title;
|
||||
/* Setting the Title */
|
||||
- (void) setTitle: (NSString*)aTitle;
|
||||
- (NSString*) title;
|
||||
|
||||
/* Getting the menu cells matrix */
|
||||
- (NSMenuView *)menuView;
|
||||
/* Setting the representing object */
|
||||
- (void) setMenuRepresentation: (id)menuRep;
|
||||
- (id) menuRepresentation;
|
||||
|
||||
// non OS spec methods
|
||||
- (void)_rightMouseDisplay;
|
||||
/* Updating Menu Layout */
|
||||
- (void) setMenuChangedMessagesEnabled: (BOOL)flag;
|
||||
- (BOOL) menuChangedMessagesEnabled;
|
||||
- (void) sizeToFit;
|
||||
|
||||
/* Displaying Context-Sensitive Help */
|
||||
- (void) helpRequested: (NSEvent*)event;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSObject (NSMenuActionResponder)
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem*)aMenuItem;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSMenu (PrivateMethods)
|
||||
- (BOOL) isFollowTransient;
|
||||
@interface NSMenu (GNUstepExtra)
|
||||
- (BOOL)isFollowTransient;
|
||||
- (NSWindow *)window;
|
||||
|
||||
/* Shows the menu window on screen */
|
||||
- (void)display;
|
||||
- (void)displayTransient;
|
||||
|
||||
/* Close the associated window menu */
|
||||
- (void)close;
|
||||
- (void)closeTransient;
|
||||
|
||||
/* Moving menus */
|
||||
- (void)nestedSetFrameOrigin:(NSPoint)aPoint;
|
||||
|
||||
/* Shift partly off-screen menus */
|
||||
- (BOOL)isPartlyOffScreen;
|
||||
- (void)nestedCheckOffScreen;
|
||||
- (void)shiftOnScreen;
|
||||
|
||||
@end
|
||||
|
||||
/* A menu's title is an instance of this class */
|
||||
@interface NSMenuWindowTitleView : NSView
|
||||
{
|
||||
// a menu's title
|
||||
int titleHeight;
|
||||
// is an instance
|
||||
id menu;
|
||||
// of this class
|
||||
NSButton* button;
|
||||
NSButtonCell* buttonCell;
|
||||
int titleHeight;
|
||||
id menu;
|
||||
NSButton* button;
|
||||
NSButtonCell* buttonCell;
|
||||
}
|
||||
|
||||
- (void) _addCloseButton;
|
||||
- (void) _releaseCloseButton;
|
||||
- (void) windowBecomeTornOff;
|
||||
- (void) setMenu: (NSMenu*)menu;
|
||||
- (NSMenu*) menu;
|
||||
|
||||
@end
|
||||
|
||||
extern NSString* const NSMenuDidSendActionNotification;
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Author: David Lazaro Saz <khelekir@encomix.es>
|
||||
Date: Sep 1999
|
||||
|
||||
Author: Ovidiu Predescu <ovidiu@net-community.com>
|
||||
Date: May 1997
|
||||
|
||||
|
@ -33,60 +36,157 @@
|
|||
|
||||
@protocol NSMenuItem <NSCopying, NSCoding>
|
||||
|
||||
- (void)setTarget:(id)anObject;
|
||||
- (id)target;
|
||||
- (void)setAction:(SEL)aSelector;
|
||||
- (SEL)action;
|
||||
+ (void)setUsesUserKeyEquivalents:(BOOL)flag;
|
||||
+ (BOOL)usesUserKeyEquivalents;
|
||||
|
||||
+ (id <NSMenuItem>)separatorItem;
|
||||
|
||||
- (id)initWithTitle:(NSString *)aString
|
||||
action:(SEL)aSelector
|
||||
keyEquivalent:(NSString *)charCode;
|
||||
|
||||
- (void)setMenu:(NSMenu *)menu;
|
||||
- (NSMenu *)menu;
|
||||
|
||||
- (BOOL)hasSubmenu;
|
||||
- (void)setSubmenu:(NSMenu *)submenu;
|
||||
- (NSMenu *)submenu;
|
||||
|
||||
- (void)setTitle:(NSString*)aString;
|
||||
- (NSString*)title;
|
||||
|
||||
- (void)setTag:(int)anInt;
|
||||
- (int)tag;
|
||||
|
||||
- (void)setEnabled:(BOOL)flag;
|
||||
- (BOOL)isEnabled;
|
||||
|
||||
- (BOOL)hasSubmenu;
|
||||
- (BOOL)isSeparatorItem;
|
||||
|
||||
- (void)setKeyEquivalent:(NSString*)aKeyEquivalent;
|
||||
- (NSString*)keyEquivalent;
|
||||
- (void)setKeyEquivalentModifierMask:(unsigned int)mask;
|
||||
- (unsigned int)keyEquivalentModifierMask;
|
||||
|
||||
+ (void)setUsesUserKeyEquivalents:(BOOL)flag;
|
||||
+ (BOOL)usesUserKeyEquivalents;
|
||||
- (NSString*)userKeyEquivalent;
|
||||
|
||||
- (void)setMnemonicLocation:(unsigned) location;
|
||||
- (unsigned)mnemonicLocation;
|
||||
- (NSString *)mnemonic;
|
||||
- (void)setTitleWithMnemonic:(NSString *)stringWithAmpersand;
|
||||
|
||||
- (void)setImage:(NSImage *)menuImage;
|
||||
- (NSImage *)image;
|
||||
|
||||
- (void)setState:(int)state;
|
||||
- (int)state;
|
||||
- (void)setOnStateImage:(NSImage *)image;
|
||||
- (NSImage *)onStateImage;
|
||||
- (void)setOffStateImage:(NSImage *)image;
|
||||
- (NSImage *)offStateImage;
|
||||
- (void)setMixedStateImage:(NSImage *)image;
|
||||
- (NSImage *)mixedStateImage;
|
||||
|
||||
- (void)setEnabled:(BOOL)flag;
|
||||
- (BOOL)isEnabled;
|
||||
|
||||
- (void)setTarget:(id)anObject;
|
||||
- (id)target;
|
||||
- (void)setAction:(SEL)aSelector;
|
||||
- (SEL)action;
|
||||
|
||||
- (void)setTag:(int)anInt;
|
||||
- (int)tag;
|
||||
|
||||
- (void)setRepresentedObject:(id)anObject;
|
||||
- (id)representedObject;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NSMenuItem : NSButtonCell <NSMenuItem>
|
||||
@interface NSMenuItem : NSObject <NSMenuItem>
|
||||
{
|
||||
id representedObject;
|
||||
BOOL hasSubmenu;
|
||||
NSMenu *mi_menu;
|
||||
NSString *mi_title;
|
||||
NSString *mi_keyEquivalent;
|
||||
unsigned int mi_keyEquivalentModifierMask;
|
||||
unsigned mi_mnemonicLocation;
|
||||
int mi_state;
|
||||
BOOL mi_enabled;
|
||||
NSImage *mi_image;
|
||||
NSImage *mi_onStateImage;
|
||||
NSImage *mi_offStateImage;
|
||||
NSImage *mi_mixedStateImage;
|
||||
id mi_target;
|
||||
SEL mi_action;
|
||||
int mi_tag;
|
||||
id mi_representedObject;
|
||||
BOOL mi_hasSubmenu;
|
||||
NSMenu *mi_submenu;
|
||||
BOOL mi_changesState;
|
||||
|
||||
// Reserved for back-end use
|
||||
void *be_mi_reserved;
|
||||
}
|
||||
|
||||
- (void)setTitle:(NSString*)aString;
|
||||
- (NSString*)title;
|
||||
|
||||
- (BOOL)hasSubmenu;
|
||||
|
||||
+ (void)setUsesUserKeyEquivalents:(BOOL)flag;
|
||||
+ (BOOL)usesUserKeyEquivalents;
|
||||
- (NSString*)userKeyEquivalent;
|
||||
|
||||
+ (id <NSMenuItem>)separatorItem;
|
||||
|
||||
- (id)initWithTitle:(NSString *)aString
|
||||
action:(SEL)aSelector
|
||||
keyEquivalent:(NSString *)charCode;
|
||||
|
||||
- (void)setMenu:(NSMenu *)menu;
|
||||
- (NSMenu *)menu;
|
||||
|
||||
- (BOOL)hasSubmenu;
|
||||
- (void)setSubmenu:(NSMenu *)submenu;
|
||||
- (NSMenu *)submenu;
|
||||
|
||||
- (void)setTitle:(NSString *)aString;
|
||||
- (NSString *)title;
|
||||
- (BOOL)isSeparatorItem;
|
||||
|
||||
- (void)setKeyEquivalent:(NSString *)aKeyEquivalent;
|
||||
- (NSString *)keyEquivalent;
|
||||
- (void)setKeyEquivalentModifierMask:(unsigned int)mask;
|
||||
- (unsigned int)keyEquivalentModifierMask;
|
||||
|
||||
- (NSString *)userKeyEquivalent;
|
||||
|
||||
- (void)setMnemonicLocation:(unsigned) location;
|
||||
- (unsigned)mnemonicLocation;
|
||||
- (NSString *)mnemonic;
|
||||
- (void)setTitleWithMnemonic:(NSString *)stringWithAmpersand;
|
||||
|
||||
- (void)setImage:(NSImage *)menuImage;
|
||||
- (NSImage *)image;
|
||||
|
||||
- (void)setState:(int)state;
|
||||
- (int)state;
|
||||
- (void)setOnStateImage:(NSImage *)image;
|
||||
- (NSImage *)onStateImage;
|
||||
- (void)setOffStateImage:(NSImage *)image;
|
||||
- (NSImage *)offStateImage;
|
||||
- (void)setMixedStateImage:(NSImage *)image;
|
||||
- (NSImage *)mixedStateImage;
|
||||
|
||||
- (void)setEnabled:(BOOL)flag;
|
||||
- (BOOL)isEnabled;
|
||||
|
||||
- (void)setTarget:(id)anObject;
|
||||
- (id)target;
|
||||
- (void)setAction:(SEL)aSelector;
|
||||
- (SEL)action;
|
||||
|
||||
- (void)setTag:(int)anInt;
|
||||
- (int)tag;
|
||||
|
||||
- (void)setRepresentedObject:(id)anObject;
|
||||
- (id)representedObject;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSMenuItem (GNUstepExtra)
|
||||
|
||||
- (void)setChangesState:(BOOL)flag;
|
||||
- (BOOL)changesState;
|
||||
|
||||
@end
|
||||
|
||||
/* Private stuff; it should be in a private header file but it really doesn't
|
||||
worth the effort. */
|
||||
|
|
|
@ -31,46 +31,45 @@
|
|||
#include <AppKit/NSButtonCell.h>
|
||||
#include <AppKit/NSMenuItem.h>
|
||||
|
||||
@interface NSMenuItemCell : NSButtonCell <NSMenuItem>
|
||||
@class NSMenuView;
|
||||
|
||||
typedef void (*DrawingIMP)(id, SEL, NSRect, NSView*);
|
||||
|
||||
@interface NSMenuItemCell : NSButtonCell <NSCopying, NSCoding>
|
||||
{
|
||||
id representedObject;
|
||||
BOOL mcell_highlighted;
|
||||
BOOL mcell_has_submenu;
|
||||
|
||||
// Not used is GS.
|
||||
NSMenuItem *mcell_item;
|
||||
NSMenuView *mcell_menuView;
|
||||
|
||||
// Cache
|
||||
BOOL mcell_needs_sizing;
|
||||
float mcell_imageWidth;
|
||||
float mcell_titleWidth;
|
||||
float mcell_keyEqWidth;
|
||||
float mcell_stateImgWidth;
|
||||
float mcell_keyEquivalentWidth;
|
||||
float mcell_stateImageWidth;
|
||||
float mcell_menuItemHeight;
|
||||
|
||||
NSImage *mcell_imageToDisplay;
|
||||
NSString *mcell_titleToDisplay;
|
||||
NSSize mcell_imageSize;
|
||||
|
||||
@private
|
||||
DrawingIMP _drawMethods[4];
|
||||
}
|
||||
|
||||
// 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)highlight:(BOOL)flag
|
||||
withFrame:(NSRect)cellFrame
|
||||
inView:(NSView*)controlView;
|
||||
|
||||
- (void)setMenuItem:(NSMenuItem *)item;
|
||||
- (NSMenuItem *)menuItem;
|
||||
|
||||
- (void)setMenuView:(NSMenuView *)menuView;
|
||||
- (NSMenuView *)menuView;
|
||||
|
||||
- (void)calcSize;
|
||||
- (void)setNeedsSizing:(BOOL)flag;
|
||||
- (BOOL)needsSizing;
|
||||
|
|
|
@ -35,23 +35,24 @@
|
|||
#include <Foundation/NSNotification.h>
|
||||
|
||||
#include <AppKit/NSMenu.h>
|
||||
#include <AppKit/NSMenuItem.h>
|
||||
#include <AppKit/NSMenuItemCell.h>
|
||||
#include <AppKit/NSScreen.h>
|
||||
#include <AppKit/NSView.h>
|
||||
#include <AppKit/NSWindow.h>
|
||||
|
||||
@class NSColor;
|
||||
@class NSPopUpButton;
|
||||
@class NSFont;
|
||||
|
||||
@interface NSMenuView : NSView
|
||||
@interface NSMenuView : NSView <NSCoding>
|
||||
{
|
||||
NSMenu *menuv_menu;
|
||||
NSMutableArray *menuv_itemCells;
|
||||
BOOL menuv_horizontal;
|
||||
NSFont *menuv_font;
|
||||
int menuv_highlightedItemIndex;
|
||||
BOOL menuv_isAttached;
|
||||
BOOL menuv_isTornOff;
|
||||
float menuv_hEdgePad;
|
||||
float menuv_horizontalEdgePad;
|
||||
float menuv_stateImageOffset;
|
||||
float menuv_stateImageWidth;
|
||||
float menuv_imageAndTitleOffset;
|
||||
|
@ -60,11 +61,12 @@
|
|||
float menuv_keyEqWidth;
|
||||
BOOL menuv_needsSizing;
|
||||
NSSize cellSize;
|
||||
float i_titleWidth;
|
||||
@private
|
||||
id menuv_popb;
|
||||
id menuv_items_link;
|
||||
BOOL menuv_keepAttachedMenus;
|
||||
int _oldHighlightedItemIndex;
|
||||
}
|
||||
|
||||
+ (float)menuBarHeight;
|
||||
|
||||
- (void)setMenu:(NSMenu *)menu;
|
||||
|
|
|
@ -44,9 +44,11 @@ common_ArrowUpH.tiff \
|
|||
common_ArrowRightH.tiff \
|
||||
common_3DArrowRightH.tiff \
|
||||
common_ArrowLeftH.tiff \
|
||||
common_2DCheckMark.tiff \
|
||||
common_Close.tiff \
|
||||
common_CloseH.tiff \
|
||||
common_CloseBroken.tiff \
|
||||
common_2DDash.tiff \
|
||||
common_Home.tiff \
|
||||
common_Mount.tiff \
|
||||
common_Unmount.tiff \
|
||||
|
|
BIN
Images/common_2DCheckMark.tiff
Normal file
BIN
Images/common_2DCheckMark.tiff
Normal file
Binary file not shown.
BIN
Images/common_2DDash.tiff
Normal file
BIN
Images/common_2DDash.tiff
Normal file
Binary file not shown.
1092
Source/NSMenu.m
1092
Source/NSMenu.m
File diff suppressed because it is too large
Load diff
|
@ -5,6 +5,9 @@
|
|||
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Author: David Lazaro Saz <khelekir@encomix.es>
|
||||
Date: Sep 1999
|
||||
|
||||
Author: Ovidiu Predescu <ovidiu@net-community.com>
|
||||
Date: May 1997
|
||||
|
||||
|
@ -33,7 +36,9 @@
|
|||
#include <AppKit/NSMenuItem.h>
|
||||
#include <AppKit/NSMenu.h>
|
||||
|
||||
static BOOL usesUserKeyEquivalents = YES;
|
||||
static BOOL usesUserKeyEquivalents = NO;
|
||||
|
||||
static Class imageClass;
|
||||
|
||||
@implementation NSMenuItem
|
||||
|
||||
|
@ -43,6 +48,7 @@ static BOOL usesUserKeyEquivalents = YES;
|
|||
{
|
||||
// Initial version
|
||||
[self setVersion:2];
|
||||
imageClass = [NSImage class];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,63 +62,129 @@ static BOOL usesUserKeyEquivalents = YES;
|
|||
return usesUserKeyEquivalents;
|
||||
}
|
||||
|
||||
+ (id <NSMenuItem>)separatorItem
|
||||
{
|
||||
// FIXME: implementation needed (Lazaro).
|
||||
return nil;
|
||||
}
|
||||
|
||||
- init
|
||||
{
|
||||
[self setAlignment:NSLeftTextAlignment];
|
||||
mi_hasSubmenu = NO;
|
||||
mi_target = nil;
|
||||
mi_menu = nil;
|
||||
mi_mnemonicLocation = 255; // No mnemonic
|
||||
mi_image = nil;
|
||||
mi_onStateImage = nil;
|
||||
mi_offStateImage = nil;
|
||||
mi_mixedStateImage = nil;
|
||||
mi_enabled = YES;
|
||||
mi_state = NSOffState;
|
||||
mi_changesState = NO;
|
||||
[super init];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
- (void) dealloc
|
||||
{
|
||||
NSDebugLog (@"NSMenuItem '%@' dealloc", [self title]);
|
||||
|
||||
[representedObject release];
|
||||
if (hasSubmenu)
|
||||
[target release];
|
||||
TEST_RELEASE(mi_title);
|
||||
TEST_RELEASE(mi_keyEquivalent);
|
||||
TEST_RELEASE(mi_image);
|
||||
TEST_RELEASE(mi_onStateImage);
|
||||
TEST_RELEASE(mi_offStateImage);
|
||||
TEST_RELEASE(mi_mixedStateImage);
|
||||
TEST_RELEASE(mi_representedObject);
|
||||
if (mi_hasSubmenu)
|
||||
[mi_submenu release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
- (id)initWithTitle:(NSString *)aString
|
||||
action:(SEL)aSelector
|
||||
keyEquivalent:(NSString *)charCode
|
||||
{
|
||||
NSMenuItem *copy = [super copyWithZone: zone];
|
||||
|
||||
NSDebugLog (@"menu item '%@' copy", [self title]);
|
||||
copy->representedObject = [representedObject retain];
|
||||
copy->hasSubmenu = hasSubmenu;
|
||||
if (hasSubmenu)
|
||||
{
|
||||
// recursive call
|
||||
id submenu = [target copyWithZone: zone];
|
||||
copy->target = submenu;
|
||||
}
|
||||
|
||||
return copy;
|
||||
[self init];
|
||||
[self setTitle: aString];
|
||||
mi_action = aSelector;
|
||||
[self setKeyEquivalent: charCode];
|
||||
// Set the images according to the spec. On: check mark; off: dash.
|
||||
[self setOnStateImage: [NSImage imageNamed:@"common_2DCheckMark"]];
|
||||
[self setMixedStateImage: [NSImage imageNamed:@"common_2DDash"]];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setTarget:(id)anObject
|
||||
- (void)setMenu:(NSMenu *)menu
|
||||
{
|
||||
BOOL hadSubmenu = hasSubmenu;
|
||||
hasSubmenu = anObject && [anObject isKindOfClass:[NSMenu class]];
|
||||
if (hasSubmenu)
|
||||
[anObject retain];
|
||||
if (hadSubmenu)
|
||||
[target release];
|
||||
[super setTarget:anObject];
|
||||
mi_menu = menu;
|
||||
}
|
||||
|
||||
- (void)setTitle:(NSString*)aString
|
||||
- (NSMenu *)menu
|
||||
{
|
||||
[super setStringValue:aString];
|
||||
}
|
||||
|
||||
- (NSString*)title
|
||||
{
|
||||
return [self stringValue];
|
||||
return mi_menu;
|
||||
}
|
||||
|
||||
- (BOOL)hasSubmenu
|
||||
{
|
||||
return hasSubmenu;
|
||||
return mi_hasSubmenu;
|
||||
}
|
||||
|
||||
- (void)setSubmenu:(NSMenu *)submenu
|
||||
{
|
||||
if ([submenu supermenu] != nil)
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"submenu already has supermenu: "];
|
||||
mi_submenu = submenu;
|
||||
if (mi_submenu == nil)
|
||||
mi_hasSubmenu = NO;
|
||||
else
|
||||
mi_hasSubmenu = YES;
|
||||
}
|
||||
|
||||
- (NSMenu *)submenu
|
||||
{
|
||||
return mi_submenu;
|
||||
}
|
||||
|
||||
- (void)setTitle:(NSString*)aString
|
||||
{
|
||||
NSString *_string;
|
||||
|
||||
if (!aString)
|
||||
_string = @"";
|
||||
else
|
||||
_string = [aString copy];
|
||||
|
||||
if (mi_title)
|
||||
RELEASE(mi_title);
|
||||
mi_title = _string;
|
||||
}
|
||||
|
||||
- (NSString*)title
|
||||
{
|
||||
return mi_title;
|
||||
}
|
||||
|
||||
- (BOOL)isSeparatorItem
|
||||
{
|
||||
// FIXME: This stuff only makes sense in MacOS or Windows alike
|
||||
// interface styles. Maybe someone wants to implement this (Lazaro).
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setKeyEquivalent:(NSString *)aKeyEquivalent
|
||||
{
|
||||
NSString *_string;
|
||||
|
||||
if (!aKeyEquivalent)
|
||||
_string = @"";
|
||||
else
|
||||
_string = [aKeyEquivalent copy];
|
||||
|
||||
if (mi_keyEquivalent)
|
||||
RELEASE(mi_keyEquivalent);
|
||||
mi_keyEquivalent = _string;
|
||||
}
|
||||
|
||||
- (NSString*)keyEquivalent
|
||||
|
@ -120,7 +192,17 @@ static BOOL usesUserKeyEquivalents = YES;
|
|||
if (usesUserKeyEquivalents)
|
||||
return [self userKeyEquivalent];
|
||||
else
|
||||
return [super keyEquivalent];
|
||||
return mi_keyEquivalent;
|
||||
}
|
||||
|
||||
- (void)setKeyEquivalentModifierMask:(unsigned int)mask
|
||||
{
|
||||
mi_keyEquivalentModifierMask = mask;
|
||||
}
|
||||
|
||||
- (unsigned int)keyEquivalentModifierMask
|
||||
{
|
||||
return mi_keyEquivalentModifierMask;
|
||||
}
|
||||
|
||||
- (NSString*)userKeyEquivalent
|
||||
|
@ -128,22 +210,260 @@ static BOOL usesUserKeyEquivalents = YES;
|
|||
NSString* userKeyEquivalent = [[[[NSUserDefaults standardUserDefaults]
|
||||
persistentDomainForName:NSGlobalDomain]
|
||||
objectForKey:@"NSCommandKeys"]
|
||||
objectForKey:[self stringValue]];
|
||||
objectForKey:mi_title];
|
||||
|
||||
if (!userKeyEquivalent)
|
||||
userKeyEquivalent = [super keyEquivalent];
|
||||
userKeyEquivalent = @"";
|
||||
|
||||
return userKeyEquivalent;
|
||||
}
|
||||
|
||||
- (void)setMnemonicLocation:(unsigned)location
|
||||
{
|
||||
mi_mnemonicLocation = location;
|
||||
}
|
||||
|
||||
- (unsigned)mnemonicLocation
|
||||
{
|
||||
if (mi_mnemonicLocation != 255)
|
||||
return mi_mnemonicLocation;
|
||||
else
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
- (NSString *)mnemonic
|
||||
{
|
||||
if (mi_mnemonicLocation != 255)
|
||||
return [[mi_title substringFromIndex: mi_mnemonicLocation]
|
||||
substringToIndex: 1];
|
||||
else
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (void)setTitleWithMnemonic:(NSString *)stringWithAmpersand
|
||||
{
|
||||
// FIXME: Do something more than copy the string. Anyway this will only
|
||||
// sense in Windows, so... (Lazaro).
|
||||
NSString *_string;
|
||||
|
||||
if (!stringWithAmpersand)
|
||||
_string = @"";
|
||||
else
|
||||
_string = [stringWithAmpersand copy];
|
||||
|
||||
if (mi_title)
|
||||
RELEASE(mi_title);
|
||||
mi_title = _string;
|
||||
}
|
||||
|
||||
- (void)setImage:(NSImage *)image
|
||||
{
|
||||
NSAssert(image == nil || [image isKindOfClass: imageClass],
|
||||
NSInvalidArgumentException);
|
||||
|
||||
ASSIGN(mi_image, image);
|
||||
}
|
||||
|
||||
- (NSImage *)image
|
||||
{
|
||||
return mi_image;
|
||||
}
|
||||
|
||||
- (void)setState:(int)state
|
||||
{
|
||||
mi_state = state;
|
||||
mi_changesState = YES;
|
||||
}
|
||||
|
||||
- (int)state
|
||||
{
|
||||
return mi_state;
|
||||
}
|
||||
|
||||
- (void)setOnStateImage:(NSImage *)image
|
||||
{
|
||||
NSAssert(image == nil || [image isKindOfClass: imageClass],
|
||||
NSInvalidArgumentException);
|
||||
|
||||
ASSIGN(mi_onStateImage, image);
|
||||
}
|
||||
|
||||
- (NSImage *)onStateImage
|
||||
{
|
||||
return mi_onStateImage;
|
||||
}
|
||||
|
||||
- (void)setOffStateImage:(NSImage *)image
|
||||
{
|
||||
NSAssert(image == nil || [image isKindOfClass: imageClass],
|
||||
NSInvalidArgumentException);
|
||||
|
||||
ASSIGN(mi_offStateImage, image);
|
||||
}
|
||||
|
||||
- (NSImage *)offStateImage
|
||||
{
|
||||
return mi_offStateImage;
|
||||
}
|
||||
|
||||
- (void)setMixedStateImage:(NSImage *)image
|
||||
{
|
||||
NSAssert(image == nil || [image isKindOfClass: imageClass],
|
||||
NSInvalidArgumentException);
|
||||
|
||||
ASSIGN(mi_mixedStateImage, image);
|
||||
}
|
||||
|
||||
- (NSImage *)mixedStateImage
|
||||
{
|
||||
return mi_mixedStateImage;
|
||||
}
|
||||
|
||||
- (void)setEnabled:(BOOL)flag
|
||||
{
|
||||
mi_enabled = flag;
|
||||
}
|
||||
|
||||
- (BOOL)isEnabled
|
||||
{
|
||||
return mi_enabled;
|
||||
}
|
||||
|
||||
- (void)setTarget:(id)anObject
|
||||
{
|
||||
mi_target = anObject;
|
||||
}
|
||||
|
||||
- (id)target
|
||||
{
|
||||
return mi_target;
|
||||
}
|
||||
|
||||
- (void)setAction:(SEL)aSelector
|
||||
{
|
||||
mi_action = aSelector;
|
||||
}
|
||||
|
||||
- (SEL)action
|
||||
{
|
||||
return mi_action;
|
||||
}
|
||||
|
||||
- (void)setTag:(int)anInt
|
||||
{
|
||||
mi_tag = anInt;
|
||||
}
|
||||
|
||||
- (int)tag
|
||||
{
|
||||
return mi_tag;
|
||||
}
|
||||
|
||||
- (void)setRepresentedObject:(id)anObject
|
||||
{
|
||||
ASSIGN(representedObject, anObject);
|
||||
ASSIGN(mi_representedObject, anObject);
|
||||
}
|
||||
|
||||
- (id)representedObject
|
||||
{
|
||||
return representedObject;
|
||||
return mi_representedObject;
|
||||
}
|
||||
|
||||
//
|
||||
// NSCopying protocol
|
||||
//
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
NSMenuItem *copy = [[isa allocWithZone: zone] init];
|
||||
|
||||
NSDebugLog (@"menu item '%@' copy", [self title]);
|
||||
copy->mi_menu = mi_menu;
|
||||
copy->mi_title = [mi_title copyWithZone: zone];
|
||||
copy->mi_keyEquivalent = [mi_keyEquivalent copyWithZone: zone];
|
||||
copy->mi_keyEquivalentModifierMask = mi_keyEquivalentModifierMask;
|
||||
copy->mi_mnemonicLocation = mi_mnemonicLocation;
|
||||
copy->mi_state = mi_state;
|
||||
copy->mi_enabled = mi_enabled;
|
||||
ASSIGN(copy->mi_image, mi_image);
|
||||
ASSIGN(copy->mi_onStateImage, mi_onStateImage);
|
||||
ASSIGN(copy->mi_offStateImage, mi_offStateImage);
|
||||
ASSIGN(copy->mi_mixedStateImage, mi_mixedStateImage);
|
||||
copy->mi_changesState = mi_changesState;
|
||||
copy->mi_target = mi_target;
|
||||
copy->mi_action = mi_action;
|
||||
copy->mi_tag = mi_tag;
|
||||
copy->mi_representedObject = [mi_representedObject retain];
|
||||
copy->mi_hasSubmenu = mi_hasSubmenu;
|
||||
copy->mi_submenu = mi_submenu;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
//
|
||||
// NSCoding protocol
|
||||
//
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
[aCoder encodeConditionalObject: mi_menu];
|
||||
[aCoder encodeObject: mi_title];
|
||||
[aCoder encodeObject: mi_keyEquivalent];
|
||||
[aCoder encodeValueOfObjCType: "I" at: &mi_keyEquivalentModifierMask];
|
||||
[aCoder encodeValueOfObjCType: "I" at: &mi_mnemonicLocation];
|
||||
[aCoder encodeValueOfObjCType: "i" at: &mi_state];
|
||||
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &mi_enabled];
|
||||
[aCoder encodeConditionalObject: mi_image];
|
||||
[aCoder encodeConditionalObject: mi_onStateImage];
|
||||
[aCoder encodeConditionalObject: mi_offStateImage];
|
||||
[aCoder encodeConditionalObject: mi_mixedStateImage];
|
||||
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &mi_changesState];
|
||||
[aCoder encodeConditionalObject: mi_target];
|
||||
[aCoder encodeValueOfObjCType: @encode(SEL) at: &mi_action];
|
||||
[aCoder encodeValueOfObjCType: "i" at: &mi_tag];
|
||||
[aCoder encodeConditionalObject: mi_representedObject];
|
||||
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &mi_hasSubmenu];
|
||||
[aCoder encodeConditionalObject: mi_submenu];
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)aDecoder
|
||||
{
|
||||
mi_menu = [aDecoder decodeObject];
|
||||
[aDecoder decodeValueOfObjCType: @encode(id) at: &mi_title];
|
||||
[aDecoder decodeValueOfObjCType: @encode(id) at: &mi_keyEquivalent];
|
||||
[aDecoder decodeValueOfObjCType: "I" at: &mi_keyEquivalentModifierMask];
|
||||
[aDecoder decodeValueOfObjCType: "I" at: &mi_mnemonicLocation];
|
||||
[aDecoder decodeValueOfObjCType: "i" at: &mi_state];
|
||||
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &mi_enabled];
|
||||
mi_image = [aDecoder decodeObject];
|
||||
mi_onStateImage = [aDecoder decodeObject];
|
||||
mi_offStateImage = [aDecoder decodeObject];
|
||||
mi_mixedStateImage = [aDecoder decodeObject];
|
||||
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &mi_changesState];
|
||||
mi_target = [aDecoder decodeObject];
|
||||
[aDecoder decodeValueOfObjCType: @encode(SEL) at: &mi_action];
|
||||
[aDecoder decodeValueOfObjCType: "i" at: &mi_tag];
|
||||
mi_representedObject = [aDecoder decodeObject];
|
||||
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &mi_hasSubmenu];
|
||||
mi_submenu = [aDecoder decodeObject];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSMenuItem (GNUstepExtra)
|
||||
|
||||
// This methods support the special arranging in columns of menu
|
||||
// items in GNUstep. There's no need to use them outside but if
|
||||
// they are used the display is more pleasant.
|
||||
|
||||
- (void) setChangesState: (BOOL)flag
|
||||
{
|
||||
mi_changesState = flag;
|
||||
}
|
||||
|
||||
- (BOOL) changesState
|
||||
{
|
||||
return mi_changesState;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -43,11 +43,10 @@
|
|||
#include <AppKit/NSMenuItemCell.h>
|
||||
|
||||
#include <AppKit/PSOperators.h>
|
||||
|
||||
static BOOL usesUserKeyEquivalents = YES;
|
||||
|
||||
@implementation NSMenuItemCell
|
||||
+ (void)initialize
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSMenuItemCell class])
|
||||
{
|
||||
|
@ -56,113 +55,156 @@ static BOOL usesUserKeyEquivalents = YES;
|
|||
}
|
||||
}
|
||||
|
||||
- (id)init
|
||||
- (id) init
|
||||
{
|
||||
mcell_has_submenu = NO;
|
||||
[super init];
|
||||
[super setTarget:nil];
|
||||
[self setTarget:nil];
|
||||
[self setHighlightsBy: NSChangeBackgroundCellMask];
|
||||
[self setShowsStateBy: NSNoCellMask];
|
||||
[self setImagePosition: NSNoImage];
|
||||
[self setAlignment: NSLeftTextAlignment];
|
||||
|
||||
_drawMethods[0] = (DrawingIMP)
|
||||
[self methodForSelector:@selector(drawStateImageWithFrame:inView:)];
|
||||
_drawMethods[1] = (DrawingIMP)
|
||||
[self methodForSelector:@selector(drawImageWithFrame:inView:)];
|
||||
_drawMethods[2] = (DrawingIMP)
|
||||
[self methodForSelector:@selector(drawTitleWithFrame:inView:)];
|
||||
_drawMethods[3] = (DrawingIMP)
|
||||
[self methodForSelector:@selector(drawKeyEquivalentWithFrame:inView:)];
|
||||
|
||||
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
|
||||
- (void) setHighlighted:(BOOL)flag
|
||||
{
|
||||
mcell_highlighted = flag;
|
||||
}
|
||||
|
||||
- (BOOL)isHighlighted
|
||||
- (BOOL) isHighlighted
|
||||
{
|
||||
return mcell_highlighted;
|
||||
}
|
||||
|
||||
- (void)setMenuItem:(NSMenuItem *)item
|
||||
- (void) highlight: (BOOL)flag
|
||||
withFrame: (NSRect)cellFrame
|
||||
inView: (NSView*)controlView
|
||||
{
|
||||
if (mcell_highlighted != flag)
|
||||
{
|
||||
mcell_highlighted = flag;
|
||||
[self drawInteriorWithFrame: cellFrame inView: controlView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setMenuItem:(NSMenuItem *)item
|
||||
{
|
||||
ASSIGN(mcell_item, item);
|
||||
}
|
||||
|
||||
- (NSMenuItem *)menuItem
|
||||
- (NSMenuItem *) menuItem
|
||||
{
|
||||
return mcell_item;
|
||||
}
|
||||
|
||||
- (void)calcSize
|
||||
- (void) setMenuView:(NSMenuView *)menuView
|
||||
{
|
||||
//calc sizes of images, title, and cache.
|
||||
ASSIGN(mcell_menuView, menuView);
|
||||
}
|
||||
|
||||
- (NSMenuView *) menuView
|
||||
{
|
||||
return mcell_menuView;
|
||||
}
|
||||
|
||||
- (void) calcSize
|
||||
{
|
||||
NSSize componentSize;
|
||||
NSImage *anImage = nil;
|
||||
float neededMenuItemHeight = 20;
|
||||
NSFont *aFont;
|
||||
|
||||
// State Image
|
||||
if ([mcell_item changesState])
|
||||
{
|
||||
// NSOnState
|
||||
componentSize = [[mcell_item onStateImage] size];
|
||||
mcell_stateImageWidth = componentSize.width;
|
||||
if (componentSize.height > neededMenuItemHeight)
|
||||
neededMenuItemHeight = componentSize.height;
|
||||
|
||||
// NSOffState
|
||||
componentSize = [[mcell_item offStateImage] size];
|
||||
if (componentSize.width > mcell_stateImageWidth)
|
||||
mcell_stateImageWidth = componentSize.width;
|
||||
if (componentSize.height > neededMenuItemHeight)
|
||||
neededMenuItemHeight = componentSize.height;
|
||||
|
||||
// NSMixedState
|
||||
componentSize = [[mcell_item mixedStateImage] size];
|
||||
if (componentSize.width > mcell_stateImageWidth)
|
||||
mcell_stateImageWidth = componentSize.width;
|
||||
if (componentSize.height > neededMenuItemHeight)
|
||||
neededMenuItemHeight = componentSize.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
mcell_stateImageWidth = 0.0;
|
||||
}
|
||||
|
||||
// Image
|
||||
if ((anImage = [mcell_item image]))
|
||||
[self setImagePosition: NSImageLeft];
|
||||
componentSize = [anImage size];
|
||||
mcell_imageWidth = componentSize.width;
|
||||
if (componentSize.height > neededMenuItemHeight)
|
||||
neededMenuItemHeight = componentSize.height;
|
||||
|
||||
// Title and Key Equivalent
|
||||
// FIXME: Calculate height (Lazaro).
|
||||
aFont = [self font];
|
||||
if (aFont)
|
||||
{
|
||||
mcell_titleWidth = [aFont widthOfString:[mcell_item title]];
|
||||
mcell_keyEquivalentWidth =
|
||||
[aFont widthOfString:[mcell_item keyEquivalent]];
|
||||
}
|
||||
else
|
||||
{
|
||||
mcell_titleWidth = [[NSFont menuFontOfSize:12]
|
||||
widthOfString:[mcell_item title]];
|
||||
mcell_keyEquivalentWidth = [[NSFont menuFontOfSize:12]
|
||||
widthOfString:[mcell_item keyEquivalent]];
|
||||
}
|
||||
|
||||
// Submenu Arrow
|
||||
if ([mcell_item hasSubmenu])
|
||||
{
|
||||
componentSize = [[NSImage imageNamed:@"common_3DArrowRight"] size];
|
||||
mcell_keyEquivalentWidth = componentSize.width;
|
||||
if (componentSize.height > neededMenuItemHeight)
|
||||
neededMenuItemHeight = componentSize.height;
|
||||
}
|
||||
|
||||
// Cache definitive height
|
||||
mcell_menuItemHeight = neededMenuItemHeight;
|
||||
|
||||
// At the end we set sizing to NO.
|
||||
mcell_needs_sizing = NO;
|
||||
}
|
||||
|
||||
- (void)setNeedsSizing:(BOOL)flag
|
||||
- (void) setNeedsSizing:(BOOL)flag
|
||||
{
|
||||
mcell_needs_sizing = flag;
|
||||
}
|
||||
|
||||
- (BOOL)needsSizing
|
||||
- (BOOL) needsSizing
|
||||
{
|
||||
return mcell_needs_sizing;
|
||||
}
|
||||
|
||||
- (float)imageWidth
|
||||
- (float) imageWidth
|
||||
{
|
||||
if (mcell_needs_sizing)
|
||||
[self calcSize];
|
||||
|
@ -170,164 +212,424 @@ static BOOL usesUserKeyEquivalents = YES;
|
|||
return mcell_imageWidth;
|
||||
}
|
||||
|
||||
- (float)titleWidth
|
||||
- (float) titleWidth
|
||||
{
|
||||
if (mcell_needs_sizing)
|
||||
[self calcSize];
|
||||
|
||||
// return mcell_titleWidth;
|
||||
return [[NSFont systemFontOfSize:12] widthOfString:[self title]];
|
||||
return mcell_titleWidth;
|
||||
}
|
||||
|
||||
- (float)keyEquivalentWidth
|
||||
- (float) keyEquivalentWidth
|
||||
{
|
||||
if (mcell_needs_sizing)
|
||||
[self calcSize];
|
||||
|
||||
return mcell_keyEqWidth;
|
||||
return mcell_keyEquivalentWidth;
|
||||
}
|
||||
|
||||
- (float)stateImageWidth
|
||||
- (float) stateImageWidth
|
||||
{
|
||||
if (mcell_needs_sizing)
|
||||
[self calcSize];
|
||||
|
||||
return mcell_stateImgWidth;
|
||||
return mcell_stateImageWidth;
|
||||
}
|
||||
|
||||
//
|
||||
// Sizes for drawing taking into account NSMenuView adjustments.
|
||||
//
|
||||
- (NSRect) imageRectForBounds:(NSRect)cellFrame
|
||||
{
|
||||
// Calculate the image part of cell frame from NSMenuView
|
||||
cellFrame.origin.x += [mcell_menuView imageAndTitleOffset];
|
||||
cellFrame.size.width = [mcell_menuView imageAndTitleWidth];
|
||||
if ([mcell_item changesState])
|
||||
cellFrame.origin.x += [mcell_menuView stateImageWidth]
|
||||
+ 2 * [mcell_menuView horizontalEdgePadding];
|
||||
|
||||
switch ([self imagePosition])
|
||||
{
|
||||
case NSNoImage:
|
||||
cellFrame = NSZeroRect;
|
||||
break;
|
||||
|
||||
case NSImageOnly:
|
||||
case NSImageOverlaps:
|
||||
break;
|
||||
|
||||
case NSImageLeft:
|
||||
cellFrame.size.width = mcell_imageWidth;
|
||||
break;
|
||||
|
||||
case NSImageRight:
|
||||
cellFrame.origin.x += mcell_titleWidth + xDist;
|
||||
cellFrame.size.width = mcell_imageWidth;
|
||||
break;
|
||||
|
||||
case NSImageBelow:
|
||||
cellFrame.size.height /= 2;
|
||||
break;
|
||||
|
||||
case NSImageAbove:
|
||||
cellFrame.size.height /= 2;
|
||||
cellFrame.origin.y += cellFrame.size.height;
|
||||
break;
|
||||
}
|
||||
|
||||
return cellFrame;
|
||||
}
|
||||
|
||||
- (NSRect) keyEquivalentRectForBounds:(NSRect)cellFrame
|
||||
{
|
||||
// Calculate the image part of cell frame from NSMenuView
|
||||
cellFrame.origin.x += [mcell_menuView keyEquivalentOffset];
|
||||
cellFrame.size.width = [mcell_menuView keyEquivalentWidth];
|
||||
|
||||
return cellFrame;
|
||||
}
|
||||
|
||||
- (NSRect) stateImageRectForBounds:(NSRect)cellFrame
|
||||
{
|
||||
// Calculate the image part of cell frame from NSMenuView
|
||||
cellFrame.origin.x += [mcell_menuView stateImageOffset];
|
||||
cellFrame.size.width = [mcell_menuView stateImageWidth];
|
||||
|
||||
return cellFrame;
|
||||
}
|
||||
|
||||
- (NSRect) titleRectForBounds:(NSRect)cellFrame
|
||||
{
|
||||
// Calculate the image part of cell frame from NSMenuView
|
||||
cellFrame.origin.x += [mcell_menuView imageAndTitleOffset];
|
||||
cellFrame.size.width = [mcell_menuView imageAndTitleWidth];
|
||||
if ([mcell_item changesState])
|
||||
cellFrame.origin.x += [mcell_menuView stateImageWidth]
|
||||
+ 2 * [mcell_menuView horizontalEdgePadding];
|
||||
|
||||
switch ([self imagePosition])
|
||||
{
|
||||
case NSNoImage:
|
||||
case NSImageOverlaps:
|
||||
break;
|
||||
|
||||
case NSImageOnly:
|
||||
cellFrame = NSZeroRect;
|
||||
break;
|
||||
|
||||
case NSImageLeft:
|
||||
cellFrame.origin.x += mcell_imageWidth + xDist;
|
||||
cellFrame.size.width = mcell_titleWidth;
|
||||
break;
|
||||
|
||||
case NSImageRight:
|
||||
cellFrame.size.width = mcell_titleWidth;
|
||||
break;
|
||||
|
||||
case NSImageBelow:
|
||||
cellFrame.size.height /= 2;
|
||||
cellFrame.origin.y += cellFrame.size.height;
|
||||
break;
|
||||
|
||||
case NSImageAbove:
|
||||
cellFrame.size.height /= 2;
|
||||
break;
|
||||
}
|
||||
|
||||
return cellFrame;
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
//
|
||||
- (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;
|
||||
NSRect floodRect = cellFrame;
|
||||
NSString *keyQ = nil;
|
||||
NSColor *backColor;
|
||||
|
||||
[controlView lockFocus];
|
||||
ctxt = GSCurrentContext();
|
||||
NSDrawButton(cellFrame, cellFrame);
|
||||
|
||||
floodRect.origin.x += 1;
|
||||
floodRect.origin.y += 2;
|
||||
floodRect.size.height -= 3;
|
||||
floodRect.size.width -= 2;
|
||||
|
||||
if (cell_highlighted)
|
||||
if ([self isHighlighted] && ([self highlightsBy] & NSPushInCellMask))
|
||||
{
|
||||
backColor = [NSColor selectedMenuItemColor];
|
||||
NSDrawGrayBezel(cellFrame, NSZeroRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
backColor = [NSColor controlColor];
|
||||
NSDrawButton(cellFrame, NSZeroRect);
|
||||
}
|
||||
[backColor set];
|
||||
NSRectFill(floodRect);
|
||||
}
|
||||
|
||||
if ([self isEnabled])
|
||||
- (void) drawImageWithFrame:(NSRect)cellFrame
|
||||
inView:(NSView *)controlView
|
||||
{
|
||||
NSSize size;
|
||||
NSPoint position;
|
||||
|
||||
cellFrame = [self imageRectForBounds: cellFrame];
|
||||
size = [mcell_imageToDisplay size];
|
||||
position.x = MAX(NSMidX(cellFrame) - (size.width/2.), 0.);
|
||||
position.y = MAX(NSMidY(cellFrame) - (size.height/2.), 0.);
|
||||
/*
|
||||
* Images are always drawn with their bottom-left corner at the origin
|
||||
* so we must adjust the position to take account of a flipped view.
|
||||
*/
|
||||
if ([control_view isFlipped])
|
||||
position.y += size.height;
|
||||
[mcell_imageToDisplay compositeToPoint: position operation: NSCompositeCopy];
|
||||
}
|
||||
|
||||
- (void) drawKeyEquivalentWithFrame:(NSRect)cellFrame
|
||||
inView:(NSView *)controlView
|
||||
{
|
||||
cellFrame = [self keyEquivalentRectForBounds: cellFrame];
|
||||
|
||||
if ([mcell_item hasSubmenu])
|
||||
{
|
||||
if (cell_highlighted)
|
||||
{
|
||||
[[NSColor selectedMenuItemTextColor] set];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[NSColor controlTextColor] set];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[[NSColor disabledControlTextColor] set];
|
||||
}
|
||||
NSSize size;
|
||||
NSPoint position;
|
||||
NSImage *arrowImage = [NSImage imageNamed:@"common_3DArrowRight"];
|
||||
|
||||
[[NSFont systemFontOfSize:12] set];
|
||||
DPSmoveto(ctxt, cellFrame.origin.x + 5, cellFrame.origin.y + 6);
|
||||
DPSshow(ctxt, [[self title] cString]);
|
||||
|
||||
if (mcell_has_submenu)
|
||||
{
|
||||
NSSize size;
|
||||
NSPoint position;
|
||||
NSImage *im = [NSImage imageNamed:@"common_3DArrowRight"];
|
||||
|
||||
floodRect.origin.x = cellFrame.size.width - 12;
|
||||
floodRect.origin.y += 5;
|
||||
floodRect.size.height = 7;
|
||||
floodRect.size.width = 7;
|
||||
|
||||
[im setBackgroundColor: backColor];
|
||||
size = [im size];
|
||||
position.x = MAX(NSMidX(floodRect) - (size.width/2.),0.);
|
||||
position.y = MAX(NSMidY(floodRect) - (size.height/2.),0.);
|
||||
size = [arrowImage size];
|
||||
position.x = cellFrame.origin.x + cellFrame.size.width - size.width;
|
||||
position.y = MAX(NSMidY(cellFrame) - (size.height/2.), 0.);
|
||||
/*
|
||||
* Images are always drawn with their bottom-left corner at the origin
|
||||
* so we must adjust the position to take account of a flipped view.
|
||||
*/
|
||||
if ([control_view isFlipped])
|
||||
position.y += size.height;
|
||||
[im compositeToPoint: position operation: NSCompositeCopy];
|
||||
[arrowImage compositeToPoint: position operation: NSCompositeCopy];
|
||||
}
|
||||
else if (keyQ = [self keyEquivalent]) {
|
||||
floodRect.origin.x = cellFrame.size.width - 12;
|
||||
floodRect.origin.y += 5;
|
||||
floodRect.size.height = 7;
|
||||
floodRect.size.width = 7;
|
||||
else
|
||||
[self _drawText: [mcell_item keyEquivalent] inFrame: cellFrame];
|
||||
}
|
||||
|
||||
- (void) drawSeparatorItemWithFrame:(NSRect)cellFrame
|
||||
inView:(NSView *)controlView
|
||||
{
|
||||
// FIXME: This only has sense in MacOS or Windows interface styles.
|
||||
// Maybe somebody wants to support this (Lazaro).
|
||||
}
|
||||
|
||||
- (void) drawStateImageWithFrame:(NSRect)cellFrame
|
||||
inView:(NSView *)controlView
|
||||
{
|
||||
NSSize size;
|
||||
NSPoint position;
|
||||
NSImage *imageToDisplay;
|
||||
|
||||
cellFrame = [self stateImageRectForBounds: cellFrame];
|
||||
|
||||
switch ([mcell_item state])
|
||||
{
|
||||
case NSOnState:
|
||||
imageToDisplay = [mcell_item onStateImage];
|
||||
break;
|
||||
|
||||
case NSMixedState:
|
||||
imageToDisplay = [mcell_item mixedStateImage];
|
||||
break;
|
||||
|
||||
case NSOffState:
|
||||
default:
|
||||
imageToDisplay = [mcell_item offStateImage];
|
||||
break;
|
||||
}
|
||||
|
||||
size = [imageToDisplay size];
|
||||
position.x = MAX(NSMidX(cellFrame) - (size.width/2.),0.);
|
||||
position.y = MAX(NSMidY(cellFrame) - (size.height/2.),0.);
|
||||
/*
|
||||
* Images are always drawn with their bottom-left corner at the origin
|
||||
* so we must adjust the position to take account of a flipped view.
|
||||
*/
|
||||
if ([control_view isFlipped])
|
||||
position.y += size.height;
|
||||
[imageToDisplay compositeToPoint: position operation: NSCompositeCopy];
|
||||
}
|
||||
|
||||
- (void) drawTitleWithFrame:(NSRect)cellFrame
|
||||
inView:(NSView *)controlView
|
||||
{
|
||||
if ([mcell_item isEnabled])
|
||||
[self setEnabled: YES];
|
||||
else
|
||||
[self setEnabled: NO];
|
||||
|
||||
[self _drawText: [mcell_item title]
|
||||
inFrame: [self titleRectForBounds: cellFrame]];
|
||||
}
|
||||
|
||||
- (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
|
||||
{
|
||||
// Save last view drawn to
|
||||
[self setControlView: controlView];
|
||||
|
||||
// Transparent buttons never draw
|
||||
if ([self isTransparent])
|
||||
return;
|
||||
|
||||
// Do nothing if cell's frame rect is zero
|
||||
if (NSIsEmptyRect(cellFrame))
|
||||
return;
|
||||
|
||||
[controlView lockFocus];
|
||||
|
||||
// Draw the border if needed
|
||||
if ([self isBordered])
|
||||
[self drawBorderAndBackgroundWithFrame: cellFrame inView: controlView];
|
||||
|
||||
[self drawInteriorWithFrame: cellFrame inView: controlView];
|
||||
|
||||
[self _drawText:keyQ inFrame:floodRect];
|
||||
}
|
||||
[controlView unlockFocus];
|
||||
}
|
||||
|
||||
- (void) drawInteriorWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
|
||||
{
|
||||
BOOL showAlternate = NO;
|
||||
unsigned mask;
|
||||
NSColor *backgroundColor = nil;
|
||||
|
||||
// Transparent buttons never draw
|
||||
if ([self isTransparent])
|
||||
return;
|
||||
|
||||
cellFrame = [self drawingRectForBounds: cellFrame];
|
||||
|
||||
// Pushed in buttons contents are displaced to the bottom right 1px
|
||||
if ([self isBordered] && mcell_highlighted
|
||||
&& ([self highlightsBy] & NSPushInCellMask))
|
||||
PStranslate(1., [control_view isFlipped] ? 1. : -1.);
|
||||
|
||||
// Determine the background color
|
||||
if ([self state])
|
||||
{
|
||||
if ([self showsStateBy]
|
||||
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask) )
|
||||
backgroundColor = [NSColor selectedMenuItemColor];
|
||||
}
|
||||
|
||||
if (mcell_highlighted)
|
||||
{
|
||||
if ([self highlightsBy]
|
||||
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask) )
|
||||
backgroundColor = [NSColor selectedMenuItemColor];
|
||||
}
|
||||
|
||||
if (backgroundColor == nil)
|
||||
backgroundColor = [NSColor controlBackgroundColor];
|
||||
|
||||
// Set cell's background color
|
||||
[backgroundColor set];
|
||||
NSRectFill(cellFrame);
|
||||
|
||||
/*
|
||||
* Determine the image and the title that will be
|
||||
* displayed. If the NSContentsCellMask is set the
|
||||
* image and title are swapped only if state is 1 or
|
||||
* if highlighting is set (when a button is pushed it's
|
||||
* content is changed to the face of reversed state).
|
||||
* The results are saved in two ivars for use in other
|
||||
* drawing methods.
|
||||
*/
|
||||
if (mcell_highlighted)
|
||||
mask = [self highlightsBy];
|
||||
else
|
||||
mask = [self showsStateBy];
|
||||
if (mask & NSContentsCellMask)
|
||||
showAlternate = [self state];
|
||||
|
||||
if (mcell_highlighted || showAlternate)
|
||||
{
|
||||
mcell_imageToDisplay = [self alternateImage];
|
||||
if (!mcell_imageToDisplay)
|
||||
mcell_imageToDisplay = [mcell_item image];
|
||||
mcell_titleToDisplay = [self alternateTitle];
|
||||
if (mcell_titleToDisplay == nil || [mcell_titleToDisplay isEqual: @""])
|
||||
mcell_titleToDisplay = [mcell_item title];
|
||||
}
|
||||
else
|
||||
{
|
||||
mcell_imageToDisplay = [mcell_item image];
|
||||
mcell_titleToDisplay = [mcell_item title];
|
||||
}
|
||||
|
||||
if (mcell_imageToDisplay)
|
||||
{
|
||||
mcell_imageSize = [mcell_imageToDisplay size];
|
||||
[mcell_imageToDisplay setBackgroundColor: backgroundColor];
|
||||
}
|
||||
|
||||
// Draw the state image
|
||||
if (mcell_stateImageWidth > 0)
|
||||
_drawMethods[0](self, @selector(drawStateImageWithFrame:inView:),
|
||||
cellFrame, controlView);
|
||||
|
||||
// Draw the image
|
||||
if (mcell_imageWidth > 0)
|
||||
_drawMethods[1](self, @selector(drawImageWithFrame:inView:),
|
||||
cellFrame, controlView);
|
||||
|
||||
// Draw the title
|
||||
if (mcell_titleWidth > 0)
|
||||
_drawMethods[2](self, @selector(drawTitleWithFrame:inView:),
|
||||
cellFrame, controlView);
|
||||
|
||||
// Draw the key equivalent
|
||||
if (mcell_keyEquivalentWidth > 0)
|
||||
_drawMethods[3](self, @selector(drawKeyEquivalentWithFrame:inView:),
|
||||
cellFrame, controlView);
|
||||
}
|
||||
|
||||
//
|
||||
// NSCopying protocol
|
||||
//
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
NSMenuItemCell *c = [super copyWithZone: zone];
|
||||
|
||||
c->mcell_highlighted = mcell_highlighted;
|
||||
c->mcell_has_submenu = mcell_has_submenu;
|
||||
if (mcell_item)
|
||||
c->mcell_item = [mcell_item copyWithZone: zone];
|
||||
c->mcell_menuView = mcell_menuView;
|
||||
c->mcell_needs_sizing = mcell_needs_sizing;
|
||||
|
||||
memcpy(c->_drawMethods, _drawMethods, sizeof(DrawingIMP) * 4);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
//
|
||||
// NSCoding protocol
|
||||
//
|
||||
- (void) encodeWithCoder: (NSCoder*)aCoder
|
||||
{
|
||||
[super encodeWithCoder: aCoder];
|
||||
|
||||
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &mcell_highlighted];
|
||||
[aCoder encodeValueOfObjCType: @encode(BOOL) at: &mcell_has_submenu];
|
||||
[aCoder encodeConditionalObject: mcell_item];
|
||||
[aCoder encodeConditionalObject: mcell_menuView];
|
||||
}
|
||||
|
||||
- (id) initWithCoder: (NSCoder*)aDecoder
|
||||
{
|
||||
[super initWithCoder: aDecoder];
|
||||
|
||||
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &mcell_highlighted];
|
||||
[aDecoder decodeValueOfObjCType: @encode(BOOL) at: &mcell_has_submenu];
|
||||
mcell_item = [aDecoder decodeObject];
|
||||
mcell_menuView = [aDecoder decodeObject];
|
||||
|
||||
mcell_needs_sizing = YES;
|
||||
|
||||
_drawMethods[0] = (DrawingIMP)
|
||||
[self methodForSelector:@selector(drawStateImageWithFrame:inView:)];
|
||||
_drawMethods[1] = (DrawingIMP)
|
||||
[self methodForSelector:@selector(drawImageWithFrame:inView:)];
|
||||
_drawMethods[2] = (DrawingIMP)
|
||||
[self methodForSelector:@selector(drawTitleWithFrame:inView:)];
|
||||
_drawMethods[3] = (DrawingIMP)
|
||||
[self methodForSelector:@selector(drawKeyEquivalentWithFrame:inView:)];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue