mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-25 16:10:55 +00:00
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@11788 72102866-910b-0410-8b05-ffd578937521
436 lines
11 KiB
Objective-C
436 lines
11 KiB
Objective-C
/** <title>NSColorList</title>
|
|
|
|
<abstract>Manage named lists of NSColors.</abstract>
|
|
|
|
Copyright (C) 1996, 2000 Free Software Foundation, Inc.
|
|
|
|
Author: Scott Christley <scottc@net-community.com>
|
|
Date: 1996
|
|
Author: Nicola Pero <n.pero@mi.flashnet.it>
|
|
Date: January 2000
|
|
|
|
This file is part of the GNUstep GUI Library.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, write to the Free Software Foundation,
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <gnustep/gui/config.h>
|
|
#include <Foundation/NSNotification.h>
|
|
#include <Foundation/NSLock.h>
|
|
#include <Foundation/NSDictionary.h>
|
|
#include <Foundation/NSArchiver.h>
|
|
#include <Foundation/NSException.h>
|
|
#include <Foundation/NSFileManager.h>
|
|
#include <Foundation/NSPathUtilities.h>
|
|
#include <Foundation/NSString.h>
|
|
|
|
#include <AppKit/NSColorList.h>
|
|
#include <AppKit/NSColor.h>
|
|
#include <AppKit/AppKitExceptions.h>
|
|
|
|
// The list of available color lists is created only once -- this has
|
|
// a drawback, that you need to restart your program to get the color
|
|
// lists read again.
|
|
static NSMutableArray *_gnustep_available_color_lists = nil;
|
|
static NSLock *_gnustep_color_list_lock = nil;
|
|
|
|
@implementation NSColorList
|
|
|
|
//
|
|
// Class methods
|
|
//
|
|
+ (void)initialize
|
|
{
|
|
if (self == [NSColorList class])
|
|
{
|
|
[self setVersion: 2];
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Private Method which loads the color lists.
|
|
* Invoke if _gnustep_available_color_lists == nil
|
|
* before any operation with that object or its lock.
|
|
*
|
|
* The aim is to defer reading the available color lists
|
|
* till we really need to, so that only programs which really use
|
|
* this feature get the overhead.
|
|
*/
|
|
+ (void) _loadAvailableColorLists
|
|
{
|
|
NSString *dir;
|
|
NSString *file;
|
|
NSEnumerator *e;
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
NSDirectoryEnumerator *de;
|
|
NSColorList *newList;
|
|
|
|
// Create the global array of color lists
|
|
_gnustep_available_color_lists = [[NSMutableArray alloc] init];
|
|
|
|
/*
|
|
* Load color lists found in standard paths into the array
|
|
* FIXME: Check exactly where in the directory tree we should scan.
|
|
*/
|
|
e = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
|
|
NSAllDomainsMask, YES) objectEnumerator];
|
|
|
|
while ((dir = (NSString *)[e nextObject]))
|
|
{
|
|
dir = [dir stringByAppendingPathComponent: @"Colors"];
|
|
de = [fm enumeratorAtPath: dir];
|
|
while ((file = [de nextObject]))
|
|
{
|
|
if ([[file pathExtension] isEqualToString: @"clr"])
|
|
{
|
|
file = [file stringByDeletingPathExtension];
|
|
newList = AUTORELEASE ([[NSColorList alloc] initWithName: file
|
|
fromFile: dir]);
|
|
[_gnustep_available_color_lists addObject: newList];
|
|
}
|
|
}
|
|
}
|
|
|
|
// And create its access lock
|
|
_gnustep_color_list_lock = [[NSLock alloc] init];
|
|
}
|
|
|
|
/*
|
|
* Getting All Color Lists
|
|
*/
|
|
+ (NSArray*) availableColorLists
|
|
{
|
|
NSArray *a;
|
|
|
|
if (_gnustep_available_color_lists == nil)
|
|
[NSColorList _loadAvailableColorLists];
|
|
|
|
// Serialize access to color list
|
|
[_gnustep_color_list_lock lock];
|
|
|
|
a = [NSArray arrayWithArray: _gnustep_available_color_lists];
|
|
|
|
[_gnustep_color_list_lock unlock];
|
|
|
|
return a;
|
|
}
|
|
|
|
/*
|
|
* Getting a Color List by Name
|
|
*/
|
|
+ (NSColorList *) colorListNamed: (NSString *)name
|
|
{
|
|
NSColorList *r;
|
|
NSEnumerator *e;
|
|
BOOL found = NO;
|
|
|
|
if (_gnustep_available_color_lists == nil)
|
|
[NSColorList _loadAvailableColorLists];
|
|
|
|
// Serialize access to color list
|
|
[_gnustep_color_list_lock lock];
|
|
|
|
e = [_gnustep_available_color_lists objectEnumerator];
|
|
|
|
while ((r = (NSColorList *)[e nextObject]))
|
|
{
|
|
if ([[r name] isEqualToString: name])
|
|
{
|
|
found = YES;
|
|
break;
|
|
}
|
|
}
|
|
|
|
[_gnustep_color_list_lock unlock];
|
|
|
|
if (found)
|
|
return r;
|
|
else
|
|
return nil;
|
|
}
|
|
|
|
/*
|
|
* Instance methods
|
|
*/
|
|
- (id) initWithName: (NSString *)name
|
|
{
|
|
return [self initWithName: name
|
|
fromFile: nil];
|
|
}
|
|
|
|
- (id) initWithName: (NSString *)name
|
|
fromFile: (NSString *)path
|
|
{
|
|
NSColorList *cl;
|
|
BOOL could_load = NO;
|
|
|
|
ASSIGN (_name, name);
|
|
|
|
if (path != nil)
|
|
{
|
|
ASSIGN (_fullFileName, [[path stringByAppendingPathComponent: name]
|
|
stringByAppendingPathExtension: @"clr"]);
|
|
|
|
// Unarchive the color list
|
|
|
|
// TODO [Optm]: Rewrite to initialize directly without unarchiving
|
|
// in another object
|
|
|
|
cl = (NSColorList*)[NSUnarchiver unarchiveObjectWithFile: _fullFileName];
|
|
|
|
if (cl && [cl isKindOfClass: [NSColorList class]])
|
|
{
|
|
could_load = YES;
|
|
|
|
_is_editable = [[NSFileManager defaultManager]
|
|
isWritableFileAtPath: _fullFileName];
|
|
|
|
ASSIGN(_colorDictionary, [NSMutableDictionary
|
|
dictionaryWithDictionary: cl->_colorDictionary]);
|
|
|
|
ASSIGN(_orderedColorKeys, [NSMutableArray
|
|
arrayWithArray: cl->_orderedColorKeys]);
|
|
}
|
|
}
|
|
|
|
if (could_load == NO)
|
|
{
|
|
_fullFileName = nil;
|
|
_colorDictionary = [[NSMutableDictionary alloc] init];
|
|
_orderedColorKeys = [[NSMutableArray alloc] init];
|
|
_is_editable = YES;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
RELEASE (_name);
|
|
TEST_RELEASE (_fullFileName);
|
|
RELEASE (_colorDictionary);
|
|
RELEASE (_orderedColorKeys);
|
|
[super dealloc];
|
|
}
|
|
|
|
/*
|
|
* Getting a Color List by Name
|
|
*/
|
|
- (NSString *) name
|
|
{
|
|
return _name;
|
|
}
|
|
|
|
/*
|
|
* Managing Colors by Key
|
|
*/
|
|
- (NSArray *) allKeys
|
|
{
|
|
return [NSArray arrayWithArray: _orderedColorKeys];
|
|
}
|
|
|
|
- (NSColor *) colorWithKey: (NSString *)key
|
|
{
|
|
return [_colorDictionary objectForKey: key];
|
|
}
|
|
|
|
- (void) insertColor: (NSColor *)color
|
|
key: (NSString *)key
|
|
atIndex: (unsigned)location
|
|
{
|
|
if (_is_editable == NO)
|
|
[NSException raise: NSColorListNotEditableException
|
|
format: @"Color list cannot be edited\n"];
|
|
|
|
[_colorDictionary setObject: color forKey: key];
|
|
[_orderedColorKeys removeObject: key];
|
|
[_orderedColorKeys insertObject: key atIndex: location];
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
postNotificationName: NSColorListChangedNotification
|
|
object: self];
|
|
}
|
|
|
|
- (void) removeColorWithKey: (NSString *)key
|
|
{
|
|
if (_is_editable == NO)
|
|
[NSException raise: NSColorListNotEditableException
|
|
format: @"Color list cannot be edited\n"];
|
|
|
|
[_colorDictionary removeObjectForKey: key];
|
|
[_orderedColorKeys removeObject: key];
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
postNotificationName: NSColorListChangedNotification
|
|
object: self];
|
|
}
|
|
|
|
- (void) setColor: (NSColor *)aColor
|
|
forKey: (NSString *)key
|
|
{
|
|
if (_is_editable == NO)
|
|
[NSException raise: NSColorListNotEditableException
|
|
format: @"Color list cannot be edited\n"];
|
|
|
|
[_colorDictionary setObject: aColor forKey: key];
|
|
|
|
if ([_orderedColorKeys containsObject: key] == NO)
|
|
[_orderedColorKeys addObject: key];
|
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
postNotificationName: NSColorListChangedNotification
|
|
object: self];
|
|
}
|
|
|
|
/*
|
|
* Editing
|
|
*/
|
|
- (BOOL) isEditable
|
|
{
|
|
return _is_editable;
|
|
}
|
|
|
|
/*
|
|
* Writing and Removing Files
|
|
*/
|
|
- (BOOL) writeToFile: (NSString *)path
|
|
{
|
|
NSFileManager *fm = [NSFileManager defaultManager];
|
|
NSString *tmpPath;
|
|
BOOL isDir;
|
|
BOOL success;
|
|
BOOL path_is_standard = YES;
|
|
|
|
/*
|
|
* We need to initialize before saving, to avoid the new file being
|
|
* counted as a different list thus making us appear twice
|
|
*/
|
|
if (_gnustep_available_color_lists == nil)
|
|
[NSColorList _loadAvailableColorLists];
|
|
|
|
if (path == nil || ([fm fileExistsAtPath: path isDirectory: &isDir] == NO))
|
|
{
|
|
// FIXME the standard path for saving color lists?
|
|
path = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
|
|
NSUserDomainMask, YES) objectAtIndex: 0]
|
|
stringByAppendingPathComponent: @"Colors"];
|
|
isDir = YES;
|
|
}
|
|
|
|
if (isDir)
|
|
{
|
|
ASSIGN (_fullFileName, [[path stringByAppendingPathComponent: _name]
|
|
stringByAppendingPathExtension: @"clr"]);
|
|
}
|
|
else // it is a file
|
|
{
|
|
_fullFileName = path;
|
|
if ([[path pathExtension] isEqual: @"clr"] == YES)
|
|
{
|
|
ASSIGN (_fullFileName, path);
|
|
}
|
|
else
|
|
{
|
|
ASSIGN (_fullFileName, [[path stringByDeletingPathExtension]
|
|
stringByAppendingPathExtension: @"clr"]);
|
|
}
|
|
}
|
|
|
|
// Check if the path is a standard path
|
|
if ([[path lastPathComponent] isEqualToString: @"Colors"] == NO)
|
|
path_is_standard = NO;
|
|
else
|
|
{
|
|
tmpPath = [path stringByDeletingLastPathComponent];
|
|
if (![NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
|
|
NSAllDomainsMask, YES) containsObject: tmpPath])
|
|
{
|
|
path_is_standard = NO;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If path is standard and it does not exist, try to create it.
|
|
* System standard paths should always be assumed to exist;
|
|
* this will normally then only try to create user paths.
|
|
*/
|
|
if (path_is_standard && ([fm fileExistsAtPath: path] == NO))
|
|
{
|
|
if([fm createDirectoryAtPath: path
|
|
attributes: nil])
|
|
{
|
|
NSLog (@"Created standard directory %@", path);
|
|
}
|
|
else
|
|
{
|
|
NSLog (@"Failed attemp to create directory %@", path);
|
|
}
|
|
}
|
|
|
|
success = [NSArchiver archiveRootObject: self
|
|
toFile: _fullFileName];
|
|
|
|
if (success && path_is_standard)
|
|
{
|
|
[_gnustep_color_list_lock lock];
|
|
if ([_gnustep_available_color_lists containsObject: self] == NO)
|
|
[_gnustep_available_color_lists addObject: self];
|
|
[_gnustep_color_list_lock unlock];
|
|
return YES;
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
- (void) removeFile
|
|
{
|
|
if (_fullFileName && _is_editable)
|
|
{
|
|
// Remove the file
|
|
[[NSFileManager defaultManager] removeFileAtPath: _fullFileName
|
|
handler: nil];
|
|
|
|
// Remove the color list from the global list of colors
|
|
if (_gnustep_available_color_lists == nil)
|
|
[NSColorList _loadAvailableColorLists];
|
|
|
|
[_gnustep_color_list_lock lock];
|
|
[_gnustep_available_color_lists removeObject: self];
|
|
[_gnustep_color_list_lock unlock];
|
|
|
|
// Reset file name
|
|
_fullFileName = nil;
|
|
}
|
|
}
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
{
|
|
[aCoder encodeObject: _name];
|
|
[aCoder encodeObject: _colorDictionary];
|
|
[aCoder encodeObject: _orderedColorKeys];
|
|
}
|
|
|
|
- (id) initWithCoder: (NSCoder*)aDecoder
|
|
{
|
|
[aDecoder decodeValueOfObjCType: @encode(id) at: &_name];
|
|
[aDecoder decodeValueOfObjCType: @encode(id) at: &_colorDictionary];
|
|
[aDecoder decodeValueOfObjCType: @encode(id) at: &_orderedColorKeys];
|
|
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|