Improved menu display and image caching

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@5505 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
richard 1999-12-14 11:18:11 +00:00
parent 5c453a3686
commit a61c6434b2
4 changed files with 128 additions and 59 deletions

View file

@ -1,3 +1,13 @@
Tue Dec 14 11:15:00 1999 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Headers/AppKit/NSMenuitemCell.h: Removed implementation cache ivars
and added an ivar for temporary storage of background color.
* Source/NSMenuItemCell.m: Removed draw implementation caching to
decrease memory footprint, but added color and image class caching
which will more than compensate in performance. Also added use of
highlight version of menu arrow.
* Source/NSImage.m: minor image caching fixes and more debug statements.
1999-12-13 <fedor@gnu.org> 1999-12-13 <fedor@gnu.org>
* Source/NSWindow.m (-_processResizeEvent): Add DPScurrentgstate * Source/NSWindow.m (-_processResizeEvent): Add DPScurrentgstate

View file

@ -55,7 +55,7 @@ typedef void (*DrawingIMP)(id, SEL, NSRect, NSView*);
NSSize mcell_imageSize; NSSize mcell_imageSize;
@private @private
DrawingIMP _drawMethods[4]; NSColor *_backgroundColor;
} }
- (void)setHighlighted:(BOOL)flag; - (void)setHighlighted:(BOOL)flag;

View file

@ -628,7 +628,8 @@ static Class cacheClass = 0;
{ {
[rep setOpaque: [repd->original isOpaque]]; [rep setOpaque: [repd->original isOpaque]];
} }
NSDebugLLog(@"NSImage", @"Rendered rep %d", (int)rep); NSDebugLLog(@"NSImage", @"Rendered rep %d on background %@",
(int)rep, repd->bg);
} }
} }
@ -887,6 +888,7 @@ static Class cacheClass = 0;
GSRepData *partialCache = nil; GSRepData *partialCache = nil;
GSRepData *validCache = nil; GSRepData *validCache = nil;
GSRepData *reps[count]; GSRepData *reps[count];
unsigned partialCount = 0;
unsigned i; unsigned i;
BOOL opaque = [rep isOpaque]; BOOL opaque = [rep isOpaque];
@ -896,7 +898,7 @@ static Class cacheClass = 0;
* Search the cached image reps for any whose original is our * Search the cached image reps for any whose original is our
* 'best' image rep. See if we can notice any invalidated * 'best' image rep. See if we can notice any invalidated
* cache as we go - if we don't find a valid cache, we want to * cache as we go - if we don't find a valid cache, we want to
* re-use an invalidated one rather than createing a new one. * re-use an invalidated one rather than creating a new one.
* NB. If the image rep is opaque, then any cached rep is valid * NB. If the image rep is opaque, then any cached rep is valid
* irrespective of the background color it was drawn with. * irrespective of the background color it was drawn with.
*/ */
@ -904,7 +906,7 @@ static Class cacheClass = 0;
{ {
GSRepData *repd = reps[i]; GSRepData *repd = reps[i];
if (repd->original == rep) if (repd->original == rep && repd->rep != rep)
{ {
if (repd->bg == nil) if (repd->bg == nil)
{ {
@ -921,6 +923,7 @@ NSDebugLLog(@"NSImage", @"Exact %@ ... %@ %d", repd->bg, _color, repd->rep);
{ {
NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep); NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
partialCache = repd; partialCache = repd;
partialCount++;
} }
} }
} }
@ -943,8 +946,13 @@ NSDebugLLog(@"NSImage", @"Partial %@ ... %@ %d", repd->bg, _color, repd->rep);
} }
cacheRep = validCache->rep; cacheRep = validCache->rep;
} }
else if (partialCache != nil) else if (partialCache != nil && partialCount > 2)
{ {
/*
* Only re-use partially correct caches if there are already
* a few partial matches - otherwise we fall default to
* creating a new cache.
*/
if (NSImageForceCaching == NO && [rep isOpaque] == NO) if (NSImageForceCaching == NO && [rep isOpaque] == NO)
{ {
if (invalidCache != nil) if (invalidCache != nil)

View file

@ -46,12 +46,19 @@
@implementation NSMenuItemCell @implementation NSMenuItemCell
static Class colorClass = 0; /* Cache color class. */
static NSImage *arrowImage = nil; /* Cache arrow image. */
static NSImage *arrowImageH = nil;
+ (void) initialize + (void) initialize
{ {
if (self == [NSMenuItemCell class]) if (self == [NSMenuItemCell class])
{ {
// Initial version [self setVersion: 1];
[self setVersion:2]; colorClass = [NSColor class];
arrowImage = [[NSImage imageNamed: @"common_3DArrowRight"] copy];
arrowImageH = [[NSImage imageNamed: @"common_3DArrowRightH"] copy];
} }
} }
@ -65,15 +72,6 @@
_cell.image_position = NSNoImage; _cell.image_position = NSNoImage;
_cell.text_align = NSLeftTextAlignment; _cell.text_align = NSLeftTextAlignment;
_drawMethods[0] = (DrawingIMP)
[self methodForSelector:@selector(drawStateImageWithFrame:inView:)];
_drawMethods[1] = (DrawingIMP)
[self methodForSelector:@selector(drawImageWithFrame:inView:)];
_drawMethods[2] = (DrawingIMP)
[self methodForSelector:@selector(drawTitleWithFrame:inView:)];
_drawMethods[3] = (DrawingIMP)
[self methodForSelector:@selector(drawKeyEquivalentWithFrame:inView:)];
return self; return self;
} }
@ -361,11 +359,12 @@
} }
} }
- (void) drawImageWithFrame:(NSRect)cellFrame - (void) drawImageWithFrame: (NSRect)cellFrame
inView:(NSView *)controlView inView: (NSView *)controlView
{ {
NSSize size; NSSize size;
NSPoint position; NSPoint position;
NSColor *backgroundColor = _backgroundColor;
cellFrame = [self imageRectForBounds: cellFrame]; cellFrame = [self imageRectForBounds: cellFrame];
size = [mcell_imageToDisplay size]; size = [mcell_imageToDisplay size];
@ -377,6 +376,26 @@
*/ */
if ([controlView isFlipped]) if ([controlView isFlipped])
position.y += size.height; position.y += size.height;
if (backgroundColor == nil)
{
if (_cell.state)
{
if (_showAltStateMask
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask))
backgroundColor = [colorClass selectedMenuItemColor];
}
if (mcell_highlighted)
{
if (_highlightsByMask
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask))
backgroundColor = [colorClass selectedMenuItemColor];
}
if (backgroundColor == nil)
backgroundColor = [colorClass controlBackgroundColor];
}
[mcell_imageToDisplay setBackgroundColor: backgroundColor];
[mcell_imageToDisplay compositeToPoint: position operation: NSCompositeCopy]; [mcell_imageToDisplay compositeToPoint: position operation: NSCompositeCopy];
} }
@ -387,11 +406,16 @@
if ([mcell_item hasSubmenu]) if ([mcell_item hasSubmenu])
{ {
NSSize size; NSSize size;
NSPoint position; NSPoint position;
NSImage *arrowImage = [NSImage imageNamed:@"common_3DArrowRight"]; NSColor *backgroundColor = _backgroundColor;
NSImage *imageToDraw;
size = [arrowImage size]; if (mcell_highlighted)
imageToDraw = arrowImageH;
else
imageToDraw = arrowImage;
size = [imageToDraw size];
position.x = cellFrame.origin.x + cellFrame.size.width - size.width; position.x = cellFrame.origin.x + cellFrame.size.width - size.width;
position.y = MAX(NSMidY(cellFrame) - (size.height/2.), 0.); position.y = MAX(NSMidY(cellFrame) - (size.height/2.), 0.);
/* /*
@ -400,7 +424,26 @@
*/ */
if ([controlView isFlipped]) if ([controlView isFlipped])
position.y += size.height; position.y += size.height;
[arrowImage compositeToPoint: position operation: NSCompositeCopy];
if (backgroundColor == nil)
{
if (_cell.state)
{
if (_showAltStateMask
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask))
backgroundColor = [colorClass selectedMenuItemColor];
}
if (mcell_highlighted)
{
if (_highlightsByMask
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask))
backgroundColor = [colorClass selectedMenuItemColor];
}
if (backgroundColor == nil)
backgroundColor = [colorClass controlBackgroundColor];
}
[imageToDraw setBackgroundColor: backgroundColor];
[imageToDraw compositeToPoint: position operation: NSCompositeCopy];
} }
else else
[self _drawText: [mcell_item keyEquivalent] inFrame: cellFrame]; [self _drawText: [mcell_item keyEquivalent] inFrame: cellFrame];
@ -413,12 +456,13 @@
// Maybe somebody wants to support this (Lazaro). // Maybe somebody wants to support this (Lazaro).
} }
- (void) drawStateImageWithFrame:(NSRect)cellFrame - (void) drawStateImageWithFrame: (NSRect)cellFrame
inView:(NSView *)controlView inView: (NSView*)controlView
{ {
NSSize size; NSSize size;
NSPoint position; NSPoint position;
NSImage *imageToDisplay; NSImage *imageToDisplay;
NSColor *backgroundColor = _backgroundColor;
cellFrame = [self stateImageRectForBounds: cellFrame]; cellFrame = [self stateImageRectForBounds: cellFrame];
@ -447,6 +491,25 @@
*/ */
if ([controlView isFlipped]) if ([controlView isFlipped])
position.y += size.height; position.y += size.height;
if (backgroundColor == nil)
{
if (_cell.state)
{
if (_showAltStateMask
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask))
backgroundColor = [colorClass selectedMenuItemColor];
}
if (mcell_highlighted)
{
if (_highlightsByMask
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask))
backgroundColor = [colorClass selectedMenuItemColor];
}
if (backgroundColor == nil)
backgroundColor = [colorClass controlBackgroundColor];
}
[imageToDisplay setBackgroundColor: _backgroundColor];
[imageToDisplay compositeToPoint: position operation: NSCompositeCopy]; [imageToDisplay compositeToPoint: position operation: NSCompositeCopy];
} }
@ -491,7 +554,6 @@
{ {
BOOL showAlternate = NO; BOOL showAlternate = NO;
unsigned mask; unsigned mask;
NSColor *backgroundColor = nil;
// Transparent buttons never draw // Transparent buttons never draw
if (_buttoncell_is_transparent) if (_buttoncell_is_transparent)
@ -504,26 +566,29 @@
&& (_highlightsByMask & NSPushInCellMask)) && (_highlightsByMask & NSPushInCellMask))
PStranslate(1., [controlView isFlipped] ? 1. : -1.); PStranslate(1., [controlView isFlipped] ? 1. : -1.);
// Determine the background color /*
* Determine the background color and cache it in an ivar so that the
* low-level drawing methods don't need to do it again.
*/
if (_cell.state) if (_cell.state)
{ {
if (_showAltStateMask if (_showAltStateMask
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask) ) & (NSChangeGrayCellMask | NSChangeBackgroundCellMask))
backgroundColor = [NSColor selectedMenuItemColor]; _backgroundColor = [colorClass selectedMenuItemColor];
} }
if (mcell_highlighted) if (mcell_highlighted)
{ {
if (_highlightsByMask if (_highlightsByMask
& (NSChangeGrayCellMask | NSChangeBackgroundCellMask) ) & (NSChangeGrayCellMask | NSChangeBackgroundCellMask))
backgroundColor = [NSColor selectedMenuItemColor]; _backgroundColor = [colorClass selectedMenuItemColor];
} }
if (backgroundColor == nil) if (_backgroundColor == nil)
backgroundColor = [NSColor controlBackgroundColor]; _backgroundColor = [colorClass controlBackgroundColor];
// Set cell's background color // Set cell's background color
[backgroundColor set]; [_backgroundColor set];
NSRectFill(cellFrame); NSRectFill(cellFrame);
/* /*
@ -560,28 +625,25 @@
if (mcell_imageToDisplay) if (mcell_imageToDisplay)
{ {
mcell_imageWidth = [mcell_imageToDisplay size].width; mcell_imageWidth = [mcell_imageToDisplay size].width;
[mcell_imageToDisplay setBackgroundColor: backgroundColor];
} }
// Draw the state image // Draw the state image
if (mcell_stateImageWidth > 0) if (mcell_stateImageWidth > 0)
_drawMethods[0](self, @selector(drawStateImageWithFrame:inView:), [self drawStateImageWithFrame: cellFrame inView: controlView];
cellFrame, controlView);
// Draw the image // Draw the image
if (mcell_imageWidth > 0) if (mcell_imageWidth > 0)
_drawMethods[1](self, @selector(drawImageWithFrame:inView:), [self drawImageWithFrame: cellFrame inView: controlView];
cellFrame, controlView);
// Draw the title // Draw the title
if (mcell_titleWidth > 0) if (mcell_titleWidth > 0)
_drawMethods[2](self, @selector(drawTitleWithFrame:inView:), [self drawTitleWithFrame: cellFrame inView: controlView];
cellFrame, controlView);
// Draw the key equivalent // Draw the key equivalent
if (mcell_keyEquivalentWidth > 0) if (mcell_keyEquivalentWidth > 0)
_drawMethods[3](self, @selector(drawKeyEquivalentWithFrame:inView:), [self drawKeyEquivalentWithFrame: cellFrame inView: controlView];
cellFrame, controlView);
_backgroundColor = nil;
} }
// //
@ -598,8 +660,6 @@
c->mcell_menuView = mcell_menuView; c->mcell_menuView = mcell_menuView;
c->mcell_needs_sizing = mcell_needs_sizing; c->mcell_needs_sizing = mcell_needs_sizing;
memcpy(c->_drawMethods, _drawMethods, sizeof(DrawingIMP) * 4);
return c; return c;
} }
@ -627,15 +687,6 @@
mcell_needs_sizing = YES; mcell_needs_sizing = YES;
_drawMethods[0] = (DrawingIMP)
[self methodForSelector:@selector(drawStateImageWithFrame:inView:)];
_drawMethods[1] = (DrawingIMP)
[self methodForSelector:@selector(drawImageWithFrame:inView:)];
_drawMethods[2] = (DrawingIMP)
[self methodForSelector:@selector(drawTitleWithFrame:inView:)];
_drawMethods[3] = (DrawingIMP)
[self methodForSelector:@selector(drawKeyEquivalentWithFrame:inView:)];
return self; return self;
} }