/* ** RulesetManager.m ** ** Copyright (c) 2002, 2003 ** ** Author: Yen-Ju Chen ** Bjoern Giesler ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "RulesetManager.h" #include @implementation NSColor (RulesetManager) + (NSColor *)colorWithRGBAArray: (NSArray *) array { if([array count] != 4) { [NSException raise: @"NSColor Creation Error" format: @"RGBA array needs 4 elements, " @"is: %@", [array description]]; return nil; } return [NSColor colorWithCalibratedRed: [[array objectAtIndex: 0] floatValue] green: [[array objectAtIndex: 1] floatValue] blue: [[array objectAtIndex: 2] floatValue] alpha: [[array objectAtIndex: 3] floatValue]]; } @end @implementation NSArray (RulesetManager) + (NSArray *) arrayWithColor: (NSColor *) color { return [NSArray arrayWithObjects: [NSNumber numberWithFloat: [color redComponent]], [NSNumber numberWithFloat: [color greenComponent]], [NSNumber numberWithFloat: [color blueComponent]], [NSNumber numberWithFloat: [color alphaComponent]], nil]; } @end static RulesetManager *sharedManager = nil; @implementation RulesetManager + (RulesetManager *) sharedRulesetManager { if (!sharedManager) { sharedManager = [[RulesetManager alloc] init]; [sharedManager loadFontAttributesFromUserDefaults]; } return sharedManager; } - (NSDictionary *) attributesForType: (NSString *) type { if (type == nil) return nil; return [fontAttributes objectForKey: type]; } - (void) setColor: (NSColor *) color forType: (NSString *) type { if ((type == nil) || (color == nil)) return; color = [color colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; /* Update font attributes */ [[fontAttributes objectForKey: type] setObject: color forKey: @"Color"]; /* Update font defaults */ [[fontDefaults objectForKey: type] setObject: [NSArray arrayWithColor: color] forKey: @"Color"]; } - (void) setFont: (NSFont *) font forType: (NSString *) type { NSMutableDictionary *dict; NSMutableArray *array; NSFontManager *fontManager = [NSFontManager sharedFontManager]; NSFontTraitMask mask; if ((type == nil) || (font == nil)) return; dict = [NSMutableDictionary new]; array = [NSMutableArray new]; /* Update font attributes */ [[fontAttributes objectForKey: type] setObject: font forKey: @"Font"]; /* Update font defaults */ [dict setObject: [font fontName] forKey: @"Name"]; [dict setObject: [NSNumber numberWithFloat: [font pointSize]] forKey: @"Size"]; mask = [fontManager traitsOfFont: font]; if (mask & NSBoldFontMask) [array addObject: @"Bold"]; if (mask & NSItalicFontMask) [array addObject: @"Italic"]; if ([array count] > 0) [dict setObject: array forKey: @"Traits"]; [[fontDefaults objectForKey: type] setObject: dict forKey: @"Font"]; RELEASE(dict); RELEASE(array); } - (NSColor *) colorForType: (NSString *) type { return [[self attributesForType: type] objectForKey: @"Color"]; } - (void) setNormalFont: (NSFont *) font { // ASSIGN(normalFont, font); [self setFont: font forType: @"Normal"]; } - (NSFont *) normalFont { NSFont *font; /* if (normalFont) return normalFont; else */ font = [[self attributesForType: @"Normal"] objectForKey: @"Font"]; if (font == nil) font = [NSFont userFixedPitchFontOfSize: [NSFont systemFontSize]]; [self setNormalFont: font]; return font; } - (void) setTrait: (NSFontTraitMask) mask forType: (NSString *) type { NSFontManager *fontManager = [NSFontManager sharedFontManager]; NSFont *font; font = [fontManager convertFont: [self normalFont] toHaveTrait: mask]; [self setFont: font forType: type]; } - (NSFont *) fontForType: (NSString *) type { NSFont *font; id object; font = [self normalFont]; if((object = [[self attributesForType: type] objectForKey: @"Font"])) { if([object isKindOfClass: [NSFont class]]) { return object; } } return font; } - (void) buildFontAttributes { NSEnumerator *e; NSString *key; id object, objectColor, objectFont; NSFont *font; NSFontManager *fontManager = [NSFontManager sharedFontManager]; if (fontDefaults == nil) return; // now, build the actual dictionary ASSIGN(fontAttributes, [NSMutableDictionary new]); e = [fontDefaults keyEnumerator]; while((key = [e nextObject])) { NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity: 2]; font = nil; object = [fontDefaults objectForKey: key]; if((objectColor = [object objectForKey: @"Color"])) { NSColor *color = [NSColor colorWithRGBAArray: objectColor]; [dict setObject: color forKey: @"Color"]; } if((objectFont = [object objectForKey: @"Font"])) { id name, size, traits; if((name = [objectFont objectForKey: @"Name"])) { font = [NSFont fontWithName: name size: [NSFont systemFontSize]]; } else { font = [self normalFont]; } if (font) { if((size = [objectFont objectForKey: @"Size"])) font = [fontManager convertFont: font toSize: [size floatValue]]; if((traits = [objectFont objectForKey: @"Traits"])) { id trait; NSFontTraitMask mask = 0; NSEnumerator *enumTrait = [traits objectEnumerator]; while((trait = [enumTrait nextObject])) { if([trait compare: @"Bold"] == NSOrderedSame) mask |= NSBoldFontMask; else if([trait compare: @"Italic"] == NSOrderedSame) mask |= NSItalicFontMask; /* ignore others */ } font = [fontManager convertFont: font toHaveTrait: mask]; } [dict setObject: font forKey: @"Font"]; } } [fontAttributes setObject: dict forKey: key]; } } - (BOOL) loadFontAttributesFromUserDefaults { NSDictionary *lookPresets, *lookDefaults; NSEnumerator *e; NSString *key; // BNF for the lookPresets: // lookPresets ::= '{' [lookPreset ';']* '}' // lookPreset ::= string '=' lpdict // lpdict ::= '{' [colordef ';'] [fontdef ';'] '}' // colordef ::= '(' red ',' green ',' blue ',' alpha ')' // red ::= float green ::= float blue ::= float alpha ::= float // fontdef ::= '{' ['Name' '=' fontname ';'] // ['Size' '=' fontsize ';'] // ['Traits' '=' fonttraits ';'] '}' // fontname ::= // fontsize ::= // fonttraits ::= '(' ['Bold' ','] ['Italic'] ')' // // Note: No, at the moment I don't do anything but bold and italic. /* The default font attributes */ lookPresets = [@"{Normal = {Color = (0.0, 0.0, 0.0, 1.0); " @" Font = {Name = Courier; " @" Size = 12.0;};}; " @" Comments = {Color = (0.0, 0.5, 0.0, 1.0); " @" Font = {Traits = (Italic);};}; " @" Strings = {Color = (.5, .5, 0.0, 1.0); " @" Font = {Traits = (Italic);};}; " @" Preprocessor = {Color = (0.5, 0.5, 0.5, 1.0); " @" Font = {Traits = (Bold);};}; " @" Keywords = {Color = (0.8, 0.0, 0.0, 1.0);}; " @" KnownTypes = {Color = (0.0, 0.5, 0.5, 1.0);}; " @"}" propertyList]; /* Read from user default */ lookDefaults = [[NSUserDefaults standardUserDefaults] objectForKey: @"CodeFontificationAttributes"]; // First put in everything from the user defaults... if (lookDefaults) ASSIGN(fontDefaults, [NSMutableDictionary dictionaryWithDictionary: lookDefaults]); else ASSIGN(fontDefaults, AUTORELEASE([NSMutableDictionary new])); // ...then, everything that the presets have and the user defaults don't. e = [lookPresets keyEnumerator]; while((key = [e nextObject])) { if([fontDefaults objectForKey: key] == nil) { [fontDefaults setObject: [lookPresets objectForKey: key] forKey: key]; } } [self buildFontAttributes]; return YES; } - (void) writeFontAttributesToUserDefaults { [[NSUserDefaults standardUserDefaults] setObject: fontDefaults forKey: @"CodeFontificationAttributes"]; [[NSUserDefaults standardUserDefaults] synchronize]; } - (id) init { self = [super init]; allNames = nil; fontAttributes = nil; fontDefaults = nil; return self; } - (void) dealloc { // RELEASE(normalFont); RELEASE(allNames); RELEASE(fontAttributes); RELEASE(fontDefaults); [super dealloc]; } @end