Some moves towards making scrollers more themable

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27518 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2009-01-05 09:43:25 +00:00
parent 99adecef26
commit 62492a9158
6 changed files with 179 additions and 60 deletions

View file

@ -2,9 +2,15 @@
* Headers/Additions/GNUstepGUI/GSTheme.h:
* Source/GSTheme.m:
* Source/NSButtonCell.m:
* Source/NSScroller.m:
* Source/GSThemeDrawing.m:
Add methods to name specific elements in the gui so that we can
locate resources for them and so that override methods can handle
them specially.
Change tile image lookup for improved consistency/simplicity and
to use new naming.
Add naming of component parts of a scroller.
2009-01-04 18:32-EST Gregory John Casamento <greg_casamento@yahoo.com>

View file

@ -155,6 +155,18 @@
@class NSMenuView;
@class GSDrawTiles;
/* Names for the component parts of a scroller,
* allowing tiles and/or colors to be set for them.
*/
APPKIT_EXPORT NSString *GSScrollerDownArrow;
APPKIT_EXPORT NSString *GSScrollerHorizontalKnob;
APPKIT_EXPORT NSString *GSScrollerHorizontalSlot;
APPKIT_EXPORT NSString *GSScrollerLeftArrow;
APPKIT_EXPORT NSString *GSScrollerRightArrow;
APPKIT_EXPORT NSString *GSScrollerUpArrow;
APPKIT_EXPORT NSString *GSScrollerVerticalKnob;
APPKIT_EXPORT NSString *GSScrollerVerticalSlot;
/**
* This defines how the values in a tile array should be used when
* drawing a rectangle. Mostly this just effects the center, middle
@ -379,8 +391,8 @@ APPKIT_EXPORT NSString *GSThemeWillDeactivateNotification;
- (NSString*) name;
/** Returns the name used to locate theming resources for a particular gui
* element. If no name has been set for the particular object, the name
* for the class of object is returned.
* element. If no name has been set for the particular object this method
* returns nil.
*/
- (NSString*) nameForElement: (id)anObject;
@ -389,12 +401,16 @@ APPKIT_EXPORT NSString *GSThemeWillDeactivateNotification;
- (void) setName: (NSString*)aString;
/** Set the name that is used to identify theming resources for a particular
* control or other gui element. The name set for a specific element will
* override the default (the name of the class of the element), and this is
* used so that where an element is part of a control, it can be displayed
* differently from the same class of element used outside that control.<br />
* control or other gui element. This is used so that where an element is
* part of a control it can be displayed differently from the same class of
* element used outside that control.<br />
* Supplying a nil value for aString simply removes any name setting for
* anObject.
* anObject.<br />
* Supplying nil for anObject is illegal (raises an exception) unless
* the value of aString is also nil (and the method does nothing).<br />
* Any control which uses this method to set names for subsidiary elements
* must also make sure to remove the name mapping before that element is
* deallocated.
*/
- (void) setName: (NSString*)aString forElement: (id)anObject;
@ -417,10 +433,14 @@ APPKIT_EXPORT NSString *GSThemeWillDeactivateNotification;
* information to draw user interface elements. The tile information
* returned by this method can be passed to the
* -fillRect:withTiles:background:fillStyle: method.<br />
* The elementState argument specifies the state for which tiles are
* requested.<br />
* The useCache argument controls whether the information is retrieved
* from cache or regenerated from information in the theme bundle.
*/
- (GSDrawTiles*) tilesNamed: (NSString*)aName cache: (BOOL)useCache;
- (GSDrawTiles*) tilesNamed: (NSString*)aName
state: (GSThemeControlState)elementState
cache: (BOOL)useCache;
@end
/**
@ -441,8 +461,9 @@ APPKIT_EXPORT NSString *GSThemeWillDeactivateNotification;
/**
* Amount by which the button is inset by the border.
*/
- (NSSize) buttonBorderForStyle: (int)style
state: (GSThemeControlState)state;
- (NSSize) buttonBorderForCell: (NSCell*)cell
style: (int)style
state: (GSThemeControlState)state;
/**
* Draws the indicator (normally a dotted rectangle) to show that

View file

@ -57,6 +57,15 @@
#import "AppKit/PSOperators.h"
#import "GSThemePrivate.h"
// Scroller part names
NSString *GSScrollerDownArrow = @"GSScrollerDownArrow";
NSString *GSScrollerHorizontalKnob = @"GSScrollerHorizontalKnob";
NSString *GSScrollerHorizontalSlot = @"GSScrollerHorizontalSlot";
NSString *GSScrollerLeftArrow = @"GSScrollerLeftArrow";
NSString *GSScrollerRightArrow = @"GSScrollerRightArrow";
NSString *GSScrollerUpArrow = @"GSScrollerUpArrow";
NSString *GSScrollerVerticalKnob = @"GSScrollerVerticalKnob";
NSString *GSScrollerVerticalSlot = @"GSScrollerVerticalSlot";
NSString *GSThemeDidActivateNotification
= @"GSThemeDidActivateNotification";
@ -80,18 +89,22 @@ typedef struct {
NSBundle *bundle;
NSColorList *colors;
NSMutableDictionary *images;
NSMutableDictionary *tiles;
NSMutableDictionary *normalTiles;
NSMutableDictionary *highlightedTiles;
NSMutableDictionary *selectedTiles;
NSImage *icon;
NSString *name;
} internal;
#define _internal ((internal*)_reserved)
#define _bundle _internal->bundle
#define _colors _internal->colors
#define _images _internal->images
#define _tiles _internal->tiles
#define _icon _internal->icon
#define _name _internal->name
#define _internal ((internal*)_reserved)
#define _bundle _internal->bundle
#define _colors _internal->colors
#define _images _internal->images
#define _normalTiles _internal->normalTiles
#define _highlightedTiles _internal->highlightedTiles
#define _selectedTiles _internal->selectedTiles
#define _icon _internal->icon
#define _name _internal->name
+ (void) defaultsDidChange: (NSNotification*)n
{
@ -322,7 +335,7 @@ typedef struct {
/*
* We could cache tile info here, but it's probably better for the
* tilesNamed:cache: method to do it lazily.
* tilesNamed:state:cache: method to do it lazily.
*/
/*
@ -475,7 +488,9 @@ typedef struct {
RELEASE(_bundle);
RELEASE(_colors);
RELEASE(_images);
RELEASE(_tiles);
RELEASE(_normalTiles);
RELEASE(_highlightedTiles);
RELEASE(_selectedTiles);
RELEASE(_icon);
NSZoneFree ([self zone], _reserved);
}
@ -514,7 +529,9 @@ typedef struct {
ASSIGN(_bundle, bundle);
_images = [NSMutableDictionary new];
_tiles = [NSMutableDictionary new];
_normalTiles = [NSMutableDictionary new];
_highlightedTiles = [NSMutableDictionary new];
_selectedTiles = [NSMutableDictionary new];
ASSIGN(_name,
[[[_bundle bundlePath] lastPathComponent] stringByDeletingPathExtension]);
@ -539,10 +556,6 @@ typedef struct {
{
NSString *name = (NSString*)NSMapGet(names, (void*)anObject);
if (name == nil)
{
name = NSStringFromClass([anObject class]);
}
return name;
}
@ -556,18 +569,26 @@ typedef struct {
- (void) setName: (NSString*)aString forElement: (id)anObject
{
if (anObject == nil)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] nil object supplied",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
if (aString == nil)
{
if (anObject == nil)
{
/* Ignore this ... it's most likely a partially initialised
* control being deallocated and removing the name for a
* subsidiary item which was never allocated in the first place.
*/
return;
}
NSMapRemove(names, (void*)anObject);
}
else
{
if (anObject == nil)
{
[NSException raise: NSInvalidArgumentException
format: @"[%@-%@] nil object supplied",
NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
}
NSMapInsert(names, (void*)anObject, (void*)aString);
}
}
@ -577,15 +598,45 @@ typedef struct {
return [GSThemeInspector sharedThemeInspector];
}
- (GSDrawTiles*) tilesNamed: (NSString*)aName cache: (BOOL)useCache
- (GSDrawTiles*) tilesNamed: (NSString*)aName
state: (GSThemeControlState)elementState
cache: (BOOL)useCache
{
GSDrawTiles *tiles;
GSDrawTiles *tiles;
NSMutableDictionary *cache;
tiles = (useCache == YES) ? [_tiles objectForKey: aName] : nil;
switch (elementState)
{
case GSThemeNormalState:
cache = _normalTiles;
break;
case GSThemeHighlightedState:
cache = _highlightedTiles;
break;
case GSThemeSelectedState:
cache = _selectedTiles;
break;
}
tiles = (useCache == YES) ? [cache objectForKey: aName] : nil;
if (tiles == nil)
{
NSDictionary *info;
NSImage *image;
NSString *fullName;
switch (elementState)
{
case GSThemeNormalState:
fullName = aName;
break;
case GSThemeHighlightedState:
fullName = [aName stringByAppendingString: @"Highlighted"];
break;
case GSThemeSelectedState:
fullName = [aName stringByAppendingString: @"Selected"];
break;
}
/* The GSThemeTiles entry in the info dictionary should be a
* dictionary containing information about each set of tiles.
@ -595,7 +646,7 @@ typedef struct {
* VerticalDivision Where to divide the image into rows.
*/
info = [self infoDictionary];
info = [[info objectForKey: @"GSThemeTiles"] objectForKey: aName];
info = [[info objectForKey: @"GSThemeTiles"] objectForKey: fullName];
if ([info isKindOfClass: [NSDictionary class]] == YES)
{
float x;
@ -639,7 +690,7 @@ typedef struct {
{
NSString *ext = [imageTypes objectAtIndex: count];
imagePath = [_bundle pathForResource: aName
imagePath = [_bundle pathForResource: fullName
ofType: ext
inDirectory: @"ThemeTiles"];
if (imagePath != nil)
@ -657,11 +708,11 @@ typedef struct {
if (tiles == nil)
{
[_tiles setObject: null forKey: aName];
[cache setObject: null forKey: aName];
}
else
{
[_tiles setObject: tiles forKey: aName];
[cache setObject: tiles forKey: aName];
RELEASE(tiles);
}
}

View file

@ -41,23 +41,27 @@
{
GSDrawTiles *tiles = nil;
NSColor *color = nil;
NSString *name = [self nameForElement: cell];
if (name == nil)
{
name = @"NSButton";
}
if (state == GSThemeNormalState)
{
tiles = [self tilesNamed: @"NSButtonNormal" cache: YES];
color = [NSColor controlBackgroundColor];
}
else if (state == GSThemeHighlightedState)
{
tiles = [self tilesNamed: @"NSButtonHighlighted" cache: YES];
color = [NSColor selectedControlColor];
}
else if (state == GSThemeSelectedState)
{
tiles = [self tilesNamed: @"NSButtonPushed" cache: YES];
color = [NSColor selectedControlColor];
}
tiles = [self tilesNamed: name state: state cache: YES];
if (tiles == nil)
{
switch (style)
@ -124,24 +128,19 @@
}
}
- (NSSize) buttonBorderForStyle: (int)style
state: (GSThemeControlState)state
- (NSSize) buttonBorderForCell: (NSCell*)cell
style: (int)style
state: (GSThemeControlState)state
{
GSDrawTiles *tiles = nil;
NSString *name = [self nameForElement: cell];
if (state == GSThemeNormalState)
if (name == nil)
{
tiles = [self tilesNamed: @"NSButtonNormal" cache: YES];
}
else if (state == GSThemeHighlightedState)
{
tiles = [self tilesNamed: @"NSButtonHighlighted" cache: YES];
}
else if (state == GSThemeSelectedState)
{
tiles = [self tilesNamed: @"NSButtonPushed" cache: YES];
name = @"NSButton";
}
tiles = [self tilesNamed: name state: state cache: YES];
if (tiles == nil)
{
switch (style)

View file

@ -1311,8 +1311,9 @@ typedef struct _GSButtonCellFlags
buttonState = GSThemeSelectedState;
}
borderSize = [[GSTheme theme] buttonBorderForStyle: _bezel_style
state: buttonState];
borderSize = [[GSTheme theme] buttonBorderForCell: self
style: _bezel_style
state: buttonState];
}
else
borderSize = NSZeroSize;
@ -1374,15 +1375,16 @@ typedef struct _GSButtonCellFlags
buttonState = GSThemeSelectedState;
}
borderSize = [[GSTheme theme] buttonBorderForStyle: _bezel_style
state: buttonState];
borderSize = [[GSTheme theme] buttonBorderForCell: self
style: _bezel_style
state: buttonState];
interiorFrame = NSInsetRect(theRect, borderSize.width, borderSize.height);
/* Pushed in buttons contents are displaced to the bottom right 1px. */
if (mask & NSPushInCellMask)
{
interiorFrame
= NSOffsetRect(interiorFrame, 1.0, [_control_view isFlipped] ? 1.0 : -1.0);
interiorFrame = NSOffsetRect(interiorFrame, 1.0,
[_control_view isFlipped] ? 1.0 : -1.0);
}
return interiorFrame;
}

View file

@ -336,6 +336,21 @@ static const float buttonsOffset = 2; // buttonsWidth = sw - buttonsOffset
return [self initWithFrame: NSZeroRect];
}
- (void) dealloc
{
GSTheme *theme = [GSTheme theme];
[theme setName: nil forElement: upCell];
[theme setName: nil forElement: downCell];
[theme setName: nil forElement: leftCell];
[theme setName: nil forElement: rightCell];
[theme setName: nil forElement: verticalKnobCell];
[theme setName: nil forElement: horizontalKnobCell];
[theme setName: nil forElement: verticalKnobSlotCell];
[theme setName: nil forElement: horizontalKnobSlotCell];
[super dealloc];
}
/**
* Cache images for scroll arrows and knob. If you override +scrollerWidth
* you may need to override this as well (to provide images for the new
@ -344,23 +359,48 @@ static const float buttonsOffset = 2; // buttonsWidth = sw - buttonsOffset
*/
- (void) drawParts
{
GSTheme *theme = [GSTheme theme] ;
GSTheme *theme;
if (upCell)
return;
theme = [GSTheme theme];
[theme setName: nil forElement: upCell];
ASSIGN(upCell ,[theme cellForScrollerArrow:
NSScrollerDecrementArrow horizontal:NO]);
[theme setName: GSScrollerUpArrow forElement: upCell];
[theme setName: nil forElement: downCell];
ASSIGN(downCell, [theme cellForScrollerArrow:
NSScrollerIncrementArrow horizontal:NO]);
[theme setName: GSScrollerDownArrow forElement: downCell];
[theme setName: nil forElement: leftCell];
ASSIGN(leftCell, [theme cellForScrollerArrow:
NSScrollerDecrementArrow horizontal:YES]);
[theme setName: GSScrollerLeftArrow forElement: leftCell];
[theme setName: nil forElement: rightCell];
ASSIGN(rightCell, [theme cellForScrollerArrow:
NSScrollerIncrementArrow horizontal:YES]);
[theme setName: GSScrollerRightArrow forElement: rightCell];
[theme setName: nil forElement: verticalKnobCell];
ASSIGN(verticalKnobCell, [theme cellForScrollerKnob: NO]);
[theme setName: GSScrollerVerticalKnob forElement: verticalKnobCell];
[theme setName: nil forElement: horizontalKnobCell];
ASSIGN(horizontalKnobCell, [theme cellForScrollerKnob: YES]);
[theme setName: GSScrollerHorizontalKnob forElement: horizontalKnobCell];
[theme setName: nil forElement: verticalKnobSlotCell];
ASSIGN(verticalKnobSlotCell, [theme cellForScrollerKnobSlot: NO]);
[theme setName: GSScrollerVerticalSlot forElement: verticalKnobSlotCell];
[theme setName: nil forElement: horizontalKnobSlotCell];
ASSIGN(horizontalKnobSlotCell, [theme cellForScrollerKnobSlot: YES]);
[theme setName: GSScrollerHorizontalSlot forElement: horizontalKnobSlotCell];
[downCell setContinuous: YES];
[downCell sendActionOn: (NSLeftMouseDownMask | NSPeriodicMask)];