If a menu item is bound to ':action', the corresponding NSMenuItem has that action set as its action message (instead of the default 'vimMenuItemAction:').

git-svn-id: http://macvim.googlecode.com/svn/trunk@73 96c4425d-ca35-0410-94e5-3396d5c13a8f
This commit is contained in:
Bjorn Winckler
2007-08-04 17:19:44 +00:00
parent 35d1d0be99
commit f57a0e3d61
4 changed files with 72 additions and 25 deletions
+2 -1
View File
@@ -73,7 +73,8 @@
atIndex:(int)index;
- (void)addMenuItemWithTag:(int)tag parent:(int)parentTag name:(char *)name
tip:(char *)tip icon:(char *)icon
keyEquivalent:(int)key modifiers:(int)mods atIndex:(int)index;
keyEquivalent:(int)key modifiers:(int)mods
action:(NSString *)action atIndex:(int)index;
- (void)removeMenuItemWithTag:(int)tag;
- (void)enableMenuItemWithTag:(int)tag state:(int)enabled;
- (void)showToolbar:(int)enable flags:(int)flags;
+5 -1
View File
@@ -569,7 +569,8 @@ static int specialKeyToNSKey(int key);
- (void)addMenuItemWithTag:(int)tag parent:(int)parentTag name:(char *)name
tip:(char *)tip icon:(char *)icon
keyEquivalent:(int)key modifiers:(int)mods atIndex:(int)index
keyEquivalent:(int)key modifiers:(int)mods
action:(NSString *)action atIndex:(int)index
{
//NSLog(@"addMenuItemWithTag:%d parent:%d name:%s tip:%s atIndex:%d", tag,
// parentTag, name, tip, index);
@@ -578,6 +579,7 @@ static int specialKeyToNSKey(int key);
int tiplen = tip ? strlen(tip) : 0;
int iconlen = icon ? strlen(icon) : 0;
int eventFlags = vimModMaskToEventModifierFlags(mods);
int actionlen = [action lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSMutableData *data = [NSMutableData data];
key = specialKeyToNSKey(key);
@@ -590,6 +592,8 @@ static int specialKeyToNSKey(int key);
if (tiplen > 0) [data appendBytes:tip length:tiplen];
[data appendBytes:&iconlen length:sizeof(int)];
if (iconlen > 0) [data appendBytes:icon length:iconlen];
[data appendBytes:&actionlen length:sizeof(int)];
if (actionlen > 0) [data appendBytes:[action UTF8String] length:actionlen];
[data appendBytes:&index length:sizeof(int)];
[data appendBytes:&key length:sizeof(int)];
[data appendBytes:&eventFlags length:sizeof(int)];
+19 -7
View File
@@ -30,7 +30,8 @@ static NSString *DefaultToolbarImageName = @"Attention";
atIndex:(int)idx;
- (void)addMenuItemWithTag:(int)tag parent:(NSMenu *)parent
title:(NSString *)title tip:(NSString *)tip
keyEquivalent:(int)key modifiers:(int)mask atIndex:(int)idx;
keyEquivalent:(int)key modifiers:(int)mask
action:(NSString *)action atIndex:(int)idx;
- (void)updateMainMenu;
- (NSToolbarItem *)toolbarItemForTag:(int)tag index:(int *)index;
- (IBAction)toolbarAction:(id)sender;
@@ -569,7 +570,7 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
[title release];
} else if (AddMenuItemMsgID == msgid) {
NSString *title = nil, *tip = nil, *icon = nil;
NSString *title = nil, *tip = nil, *icon = nil, *action = nil;
const void *bytes = [data bytes];
int tag = *((int*)bytes); bytes += sizeof(int);
int parentTag = *((int*)bytes); bytes += sizeof(int);
@@ -591,6 +592,13 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
encoding:NSUTF8StringEncoding];
bytes += iconlen;
}
int actionlen = *((int*)bytes); bytes += sizeof(int);
if (actionlen > 0) {
action = [[NSString alloc] initWithBytes:(void*)bytes
length:actionlen
encoding:NSUTF8StringEncoding];
bytes += actionlen;
}
int idx = *((int*)bytes); bytes += sizeof(int);
if (idx < 0) idx = 0;
int key = *((int*)bytes); bytes += sizeof(int);
@@ -604,12 +612,14 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
} else {
NSMenu *parent = [self menuForTag:parentTag];
[self addMenuItemWithTag:tag parent:parent title:title tip:tip
keyEquivalent:key modifiers:mask atIndex:idx];
keyEquivalent:key modifiers:mask action:action
atIndex:idx];
}
[title release];
[tip release];
[icon release];
[action release];
} else if (RemoveMenuItemMsgID == msgid) {
const void *bytes = [data bytes];
int tag = *((int*)bytes); bytes += sizeof(int);
@@ -891,21 +901,23 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
- (void)addMenuItemWithTag:(int)tag parent:(NSMenu *)parent
title:(NSString *)title tip:(NSString *)tip
keyEquivalent:(int)key modifiers:(int)mask atIndex:(int)idx
keyEquivalent:(int)key modifiers:(int)mask
action:(NSString *)action atIndex:(int)idx
{
if (parent) {
NSMenuItem *item = nil;
if (title) {
item = [[[NSMenuItem alloc] init] autorelease];
[item setTitle:title];
[item setAction:@selector(vimMenuItemAction:)];
// TODO: Check that 'action' is a valid action (nothing will happen
// if it isn't, but it would be nice with a warning).
if (action) [item setAction:NSSelectorFromString(action)];
else [item setAction:@selector(vimMenuItemAction:)];
if (tip) [item setToolTip:tip];
if (key != 0) {
NSString *keyString =
[NSString stringWithFormat:@"%C", key];
//NSLog(@"Set key equivalent %@ (code=0x%x, mods=%d)",
// keyString, key, mask);
[item setKeyEquivalent:keyString];
[item setKeyEquivalentModifierMask:mask];
}
+46 -16
View File
@@ -14,6 +14,8 @@
#import "vim.h"
static BOOL gui_cocoa_is_valid_action(NSString *action);
// -- Initialization --------------------------------------------------------
@@ -582,6 +584,26 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
char *tip = menu->strings[MENU_INDEX_TIP]
? (char*)menu->strings[MENU_INDEX_TIP] : (char*)menu->actext;
// HACK! Check if menu is mapped to ':action actionName:'; if so, pass the
// action along so that MacVim can bind the menu item to this action. This
// means that if a menu item maps to an action in normal mode, then all
// other modes will also use the same action.
NSString *action = nil;
char_u *map_str = menu->strings[MENU_INDEX_NORMAL];
if (map_str) {
NSString *mapping = [NSString stringWithCString:(char*)map_str
encoding:NSUTF8StringEncoding];
NSArray *parts = [mapping componentsSeparatedByString:@" "];
if ([parts count] >=2
&& [[parts objectAtIndex:0] isEqual:@":action"]) {
action = [parts objectAtIndex:1];
action = [action stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if (!gui_cocoa_is_valid_action(action))
action = nil;
}
}
[[MMBackend sharedInstance]
addMenuItemWithTag:(int)menu
parent:(int)menu->parent
@@ -590,6 +612,7 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
icon:(char*)icon
keyEquivalent:menu->ke_key
modifiers:menu->ke_mods
action:action
atIndex:idx];
}
@@ -861,29 +884,14 @@ gui_mch_set_scrollbar_thumb(
ex_action(eap)
exarg_T *eap;
{
static NSDictionary *actionDict = nil;
if (!gui.in_use) {
EMSG(_("E???: Command only available in GUI mode"));
return;
}
if (!actionDict) {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *path = [mainBundle pathForResource:@"Actions"
ofType:@"plist"];
if (path) {
actionDict = [[NSDictionary alloc] initWithContentsOfFile:path];
} else {
// Allocate bogus dictionary so that error only pops up once.
actionDict = [NSDictionary new];
EMSG(_("E???: Failed to load action dictionary"));
}
}
NSString *name = [NSString stringWithCString:(char*)eap->arg
encoding:NSUTF8StringEncoding];
if ([actionDict objectForKey:name]) {
if (gui_cocoa_is_valid_action(name)) {
[[MMBackend sharedInstance] executeActionWithName:name];
} else {
EMSG2(_("E???: \"%s\" is not a valid action"), eap->arg);
@@ -1244,3 +1252,25 @@ gui_mch_toggle_tearoffs(int enable)
mch_set_mouse_shape(int shape)
{
}
static BOOL
gui_cocoa_is_valid_action(NSString *action)
{
static NSDictionary *actionDict = nil;
if (!actionDict) {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *path = [mainBundle pathForResource:@"Actions"
ofType:@"plist"];
if (path) {
actionDict = [[NSDictionary alloc] initWithContentsOfFile:path];
} else {
// Allocate bogus dictionary so that error only pops up once.
actionDict = [NSDictionary new];
EMSG(_("E???: Failed to load action dictionary"));
}
}
return [actionDict objectForKey:action] != nil;
}