Merge branch 'menu-validation' into 0.9.1

This commit is contained in:
Klaas Pieter Annema committed 2011-04-20 11:24:17 +02:00
commit 592328f604
6 files changed
+102 -10

No files matched your search

+22 -2
View File
@@ -536,7 +536,6 @@ var _CPMenuBarVisible = NO,
*/
- (void)submenuAction:(id)aSender
{
}
/*!
@@ -584,11 +583,30 @@ var _CPMenuBarVisible = NO,
}
/*!
Not implemented.
Enables or disables the receiver’s menu items.
If the target does not implement the menu item's action method the item is disabled.
If the target responsds to selector validateMenuItem: or validateUserInterfaceItem: (in that order) the return value is used.
*/
- (void)update
{
if (![self autoenablesItems])
return;
var items = [self itemArray];
for (var i = 0; i < [items count]; i++)
{
var item = [items objectAtIndex:i],
validator = [CPApp targetForAction:[item action] to:[item target] from:item];
if (!validator || ![validator respondsToSelector:[item action]])
[item _setEnabled:NO];
else if ([validator respondsToSelector:@selector(validateMenuItem:)])
[item _setEnabled:[validator validateMenuItem:item]];
else if ([validator respondsToSelector:@selector(validateUserInterfaceItem:)])
[item _setEnabled:[validator validateUserInterfaceItem:item]];
}
[[_menuWindow _menuView] tile];
}
// Managing the Title
@@ -1100,6 +1118,8 @@ var CPMenuTitleKey = @"CPMenuTitleKey",
_showsStateColumn = ![aCoder containsValueForKey:CPMenuShowsStateColumnKey] || [aCoder decodeBoolForKey:CPMenuShowsStateColumnKey];
_autoenablesItems = YES;
[self setMinimumWidth:0];
}
+8 -2
View File
@@ -243,9 +243,15 @@ var STICKY_TIME_INTERVAL = 500,
// Close the current menu item because we are going to select a new one after a short delay
[self showMenu:nil fromMenu:activeMenu atPoint:CGPointMakeZero()];
_showTimerID = setTimeout(function() {
if (![activeMenuContainer isMenuBar])
{
_showTimerID = setTimeout(function() {
[self showMenu:[activeItem submenu] fromMenu:[activeItem menu] atPoint:newMenuOrigin];
}, 250);
}
else
[self showMenu:[activeItem submenu] fromMenu:[activeItem menu] atPoint:newMenuOrigin];
}, 250);
}
}
+6
View File
@@ -208,8 +208,14 @@ var STICKY_TIME_INTERVAL = 500,
return [_menuView menu];
}
- (_CPMenuView)_menuView
{
return _menuView;
}
- (void)orderFront:(id)aSender
{
[[self menu] update];
[self setFrame:_unconstrainedFrame];
[super orderFront:aSender];
+14 -2
View File
@@ -133,10 +133,17 @@
if ([_menu autoenablesItems])
return;
_isEnabled = isEnabled;
[self _setEnabled:isEnabled];
}
- (void)_setEnabled:(BOOL)isEnabled
{
if (_isEnabled === isEnabled)
return;
_isEnabled = !!isEnabled;
[_menuItemView setDirty];
[_menu itemChanged:self];
}
@@ -851,6 +858,11 @@ CPControlKeyMask
return ![self submenu] && [self menu] === [CPApp mainMenu];
}
- (CPString)description
{
return [super description] + @" target: " + [self target] + @" action: " + CPStringFromSelector([self action]);
}
@end
var CPMenuItemIsSeparatorKey = @"CPMenuItemIsSeparatorKey",
-4
View File
@@ -47,12 +47,8 @@
// If the destination doesn't respond to this selector, warn but don't die.
if (_destination && ![_destination respondsToSelector:selector])
{
CPLog.warn(@"Could not connect the action " + selector + @" to target of class " + [_destination className]);
return;
}
// Not being able to set the action is a fatal error.
if ([_source respondsToSelector:@selector(setAction:)])
objj_msgSend(_source, @selector(setAction:), selector);
@@ -0,0 +1,52 @@
@implementation CPMenuValidatedUserInterfaceItemTest : OJTestCase
{
CPMenu _menu @accessors(property=menu);
}
- (void)setUp
{
[[CPApplication sharedApplication] setDelegate:[[MenuTarget alloc] init]];
_menu = [[CPMenu alloc] init];
[_menu addItem:[[CPMenuItem alloc] initWithTitle:@"implemented" action:@selector(implementedAction:) keyEquivalent:nil]];
[_menu addItem:[[CPMenuItem alloc] initWithTitle:@"disabled" action:@selector(disabledAction:) keyEquivalent:nil]];
[_menu addItem:[[CPMenuItem alloc] initWithTitle:@"unimplemented" action:@selector(unimplementedAction:) keyEquivalent:nil]];
}
- (void)testAutoenable
{
// Update is what actually performs the autoenabling so we need to call it manually.
// It's normally called automatically just before a menu becomes visible.
[[self menu] update];
[self assertTrue:[[[self menu] itemWithTitle:@"implemented"] isEnabled] message:@"The implemented action should be enabled"];
[self assertFalse:[[[self menu] itemWithTitle:@"disabled"] isEnabled] message:@"The disbabled action should be disabled"];
[self assertFalse:[[[self menu] itemWithTitle:@"unimplemented"] isEnabled] message:@"The unimplemented action should be disabled"];
}
@end
@implementation MenuTarget : CPObject
{
}
- (BOOL)validateMenuItem:(CPMenuItem)theMenuItem
{
if ([theMenuItem action] === @selector(disabledAction:))
return NO;
return YES;
}
- (@action)implementedAction:(id)theSender
{
}
- (@action)disabledAction:(id)theSender
{
}
@end