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:
dpsimons 2010-04-24 17:12:35 +00:00
parent 329dc9aef1
commit 7a815aa384
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> 2010-04-23 Eric Wasylishen <ewasylishen@gmail.com>
* Source/NSMenuItem.m: Fix for bug 29635 * Source/NSMenuItem.m: Fix for bug 29635

View file

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

View file

@ -659,7 +659,7 @@ static BOOL menuBarVisible = YES;
up menus in NSApplicationWillFinishLaunching. up menus in NSApplicationWillFinishLaunching.
*/ */
[nc addObserver: self [nc addObserver: self
selector: @selector(_showTornOffMenuIfAny:) selector: @selector(applicationDidFinishLaunching:)
name: NSApplicationDidFinishLaunchingNotification name: NSApplicationDidFinishLaunchingNotification
object: NSApp]; object: NSApp];
@ -684,6 +684,16 @@ static BOOL menuBarVisible = YES;
/* /*
* Setting Up the Menu Commands * 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 - (void) insertItem: (id <NSMenuItem>)newItem
atIndex: (int)index atIndex: (int)index
{ {
@ -723,6 +733,7 @@ static BOOL menuBarVisible = YES;
[nc postNotification: inserted]; [nc postNotification: inserted];
else else
[_notifications addObject: inserted]; [_notifications addObject: inserted];
[self menuChanged];
// Set this after the insert notification has been sent. // Set this after the insert notification has been sent.
[newItem setMenu: self]; [newItem setMenu: self];
@ -794,6 +805,7 @@ static BOOL menuBarVisible = YES;
[nc postNotification: removed]; [nc postNotification: removed];
else else
[_notifications addObject: removed]; [_notifications addObject: removed];
[self menuChanged];
} }
- (void) itemChanged: (id <NSMenuItem>)anObject - (void) itemChanged: (id <NSMenuItem>)anObject
@ -819,6 +831,7 @@ static BOOL menuBarVisible = YES;
[nc postNotification: changed]; [nc postNotification: changed];
else else
[_notifications addObject: changed]; [_notifications addObject: changed];
[self menuChanged];
// Update the menu. // Update the menu.
[self update]; [self update];
@ -1048,33 +1061,6 @@ static BOOL menuBarVisible = YES;
- (void) update - (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)
{ {
if ([_delegate respondsToSelector:@selector(menuNeedsUpdate:)]) if ([_delegate respondsToSelector:@selector(menuNeedsUpdate:)])
@ -1199,7 +1185,16 @@ static BOOL menuBarVisible = YES;
} }
NS_ENDHANDLER NS_ENDHANDLER
// Reenable displaying of menus // 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])) if (_menu.needsSizing && ([_aWindow isVisible] || [_bWindow isVisible]))
@ -1610,16 +1605,7 @@ static BOOL menuBarVisible = YES;
for (i = 0; i < [dItems count]; i++) for (i = 0; i < [dItems count]; i++)
{ {
NSMenuItem *item = [dItems objectAtIndex: i]; NSMenuItem *item = [dItems objectAtIndex: i];
NSMenu *sub = [item submenu];
[self addItem: item]; [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]; [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 - (void) _showOnActivateApp: (NSNotification*)notification
{ {
if ([NSApp mainMenu] == self) if ([NSApp mainMenu] == self)
@ -1902,7 +1894,7 @@ static BOOL menuBarVisible = YES;
oldRep = [self menuRepresentation]; oldRep = [self menuRepresentation];
oldStyle = [oldRep interfaceStyle]; oldStyle = [oldRep interfaceStyle];
newStyle = NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil); newStyle = NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil);
/* /*
* If necessary, rebuild menu for (different) style * If necessary, rebuild menu for (different) style
*/ */
@ -1953,6 +1945,7 @@ static BOOL menuBarVisible = YES;
{ {
[self display]; [self display];
} }
[[GSTheme theme] updateAllWindowsWithMenu: self];
} }
else else
{ {

View file

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