Only rebuild in-window menus when needed (significant performance improvement)

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@30232 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Doug Simons 2010-04-24 17:12:35 +00:00
parent 165dcffe60
commit b136536052
4 changed files with 74 additions and 45 deletions

View file

@ -1,3 +1,12 @@
2010-04-24 Doug Simons <doug.simons@testplant.com>
* Headers/AppKit/NSMenu.h:
* Source/NSMenu.m:
* Source/NSMenuItem.m:
Rebuild in-window menus only when needed on Windows. Also fixed
notifying a menu item's menu only when a property value actually
changes.
2010-04-23 Eric Wasylishen <ewasylishen@gmail.com>
* Source/NSMenuItem.m: Fix for bug 29635

View file

@ -347,7 +347,8 @@
unsigned int is_tornoff: 1;
unsigned int transient: 1;
unsigned int horizontal: 1;
unsigned int unused: 26;
unsigned int mainMenuChanged: 1;
unsigned int unused: 25;
} _menu;
@private

View file

@ -659,7 +659,7 @@ static BOOL menuBarVisible = YES;
up menus in NSApplicationWillFinishLaunching.
*/
[nc addObserver: self
selector: @selector(_showTornOffMenuIfAny:)
selector: @selector(applicationDidFinishLaunching:)
name: NSApplicationDidFinishLaunchingNotification
object: NSApp];
@ -684,6 +684,16 @@ static BOOL menuBarVisible = YES;
/*
* Setting Up the Menu Commands
*/
- (void) menuChanged
{
// propagate notification up to the main menu
if (self == [NSApp mainMenu])
_menu.mainMenuChanged = YES;
else
[[self supermenu] menuChanged];
}
- (void) insertItem: (id <NSMenuItem>)newItem
atIndex: (int)index
{
@ -723,6 +733,7 @@ static BOOL menuBarVisible = YES;
[nc postNotification: inserted];
else
[_notifications addObject: inserted];
[self menuChanged];
// Set this after the insert notification has been sent.
[newItem setMenu: self];
@ -794,6 +805,7 @@ static BOOL menuBarVisible = YES;
[nc postNotification: removed];
else
[_notifications addObject: removed];
[self menuChanged];
}
- (void) itemChanged: (id <NSMenuItem>)anObject
@ -819,6 +831,7 @@ static BOOL menuBarVisible = YES;
[nc postNotification: changed];
else
[_notifications addObject: changed];
[self menuChanged];
// Update the menu.
[self update];
@ -1048,33 +1061,6 @@ static BOOL menuBarVisible = YES;
- (void) update
{
if (self == [NSApp mainMenu])
{
/* For microsoft style menus, we attempt to notice that we have
* a main window, and make sure that the menu appears in it.
*/
if (NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil) ==
NSWindows95InterfaceStyle)
{
NSWindow *w = [NSApp mainWindow];
if (w == nil)
{
/* Make sure we are set up properly and displayed.
*/
if ([_aWindow isVisible] == NO)
{
[self setMain: YES];
}
}
else if ([w menu] != self)
{
[w setMenu: self];
}
[[GSTheme theme] updateAllWindowsWithMenu: self];
}
}
if (_delegate)
{
if ([_delegate respondsToSelector:@selector(menuNeedsUpdate:)])
@ -1199,7 +1185,16 @@ static BOOL menuBarVisible = YES;
}
NS_ENDHANDLER
// Reenable displaying of menus
[self setMenuChangedMessagesEnabled: YES];
[self setMenuChangedMessagesEnabled: YES]; // this will send pending _notifications
}
if (_menu.mainMenuChanged)
{
if (NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil) == NSWindows95InterfaceStyle)
{
[[GSTheme theme] updateAllWindowsWithMenu: self];
}
_menu.mainMenuChanged = NO;
}
if (_menu.needsSizing && ([_aWindow isVisible] || [_bWindow isVisible]))
@ -1610,16 +1605,7 @@ static BOOL menuBarVisible = YES;
for (i = 0; i < [dItems count]; i++)
{
NSMenuItem *item = [dItems objectAtIndex: i];
NSMenu *sub = [item submenu];
[self addItem: item];
// FIXME: We propably don't need this, as all the fields are
// already set up for the submenu item.
if (sub != nil)
{
[sub setSupermenu: nil];
[self setSubmenu: sub forItem: item];
}
}
[self setMenuChangedMessagesEnabled: YES];
@ -1703,6 +1689,12 @@ static BOOL menuBarVisible = YES;
}
}
- (void) applicationDidFinishLaunching:(NSNotification *)notification
{
[[GSTheme theme] updateAllWindowsWithMenu: [NSApp mainMenu]];
[self _showTornOffMenuIfAny:notification];
}
- (void) _showOnActivateApp: (NSNotification*)notification
{
if ([NSApp mainMenu] == self)
@ -1902,7 +1894,7 @@ static BOOL menuBarVisible = YES;
oldRep = [self menuRepresentation];
oldStyle = [oldRep interfaceStyle];
newStyle = NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil);
/*
* If necessary, rebuild menu for (different) style
*/
@ -1953,6 +1945,7 @@ static BOOL menuBarVisible = YES;
{
[self display];
}
[[GSTheme theme] updateAllWindowsWithMenu: self];
}
else
{

View file

@ -174,6 +174,9 @@ static Class imageClass;
- (void) setSubmenu: (NSMenu*)submenu
{
if (submenu == _submenu)
return; // no change
if ([submenu supermenu] != nil)
{
[NSException raise: NSInvalidArgumentException
@ -200,7 +203,10 @@ static Class imageClass;
{
if (nil == aString)
aString = @"";
if ([_title isEqualToString:aString])
return; // no change
ASSIGNCOPY(_title, aString);
[_menu itemChanged: self];
}
@ -225,7 +231,9 @@ static Class imageClass;
@"Attempt to use nil as key equivalent");
aKeyEquivalent = @"";
}
if ([_keyEquivalent isEqualToString:aKeyEquivalent])
return; // no change
ASSIGNCOPY(_keyEquivalent, aKeyEquivalent);
[_menu itemChanged: self];
}
@ -240,7 +248,10 @@ static Class imageClass;
- (void) setKeyEquivalentModifierMask: (unsigned int)mask
{
if (_keyEquivalentModifierMask == mask)
return; // no change
_keyEquivalentModifierMask = mask;
[_menu itemChanged: self];
}
- (unsigned int) keyEquivalentModifierMask
@ -269,6 +280,9 @@ static Class imageClass;
- (void) setMnemonicLocation: (unsigned)location
{
if (_mnemonicLocation == location)
return; // no change
_mnemonicLocation = location;
[_menu itemChanged: self];
}
@ -302,7 +316,10 @@ static Class imageClass;
{
NSAssert(image == nil || [image isKindOfClass: imageClass],
NSInvalidArgumentException);
if (_image == image)
return; // no change
ASSIGN(_image, image);
[_menu itemChanged: self];
}
@ -331,7 +348,10 @@ static Class imageClass;
{
NSAssert(image == nil || [image isKindOfClass: imageClass],
NSInvalidArgumentException);
if (_onStateImage == image)
return; // no change
ASSIGN(_onStateImage, image);
[_menu itemChanged: self];
}
@ -345,6 +365,9 @@ static Class imageClass;
{
NSAssert(image == nil || [image isKindOfClass: imageClass],
NSInvalidArgumentException);
if (_offStateImage == image)
return; // no change
ASSIGN(_offStateImage, image);
[_menu itemChanged: self];
@ -359,7 +382,10 @@ static Class imageClass;
{
NSAssert(image == nil || [image isKindOfClass: imageClass],
NSInvalidArgumentException);
if (_mixedStateImage == image)
return; // no change
ASSIGN(_mixedStateImage, image);
[_menu itemChanged: self];
}