Improved the menu theming to support some common menu look variations.

Fixed bug #34792 too.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@34174 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Quentin Mathe 2011-11-16 10:32:15 +00:00
parent eaafb6754d
commit 96aad93e0f
5 changed files with 268 additions and 53 deletions

View file

@ -1,3 +1,25 @@
2011-11-16 Quentin Mathe <quentin.mathe@gmail.com>
Improved the menu theming to support some common menu look variations.
Fixed bug #34792 too.
* Headers/Additions/GNUstepGUI/GSTheme.h
* Source/GSTheme.m
* Source/GSThemeDrawing.m
(-menuBackgroundColor, -menuItemBackgroundColor, -menuBorderColor
-menuBorderColorForEdge:isHorizontal:,
-drawsBorderForMenuItemCell:state:isHorizontal:,
-drawTitleForMenuItemCell:withFrame:inView:state:isHorizontal:,
-menuSeparatorInset): Added.
(-menuBarBackgroundColor, -menuBarBorderColor): Added but not yet used.
(-menuSeparatorColor): Renamed -menuSeparatorItemColor.
* Source/NSMenuItemCell.m
(-backgroundColor:): Changed to get the background color from
-menuItemBackgroundColor.
(-themeControlState): Added.
(-drawTitleWithFrame:inView:): Moved drawing code to GSTheme.
Made separator menu item themable, by moving the drawing code from
NSMenuItemCell to a new method in GSThemeDrawing.
2011-11-13 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSImage.m (-bestRepresentationForDevice:): Fix last

View file

@ -877,40 +877,138 @@ APPKIT_EXPORT NSString *GSThemeWillDeactivateNotification;
roundedLeft: (BOOL)roundedLeft
roundedRight: (BOOL)roundedRight;
/**
* <p>Returns the color used to draw a menu view background.</p>
*
* <p>By default, looks up the color named <em>menuBackgroundColor</em>,
* otherwise returns the window background color.</p>
*
* <p>The returned color is used by
* -drawBackgroundForMenuView:withFrame:dirtyRect:horizontal:</p>
*
* <p>Can be overriden in subclasses to return a custom color.</p>
*/
- (NSColor *) menuBackgroundColor;
/**
* <p>Returns the color used to draw a menu item background.</p>
*
* The menu item background is drawn atop the menu background.
*
* <p>By default, looks up the color named <em>menuItemBackgroundColor</em>,
* otherwise returns the control background color.<br />
* When selected or highlighted, the background color is provided by
* [NSColor+selectedMenuItemColor].</p>
*
* <p>The returned value used by
* -drawBorderAndBackgroundForMenuItemCell:withFrame:inView:state:isHorizontal:
* and [NSMenuItemCell-backgroundColor].</p>
*
* <p>Can be overriden in subclasses to return a custom color.</p>
*/
- (NSColor *) menuItemBackgroundColor;
- (NSColor *) menuBarBackgroundColor;
- (NSColor *) menuBarBorderColor;
/**
* <p>Returns the color used to draw a menu view border.</p>
*
* <p>By default, looks up the color named <em>menuBorderColor</em>,
* otherwise returns the dark gray color.</p>
*
* <p>The returned color is used by
* -drawBackgroundForMenuView:withFrame:dirtyRect:horizontal:</p>
*
* <p>Can be overriden in subclasses to return a custom color.</p>
*/
- (NSColor *) menuBorderColor;
/**
* <p>Returns a color to draw each edge in a menu view border.</p>
*
* <p>By default, returns -menuBorderColor for the upper and left edges of a
* vertical menu, or for the bottom edge of a horizontal one.</p>
*
* <p>The returned edge color is used by
* -drawBackgroundForMenuView:withFrame:dirtyRect:horizontal:</p>
*
* <p>Can be overriden in subclasses to return a custom color per edge.</p>
*/
- (NSColor *) menuBorderColorForEdge: (NSRectEdge)edge
isHorizontal: (BOOL)horizontal;
- (void) drawBackgroundForMenuView: (NSMenuView*)menuView
withFrame: (NSRect)bounds
dirtyRect: (NSRect)dirtyRect
horizontal: (BOOL)horizontal;
/**
* <p>Returns whether the menu item border should be drawn or not.</p>
*
* <p>By default, returns [NSMenuItemCell-isBordered] value. The value is NO
* when the menu is horizontal, YES when vertical.</p>
*
* <p>The returned value used by
* -drawBorderAndBackgroundForMenuItemCell:withFrame:inView:state:isHorizontal:</p>
*
* <p>Can be overriden in subclasses.</p>
*/
- (BOOL) drawsBorderForMenuItemCell: (NSMenuItemCell *)cell
state: (GSThemeControlState)state
isHorizontal: (BOOL)horizontal;
// menu item cell drawing method
- (void) drawBorderAndBackgroundForMenuItemCell: (NSMenuItemCell *)cell
withFrame: (NSRect)cellFrame
inView: (NSView *)controlView
state: (GSThemeControlState)state
isHorizontal: (BOOL)isHorizontal;
/**
* <p>Draws the menu item title.</p>
*
* <p>Can be overriden to customize the text font, size and position.<br />
* You can use <code>[[cell menuItem] title]</code> to get the title.</p>
*
* <p>The title color is mapped to the theme state as described below:</p>
* <deflist>
* <item>GSThemeSelectedState</item><desc>[NSColor+selectedMenuItemTextColor]</desc>
* <item>GSThemeDisabledState</item><desc>[NSColor+controlTextColor] or
* [NSColor+disabledControlTextColor]</desc>
* </deflist>
*/
- (void) drawTitleForMenuItemCell: (NSMenuItemCell *)cell
withFrame: (NSRect)cellFrame
inView: (NSView *)controlView
state: (GSThemeControlState)state
isHorizontal: (BOOL)isHorizontal;
/**
* <p>Returns the color used to draw a separator line in a menu.</p>
*
* <p>By default, looks up the color named <em>menuSeparatorItemColor</em>,
* otherwise returns the black color.</p>
* <p>By default, looks up the color named <em>menuSeparatorColor</em>,
* otherwise returns nil.</p>
*
* <p>The returned color is used by
* -drawSeparatorItemForMenuItemCell:withFrame:inView:isHorizontal:</p>
*
* <p>Can be overriden in subclasses to return a custom color.</p>
*/
- (NSColor *) menuSeparatorItemColor;
- (NSColor *) menuSeparatorColor;
/**
* <p>Returns the left and right inset used to draw a separator line in a menu.</p>
*
* <p>By default, returns 3.0.</p>
*
* <p>The returned color is used by
* -drawSeparatorItemForMenuItemCell:withFrame:inView:isHorizontal:</p>
*
* <p>Can be overriden in subclasses to return a custom value.</p>
*/
- (CGFloat) menuSeparatorInset;
/**
* <p>Draws a separator between normal menu items in a menu.</p>
*
* <p>Each separator corresponds to a menu item that returns YES to
* -isSeparatorItem</p>
*
* <p>You can provide an image tile named <em>GSMenuSeparatoritem</em> to
* <p>You can provide an image tile named <em>GSMenuSeparatorItem</em> to
* draw the separator.</br>
* Can be overriden in subclasses to customize the drawing.</p>
*
* <p>See also -menuSeparatorItemColor</p>
* <p>See also -menuSeparatorColor and -menuSeparatorInset</p>
*/
- (void) drawSeparatorItemForMenuItemCell: (NSMenuItemCell *)cell
withFrame: (NSRect)cellFrame

View file

@ -393,6 +393,7 @@ typedef struct {
cls = self;
}
instance = [[cls alloc] initWithBundle: bundle];
NSLog(@"Instantiated %@ from %@ in %@", instance, cls, [bundle bundlePath]);
return AUTORELEASE(instance);
}

View file

@ -803,6 +803,75 @@
}
}
- (NSColor *) menuBackgroundColor
{
NSColor *color = [self colorNamed: @"menuBackgroundColor"
state: GSThemeNormalState];
if (color == nil)
{
color = [NSColor windowBackgroundColor];
}
return color;
}
- (NSColor *) menuItemBackgroundColor
{
NSColor *color = [self colorNamed: @"menuItemBackgroundColor"
state: GSThemeNormalState];
if (color == nil)
{
color = [NSColor controlBackgroundColor];
}
return color;
}
- (NSColor *) menuBorderColor
{
NSColor *color = [self colorNamed: @"menuBorderColor"
state: GSThemeNormalState];
if (color == nil)
{
color = [NSColor darkGrayColor];
}
return color;
}
- (NSColor *) menuBarBackgroundColor
{
NSColor *color = [self colorNamed: @"menuBarBackgroundColor"
state: GSThemeNormalState];
if (color == nil)
{
color = [self menuBackgroundColor];
}
return color;
}
- (NSColor *) menuBarBorderColor
{
NSColor *color = [self colorNamed: @"menuBarBorderColor"
state: GSThemeNormalState];
if (color == nil)
{
color = [self menuBorderColor];
}
return color;
}
- (NSColor *) menuBorderColorForEdge: (NSRectEdge)edge isHorizontal: (BOOL)horizontal
{
if (horizontal && edge == NSMinYEdge)
{
return [self menuBorderColor];
}
else if (edge == NSMinXEdge || edge == NSMaxYEdge)
{
// Draw the dark gray upper left lines.
return [self menuBorderColor];
}
return nil;
}
- (void) drawBackgroundForMenuView: (NSMenuView*)menuView
withFrame: (NSRect)bounds
dirtyRect: (NSRect)dirtyRect
@ -814,25 +883,15 @@
if (tiles == nil)
{
NSRectEdge sides[2];
float grays[] = {NSDarkGray, NSDarkGray};
NSRectEdge sides[4] = { NSMinXEdge, NSMaxYEdge, NSMaxXEdge, NSMinYEdge };
NSColor *colors[] = {[self menuBorderColorForEdge: NSMinXEdge isHorizontal: horizontal],
[self menuBorderColorForEdge: NSMaxYEdge isHorizontal: horizontal],
[self menuBorderColorForEdge: NSMaxXEdge isHorizontal: horizontal],
[self menuBorderColorForEdge: NSMinYEdge isHorizontal: horizontal]};
[[NSColor windowBackgroundColor] set];
NSRectFill(NSIntersectionRect(bounds, dirtyRect));
if (horizontal == YES)
{
sides[0] = NSMinYEdge;
sides[1] = NSMinYEdge;
NSDrawTiledRects(bounds, dirtyRect, sides, grays, 2);
}
else
{
sides[0] = NSMinXEdge;
sides[1] = NSMaxYEdge;
// Draw the dark gray upper left lines.
NSDrawTiledRects(bounds, dirtyRect, sides, grays, 2);
}
[[self menuBackgroundColor] set];
NSRectFill(NSIntersectionRect(bounds, dirtyRect));
NSDrawColorTiledRects(bounds, dirtyRect, sides, colors, 4);
}
else
{
@ -842,6 +901,13 @@
}
}
- (BOOL) drawsBorderForMenuItemCell: (NSMenuItemCell *)cell
state: (GSThemeControlState)state
isHorizontal: (BOOL)horizontal
{
return [cell isBordered];
}
- (void) drawBorderAndBackgroundForMenuItemCell: (NSMenuItemCell *)cell
withFrame: (NSRect)cellFrame
inView: (NSView *)controlView
@ -854,7 +920,6 @@
if (tiles == nil)
{
NSColor *backgroundColor = [cell backgroundColor];
if (isHorizontal)
@ -869,8 +934,12 @@
[backgroundColor set];
NSRectFill(cellFrame);
if (![cell isBordered])
return;
if (![self drawsBorderForMenuItemCell: cell
state: state
isHorizontal: isHorizontal])
{
return;
}
if (state == GSThemeSelectedState)
{
@ -889,17 +958,26 @@
}
}
- (NSColor *) menuSeparatorItemColor
- (NSColor *) menuSeparatorColor
{
NSColor *color = [self colorNamed: @"menuSeparatorItemColor"
NSColor *color = [self colorNamed: @"menuSeparatorColor"
state: GSThemeNormalState];
if (color == nil)
NSInterfaceStyle style = NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil);
// TODO: Remove the style check... Windows theming should be in a subclass
// probably
if (color == nil && style == NSWindows95InterfaceStyle)
{
color = [NSColor blackColor];
}
return color;
}
- (CGFloat) menuSeparatorInset
{
return 3.0;
}
- (void) drawSeparatorItemForMenuItemCell: (NSMenuItemCell *)cell
withFrame: (NSRect)cellFrame
inView: (NSView *)controlView
@ -909,23 +987,20 @@
if (tiles == nil)
{
NSInterfaceStyle style = NSInterfaceStyleForKey(@"NSMenuInterfaceStyle", nil);
if (style == NSMacintoshInterfaceStyle || style == NSWindows95InterfaceStyle)
{
NSBezierPath *path = [NSBezierPath bezierPath];
NSPoint start = NSMakePoint(3, cellFrame.size.height / 2 +
cellFrame.origin.y);
NSPoint end = NSMakePoint(cellFrame.size.width - 3,
cellFrame.size.height / 2 + cellFrame.origin.y);
NSBezierPath *path = [NSBezierPath bezierPath];
CGFloat inset = [self menuSeparatorInset];
NSPoint start = NSMakePoint(inset, cellFrame.size.height / 2 +
cellFrame.origin.y + 0.5);
NSPoint end = NSMakePoint(cellFrame.size.width - inset,
cellFrame.size.height / 2 + cellFrame.origin.y + 0.5);
[[NSColor blackColor] set];
[[self menuSeparatorColor] set];
[path moveToPoint: start];
[path lineToPoint: end];
[path setLineWidth: 0.0];
[path moveToPoint: start];
[path lineToPoint: end];
[path stroke];
}
[path stroke];
}
else
{
@ -935,6 +1010,16 @@
}
}
- (void) drawTitleForMenuItemCell: (NSMenuItemCell *)cell
withFrame: (NSRect)cellFrame
inView: (NSView *)controlView
state: (GSThemeControlState)state
isHorizontal: (BOOL)isHorizontal
{
[cell _drawText: [[cell menuItem] title]
inFrame: [cell titleRectForBounds: cellFrame]];
}
- (Class) titleViewClassForMenuView: (NSMenuView *)aMenuView
{
return [GSTitleView class];

View file

@ -163,6 +163,7 @@ static NSString *commandKeyString = @"#";
state = GSThemeSelectedState;
}
// TODO: Make the color lookup simpler.
color = [[GSTheme theme] colorNamed: @"NSMenuItem" state: state];
if (color == nil)
{
@ -172,7 +173,7 @@ static NSString *commandKeyString = @"#";
}
else
{
color = [NSColor controlBackgroundColor];
color = [[GSTheme theme] menuItemBackgroundColor];
}
}
@ -657,11 +658,7 @@ static NSString *commandKeyString = @"#";
}
}
//
// Drawing.
//
- (void) drawBorderAndBackgroundWithFrame: (NSRect)cellFrame
inView: (NSView *)controlView
- (GSThemeControlState) themeControlState
{
unsigned mask;
GSThemeControlState state = GSThemeNormalState;
@ -695,10 +692,19 @@ static NSString *commandKeyString = @"#";
state = GSThemeSelectedState;
}
return state;
}
//
// Drawing.
//
- (void) drawBorderAndBackgroundWithFrame: (NSRect)cellFrame
inView: (NSView *)controlView
{
[[GSTheme theme] drawBorderAndBackgroundForMenuItemCell: self
withFrame: cellFrame
inView: controlView
state: state
state: [self themeControlState]
isHorizontal: [_menuView isHorizontal]];
}
@ -792,8 +798,11 @@ static NSString *commandKeyString = @"#";
- (void) drawTitleWithFrame: (NSRect)cellFrame
inView: (NSView *)controlView
{
[self _drawText: [_menuItem title]
inFrame: [self titleRectForBounds: cellFrame]];
[[GSTheme theme] drawTitleForMenuItemCell: self
withFrame: cellFrame
inView: controlView
state: [self themeControlState]
isHorizontal: [_menuView isHorizontal]];
}
- (void) _drawBorderAndBackgroundWithFrame: (NSRect)cellFrame inView: (NSView*)controlView