Files
cappuccino/Tests/Manual/UndoRedoWithMenuUpdate/AppController.j
T

244 lines
6.2 KiB
Plaintext

@implementation AppController : CPObject
{
CPTextField label;
CPSlider theSlider;
CPUndoManager undoManager @accessors;
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],
contentView = [theWindow contentView];
label = [[CPTextField alloc] initWithFrame:CGRectMakeZero()];
[label setStringValue:@"Hello World!"];
[label setFont:[CPFont boldSystemFontOfSize:24.0]];
[label sizeToFit];
[label setAutoresizingMask:CPViewMinXMargin | CPViewMaxXMargin | CPViewMinYMargin | CPViewMaxYMargin];
[label setCenter:[contentView center]];
[contentView addSubview:label];
theSlider = [[CPSlider alloc] initWithFrame:CGRectMake(100, 100, 180, 24)];
[theSlider setMinValue:36];
[theSlider setMaxValue:238];
[theSlider setObjectValue:([theSlider minValue] + [theSlider maxValue]) / 2];
[theSlider setTarget:self];
[theSlider setAction:@selector(doSlider:)];
[contentView addSubview:theSlider];
[theWindow orderFront:self];
// Uncomment the following line to turn on the standard menu bar.
[CPMenu setMenuBarVisible:YES];
// setup the menus to manage
undoManager = [[CPUndoManager alloc] init];
var editmenuItem = [[[CPApplication sharedApplication] mainMenu] itemWithTitle: @"Edit"];
[[editmenuItem submenu] setAutoenablesItems:YES];
var undoMenuItem = [[editmenuItem submenu] itemWithTitle:@"Undo"];
[undoMenuItem setTag:@"Undo"];
[undoMenuItem setTarget:self];
var redoMenuItem = [[editmenuItem submenu] itemWithTitle:@"Redo"];
[redoMenuItem setTag:@"Redo"];
[redoMenuItem setTarget:self];
}
- (void)doSlider:sender
{
[self setSliderValue:[sender objectValue]];
}
- (void)setSliderValue:aValue
{
[[undoManager prepareWithInvocationTarget:self] setSliderValue:[label objectValue]];
[theSlider setObjectValue:aValue];
[undoManager setActionName:@"slideto: " + aValue];
[label setObjectValue:aValue];
[label sizeToFit];
}
- (void)undo:(id)sender
{
[undoManager undo];
[[sender _menuItemView] highlight:NO];
}
- (void)redo:(id)sender
{
[undoManager redo];
[[sender _menuItemView] highlight:NO];
}
//this will be called whenver the user clicks on an autoenabled menu
- (BOOL)validateMenuItem:(id)anItem
{
switch ([anItem tag])
{
case @"Undo" :
[anItem setTitle:[undoManager undoMenuItemTitle]];
return([undoManager canUndo]);
break;
case @"Redo" :
[anItem setTitle:[undoManager redoMenuItemTitle]];
return([undoManager canRedo]);
break;
default:
return [anItem isEnabled];
}
}
@end
////////////// autoenablesItems from here http://github.com/farcaller/cappuccino/commit/5d1af7192d2afe5b938c5bcdd197f15c79811b7f
////////////// Currently waiting to be pulled into master
@implementation CPMenu(autoenablesItems)
- (void)update
{
var cnt = [_items count];
for (var i = 0; i < cnt; ++i)
{
var item = [_items objectAtIndex:i];
if ([[item target] respondsToSelector:@selector(validateMenuItem:)])
[item _setEnabledByMenu:[[item target] validateMenuItem:item]];
else
[item _setEnabledByMenu:[item isEnabled]]; /// BD Change from NO
}
}
@end
@implementation CPMenuItem(autoenablesItems)
// a private function to toggle availability as part of update check
- (void)_setEnabledByMenu:(BOOL)isEnabled
{
if (![_menu autoenablesItems])
return;
_isEnabled = isEnabled;
[_menuItemView setDirty];
}
// Performs autoenable processing, returns isEnabled to propagate state
- (BOOL)_performAutoenable
{
if ([_menu autoenablesItems])
{
if (_target)
{
if ([_target respondsToSelector:@selector(validateMenuItem:)])
{
var isEnabled = [_target validateMenuItem:self];
_isEnabled = isEnabled;
[_menuItemView setDirty];
return _isEnabled;
}
else
return YES; // enabled by default
}
else
{
// XXX: will toggle state as part of _target check
_isEnabled = isEnabled;
[_menuItemView setDirty];
return NO;
}
}
else
{
// XXX: should it return NO, if target is nil?..
return [self isEnabled];
}
}
@end
@implementation _CPMenuManager(autoenablesItems)
- (void)showMenu:(CPMenu)newMenu fromMenu:(CPMenu)baseMenu atPoint:(CGPoint)aGlobalLocation
{
var count = _menuContainerStack.length,
index = count;
// Hide all menus up to the base menu...
while (index--)
{
var menuContainer = _menuContainerStack[index],
menu = [menuContainer menu];
// If we reach the base menu, or this menu is already being shown, break.
if (menu === baseMenu)
break;
// If this menu is already being shown, unhighlight and return.
if (menu === newMenu)//&& [menu supermenu] === baseMenu)
{
[newMenu _highlightItemAtIndex:CPNotFound];
return;
}
[menuContainer orderOut:self];
[menuContainer setMenu:nil];
[_CPMenuWindow poolMenuWindow:menuContainer];
[_menuContainerStack removeObjectAtIndex:index];
}
if (!newMenu)
return;
if ([newMenu autoenablesItems])
[newMenu update];
// Unhighlight any previously highlighted item.
[newMenu _highlightItemAtIndex:CPNotFound];
var menuWindow = [_CPMenuWindow menuWindowWithMenu:newMenu font:[_menuContainerStack[0] font]];
[_menuContainerStack addObject:menuWindow];
[menuWindow setConstraintRect:_constraintRect];
// If our parent menu is a menu bar...
if (baseMenu === [self trackingMenu] && [[self trackingMenuContainer] isMenuBar])
[menuWindow setBackgroundStyle:_CPMenuWindowMenuBarBackgroundStyle];
else
[menuWindow setBackgroundStyle:_CPMenuWindowPopUpBackgroundStyle];
[menuWindow setFrameOrigin:aGlobalLocation];
[menuWindow orderFront:self];
}
@end
//////////////////////////// end of autoenablesItems