Added support for providing custom theme control images (e.g. checkbox) in the same way we support it for tiles

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@36836 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Quentin Mathe 2013-07-04 15:46:11 +00:00
parent 461dcd25c9
commit da2351d2b2
5 changed files with 187 additions and 82 deletions

View file

@ -1,3 +1,14 @@
2013-07-04 Quentin Mathe <quentin.mathe@gmail.com>
* Headers/Additions/GNUstepGUI/GSTheme.h:
* Source/GSTheme.m:
Added new theme image constant image names.
* Source/NSImage.m (+imageNamed:, +_reloadCachedImages,
+_pathForImageNamed:): Added support for providing custom theme control
images in the same way that we support it for tiles. We now support a
GSThemeImages section in the theme Info.plist for all the images stored
inside a ThemeImages directory of the theme bundle.
2013-07-04 Richard Frith-Macdonald <rfm@gnu.org>
* config.make.in: Fix error in order of link/include directories

View file

@ -244,6 +244,9 @@
@class NSTabViewItem;
@class GSDrawTiles;
APPKIT_EXPORT NSString *GSSwitch;
APPKIT_EXPORT NSString *GSRadio;
/* First, declare names used for obtaining colors and/or tiles for specific
* controls and parts of controls.
*/

View file

@ -2,34 +2,48 @@
actual files where the GNUstep keeps them. The format is the "strings"
format and content is trivial. */
NSApplicationIcon = GNUstep;
NSSwitch = common_SwitchOff;
NSHighlightedSwitch = common_SwitchOn;
NSRadioButton = common_RadioOff;
NSHighlightedRadioButton = common_RadioOn;
AppleMenuImage = GNUstepMenuImage;
NSMenuCheckmark = common_2DCheckMark;
NSMenuArrow = common_3DArrowRight;
NSMenuMixedState = common_2DDash;
NSComboArrow = common_ComboBoxEllipsis;
GSClosedHandCursor = common_ClosedHandCursor;
GSOpenHandCursor = common_OpenHandCursor;
GSDragCopyCursor = common_copyCursor;
GSDragLinkCursor = common_linkCursor;
GSOperationNotAllowedCursor = common_noCursor;
GNUstep = NSApplicationIcon;
common_SwitchOff = GSSwitch;
NSSwitch = GSSwitch;
common_SwitchOn = GSSwitchSelected;
NSHighlightedSwitch = GSSwitchSelected;
common_RadioOff = GSRadio;
NSRadioButton = GSRadio;
common_RadioOn = GSRadioSelected;
NSHighlightedRadioButton = GSRadioSelected;
GNUstepMenuImage = GSApplicationMenuIcon;
AppleMenuImage = GSApplicationMenuIcon;
common_3DArrowRight = GSMenuArrow;
NSMenuArrow = GSMenuArrow;
common_2DCheckMark = GSMenuSelected;
NSMenuCheckmark = GSMenuSelected;
common_2DDash = GSMenuMixed;
NSMenuMixedState = GSMenuMixed;
common_ComboBoxEllipsis = GSComboArrow;
NSComboArrow = GSComboArrow;
common_ClosedHandCursor = GSClosedHandCursor;
common_OpenHandCursor = GSOpenHandCursor;
common_copyCursor = GSDragCopyCursor;
common_linkCursor = GSDragLinkCursor;
common_noCursor = GSOperationNotAllowedCursor;
/* Toolbar images */
NSToolbarCustomizeToolbarItemImage = common_ToolbarCustomizeToolbarItem;
NSToolbarPrint = common_Printer;
NSToolbarShowColors = common_ToolbarShowColorsItem;
NSToolbarShowFonts = common_ToolbarShowFontsItem;
common_ToolbarCustomizeToolbarItem = NSToolbarCustomizeToolbarItemImage;
common_Printer = NSToolbarPrint;
common_ToolbarShowColorsItem = NSToolbarShowColors;
common_ToolbarShowFontsItem = NSToolbarShowFonts;
/* Misc. */
NSColorPanel = common_ToolbarShowColorsItem;
NSComputer = common_Root_PC;
NSStopProgressTemplate = GSStop;
NSFontPanel = common_ToolbarShowFontsItem;
NSFolder = common_Folder;
NSInfo = common_Info;
common_ToolbarShowColorsItem = NSColorPanel;
common_Root_PC = NSComputer;
GSStop = NSStopProgressTemplate;
common_ToolbarShowFontsItem = NSFontPanel;
common_Folder = NSFolder;
common_Info = NSInfo;

View file

@ -64,6 +64,9 @@
#import "AppKit/PSOperators.h"
#import "GSThemePrivate.h"
NSString *GSSwitch = @"GSSwitch";
NSString *GSRadio = @"GSRadio";
// Scroller part names
NSString *GSScrollerDownArrow = @"GSScrollerDownArrow";
NSString *GSScrollerHorizontalKnob = @"GSScrollerHorizontalKnob";

View file

@ -201,17 +201,20 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
+ (id) imageNamed: (NSString *)aName
{
NSImage *image;
NSString *realName;
/* 2009-09-10 changed operation of nsmapping so that the loaded
* image is stored under the key 'aName', not under the mapped
* name. That way the image is created with the correct name and
* a later call to -setName: will work properly.
*/
[imageLock lock];
image = (NSImage*)[nameDict objectForKey: aName];
if (image == nil && aName != nil)
realName = [nsmapping objectForKey: aName];
if (realName == nil)
{
NSString *path = [self _pathForImageNamed: aName];
realName = aName;
}
image = (NSImage*)[nameDict objectForKey: realName];
if (image == nil && realName != nil)
{
NSString *path = [self _pathForImageNamed: realName];
if ([path length] != 0)
{
@ -219,12 +222,13 @@ repd_for_rep(NSArray *_reps, NSImageRep *rep)
initByReferencingFile: path];
if (image != nil)
{
[image setName: aName];
[image setName: realName];
image->_flags.archiveByName = YES;
AUTORELEASE(image);
}
}
}
IF_NO_GC([[image retain] autorelease]);
[imageLock unlock];
return image;
@ -1895,28 +1899,106 @@ iterate_reps_for_types(NSArray* imageReps, SEL method)
+ (void) _reloadCachedImages
{
NSString *name;
NSEnumerator *e;
NSEnumerator *e = [nameDict keyEnumerator];
[imageLock lock];
e = [nameDict keyEnumerator];
while ((name = [e nextObject]) != nil)
{
NSImage *image = [nameDict objectForKey: name];
NSString *path = [self _pathForImageNamed: name];
if (![path isEqual: image->_fileName])
//NSLog(@"Loaded image %@ from %@", name, path);
if (path != nil && ![path isEqual: image->_fileName])
{
/* Reset the existing image to use the contents of
* the specified file.
*/
[image _resetAndUseFromFile: path];
}
}
}
[imageLock unlock];
}
+ (NSString *) _pathForLibraryImageNamed: (NSString *)aName
ofType: (NSString *)ext
inDirectory: (NSString *)aDir
{
if (ext != nil)
{
return [NSBundle pathForLibraryResource: aName
ofType: ext
inDirectory: aDir];
}
NSEnumerator *e = [[self imageFileTypes] objectEnumerator];
id o = nil;
NSString *path = nil;
while ((o = [e nextObject]) != nil)
{
path = [NSBundle pathForLibraryResource: aName
ofType: o
inDirectory: aDir];
if (path != nil && [path length] != 0)
break;
}
return path;
}
+ (NSString *) _pathForImageNamed: (NSString *)aName
ofType: (NSString *)ext
subdirectory: (NSString *)aDir
inBundle: (NSBundle *)aBundle
{
if (ext != nil)
{
return [aBundle pathForResource: aName
ofType: ext
inDirectory: aDir];
}
NSEnumerator *e = [[self imageFileTypes] objectEnumerator];
id o = nil;
NSString *path = nil;
while ((o = [e nextObject]) != nil)
{
path = [aBundle pathForResource: aName
ofType: o
inDirectory: aDir];
if (path != nil && [path length] != 0)
break;
}
return path;
}
/*
* nsmapping.strings maps alternative image naming schemes to the GSTheme
* standard image naming scheme. For example, NSSwitch (from OpenStep) and
* common_SwitchOff (from GNUstep) are mapped to GSSwitch. In nameDict that
* tracks image instances, the keys are image names from GSTheme such as
* GSSwitch or additional icon names such NSApplicationIcon or
* NSToolbarShowColors. In the long run, it would be cleaner to move built-in
* theme images into a GNUstep.theme bundle.
*
* If you pass NSSwitch to +imageNamed:, nsmapping is used to get GSSwitch as
* the real name, then _pathForImageNamed: will look up the image first in the
* theme and fall back on the Library images. For the library images, we do a
* reverse lookup in nsmapping (using allKeysForObject:) to get the image file
* name (e.g. from GSSwitch to common_SwitchOff). This reverse lookup is
* similar to the one supported for getting image file names from the
* GSThemeImages section of a theme Info.plist. By creating a GNUstep.theme
* bundle, this reverse lookup could be handled by GSTheme rather than being
* treated as a special case in -_pathForImageNamed:.
*/
+ (NSString *) _pathForImageNamed: (NSString *)aName
{
NSString *realName = [nsmapping objectForKey: aName];
NSString *realName = aName;
NSString *ext;
NSString *path = nil;
NSBundle *main_bundle;
@ -1970,54 +2052,46 @@ iterate_reps_for_types(NSArray* imageReps, SEL method)
}
/* If not found then search in the theme */
if (!path)
if (path == nil)
{
NSBundle *themeBundle = [[GSTheme theme] bundle];
if (ext)
{
path = [themeBundle pathForResource: realName
ofType: ext
inDirectory: @"ThemeImages"];
}
else
{
id o, e;
e = [array objectEnumerator];
while ((o = [e nextObject]))
{
path = [themeBundle pathForResource: realName
ofType: o
inDirectory: @"ThemeImages"];
if (path != nil && [path length] != 0)
break;
}
}
NSDictionary *themeMapping =
[[[GSTheme theme] infoDictionary] objectForKey: @"GSThemeImages"];
NSString *mappedName = [themeMapping objectForKey: realName];
if (mappedName != nil)
{
// TODO: Could search the images if no file extension is provided
if ([[mappedName pathExtension] isEqual: @""])
{
NSLog(@"Theme image name %@ requires a file extension in the "
"theme Info.plist to get loaded.", mappedName);
}
path = [[[GSTheme theme] bundle] pathForResource: mappedName
ofType: nil
inDirectory: @"ThemeImages"];
}
}
/* If not found then search in system */
if (!path)
if (path == nil)
{
if (ext)
{
path = [NSBundle pathForLibraryResource: realName
ofType: ext
inDirectory: @"Images"];
}
else
{
id o, e;
e = [array objectEnumerator];
while ((o = [e nextObject]))
{
path = [NSBundle pathForLibraryResource: realName
ofType: o
inDirectory: @"Images"];
if (path != nil && [path length] != 0)
break;
}
}
path = [self _pathForLibraryImageNamed: realName ofType: ext inDirectory: @"Images"];
}
/* If not found then search in system using reverse nsmapping */
if (path == nil)
{
NSEnumerator *e = [[nsmapping allKeysForObject: realName] objectEnumerator];
NSString *aliasName = nil;
while ((aliasName = [e nextObject]) != nil)
{
path = [self _pathForLibraryImageNamed: aliasName ofType: ext inDirectory: @"Images"];
if (path != nil)
break;
}
}
return path;