Skip to content

Commit

Permalink
Making CPThemedAttribute more robust.
Browse files Browse the repository at this point in the history
Reviewed by me.
  • Loading branch information
Francisco Tolmasky committed Mar 9, 2009
1 parent ee3b7de commit a072112
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 164 deletions.
5 changes: 5 additions & 0 deletions AppKit/CPTheme.j
Expand Up @@ -305,4 +305,9 @@ var CPThemeNameKey = @"CPThemeNameKey",
return _bundle;
}

- (BOOL)awakenCustomResources
{
return YES;
}

@end
201 changes: 61 additions & 140 deletions AppKit/CPThemedAttribute.j
Expand Up @@ -30,18 +30,16 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010

@implementation CPThemedAttribute : CPObject
{
BOOL _isSingularObject;

JSObject _cache;
JSObject _cache;

CPString _name;
id _defaultValue;
CPString _name;
id _defaultValue;

CPTheme _theme;
Class _themedClass;
CPTheme _theme;
Class _themedClass;

id _values;
id _valueFromTheme;
CPDictionary _values;
CPThemedAttribute _attributeFromTheme;
}

- (id)initWithName:(CPString)aName defaultValue:(id)aDefaultValue theme:(CPTheme)aTheme class:(Class)aClass
Expand All @@ -59,9 +57,8 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010
_theme = aTheme;
_themedClass = aClass;

_isSingularObject = YES;
_values = nil;
_valueFromTheme = [_theme valueForAttributeName:_name inClass:_themedClass];
_values = [CPDictionary dictionary];
_attributeFromTheme = nil;//[_theme valueForAttributeName:_name inClass:_themedClass];
}

return self;
Expand Down Expand Up @@ -90,23 +87,27 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010

_cache = {};
_theme = aTheme;
_valueFromTheme = [_theme valueForAttributeName:_name inClass:_themedClass];
_attributeFromTheme = nil;//[_theme valueForAttributeName:_name inClass:_themedClass];
}

- (void)setThemedClass:(Class)aClass
{
if (_themedClass === aClass)
return;

_cache = {};
_themedClass = aClass;
_valueFromTheme = [_theme valueForAttributeName:_name inClass:_themedClass];
_attributeFromTheme = nil;//[_theme valueForAttributeName:_name inClass:_themedClass];
}

- (void)setValue:(id)aValue
{
_cache = {};
_isSingularObject = YES;
_values = aValue;

if (aValue === undefined || aValue === nil)
_values = [CPDictionary dictionary];
else
_values = [CPDictionary dictionaryWithObject:aValue forKey:String(CPControlStateNormal)];
}

- (id)value
Expand All @@ -116,84 +117,61 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010

- (void)setValue:(id)aValue forControlState:(CPControlState)aState
{
//delete _cache[aState];
_cache = {};

if (aState !== CPControlStateNormal)
{
if (_isSingularObject)
{
var normalValue = _values;

_isSingularObject = NO;

_values = {};

if (normalValue)
_values[CPControlStateNormal] = normalValue;
}

_values[aState] = aValue;
}

else if (_isSingularObject)
_values = aValue;

if ((aValue === undefined) || (aValue === nil))
[_values removeObjectForKey:String(aState)];
else
_values[CPControlStateNormal] = aValue;
[_values setObject:aValue forKey:String(aState)];
}

- (id)valueForControlState:(CPControlState)aState
{
var value = _cache[aState];

if (value !== undefined && value !== nil)
// This can be nil.
if (value !== undefined)
return value;

if (_isSingularObject)
var value = _values;
value = [_values objectForKey:String(aState)];

else
// If we don't have a value, and we have a non-normal state...
if ((value === undefined || value === nil) && aState > 0)
{
var value = _values[aState];

// If we don't have a value, and we have a non-normal state...
if ((value === undefined || value === nil) && aState > 0)
// If this is a composite state, find the closest partial subset match.
if (aState & (aState - 1))
{
// If this is a composite state, find the closest partial subset match.
if (aState & (aState - 1))
var highestBitCount = 0,
states = [_values allKeys],
count = states.length;

while (count--)
{
var highestBitCount = 0;
// state is a string!
state = Number(states[count]);

for (state in _values)
// A & B = A iff A < B
if ((state & aState) === state)
{
if (!_values.hasOwnProperty(state))
continue;

// state is a string!
state = Number(state);
var bitCount = (state < BIT_COUNT.length) ? BIT_COUNT[state] : bit_count(state);

// A & B = A iff A < B
if ((state & aState) === state)
if (bitCount > highestBitCount)
{
var bitCount = (state < BIT_COUNT.length) ? BIT_COUNT[state] : bit_count(state);

if (bitCount > highestBitCount)
{
highestBitCount = bitCount;
value = _values[state];
}
highestBitCount = bitCount;
value = [_values objectForKey:String(state)];
}
}
}

// Still don't have a value? OK, let's use the normal value.
if (value === undefined || value === nil)
value = _values[CPControlStateNormal];
}

// Still don't have a value? OK, let's use the normal value.
if (value === undefined || value === nil)
value = [_values objectForKey:String(CPControlStateNormal)];
}

if (value === undefined || value === nil)
value = [_valueFromTheme valueForControlState:aState];
value = [_attributeFromTheme valueForControlState:aState];

if (value === undefined || value === nil)
value = _defaultValue;
Expand All @@ -205,36 +183,12 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010

- (CPThemedAttribute)themedAttributeMergedWithThemedAttribute:(CPThemedAttribute)aThemedAttribute
{
var themedAttribute = CPThemedAttributeMake(_name, _defaultValue, _theme, _themedClass);
var mergedAttribute = CPThemedAttributeMake(_name, _defaultValue, _theme, _themedClass);

themedAttribute._isSingularObject = NO;
themedAttribute._values = {};

if (_isSingularObject)
themedAttribute._values[CPControlStateNormal] = _values;

else
{
var values = _values;

for (state in _values)
if (_values.hasOwnProperty(state))
themedAttribute._values[state] = _values[state];
}
mergedAttribute._values = [_values copy];
[mergedAttribute._values addEntriesFromDictionary:aThemedAttribute._values];

if (aThemedAttribute._isSingularObject)
themedAttribute._values[CPControlStateNormal] = aThemedAttribute._values;

else
{
var values = aThemedAttribute._values;

for (state in values)
if (values.hasOwnProperty(state))
themedAttribute._values[state] = values[state];
}

return themedAttribute;
return mergedAttribute;
}

- (id)initWithCoder:(CPCoder)aCoder
Expand All @@ -244,52 +198,15 @@ var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*0010
if (self)
{
_cache = {};
_isSingularObject = [aCoder containsValueForKey:@"value"];

if (_isSingularObject)
_values = [aCoder decodeObjectForKey:"value"];

else
{
_values = {};

var statesAndValues = [aCoder decodeObjectForKey:"statesAndValues"];
count = [statesAndValues count];

while (count--)
{
var value = statesAndValues[count--],
state = statesAndValues[count];

_values[state] = value;
}
}
_values = [aCoder decodeObjectForKey:@"values"];
}

return self;
}

- (void)encodeWithCoder:(CPCoder)aCoder
{
if (_isSingularObject)
{
[aCoder encodeObject:_values forKey:@"value"];

return;
}

var statesAndValues = [];

for (state in _values)
{
if (!_values.hasOwnProperty(state))
continue;

statesAndValues.push(state);
statesAndValues.push(_values[state]);
}

[aCoder encodeObject:statesAndValues forKey:@"statesAndValues"];
[aCoder encodeObject:_values forKey:@"values"];
}

@end
Expand All @@ -301,14 +218,18 @@ function CPThemedAttributeMake(aName, aDefaultValue, aTheme, aClass)

function CPThemedAttributeEncode(aCoder, aThemedAttribute)
{
if (aThemedAttribute._isSingularObject)
var values = aThemedAttribute._values,
count = [values count];

if (count === 1)
{
var actualValue = aThemedAttribute._values;
var key = [values allKeys][0];

if (aThemedAttribute._values)
[aCoder encodeObject:actualValue forKey:"$a" + [aThemedAttribute name]];
if (Number(key) === 0)
return [aCoder encodeObject:[values objectForKey:key] forKey:"$a" + [aThemedAttribute name]];
}
else

if (count >= 1)
[aCoder encodeObject:aThemedAttribute forKey:"$a" + [aThemedAttribute name]];
}

Expand Down
16 changes: 15 additions & 1 deletion AppKit/Cib/CPCib.j
Expand Up @@ -42,14 +42,18 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
{
CPData _data;
CPBundle _bundle;
BOOL _awakenCustomResources;
}

- (id)initWithContentsOfURL:(CPURL)aURL
{
self = [super init];

if (self)
{
_data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:aURL] returningResponse:nil error:nil];
_awakenCustomResources = YES;
}

return self;
}
Expand All @@ -66,9 +70,19 @@ var CPCibObjectDataKey = @"CPCibObjectDataKey";
return self;
}

- (void)_setAwakenCustomResources:(BOOL)shouldAwakenCustomResources
{
_awakenCustomResources = shouldAwakenCustomResources;
}

- (BOOL)_awakenCustomResources
{
return _awakenCustomResources;
}

- (BOOL)instantiateCibWithExternalNameTable:(CPDictionary)anExternalNameTable
{
var unarchiver = [[_CPCibKeyedUnarchiver alloc] initForReadingWithData:_data bundle:_bundle],
var unarchiver = [[_CPCibKeyedUnarchiver alloc] initForReadingWithData:_data bundle:_bundle awakenCustomResources:_awakenCustomResources],
replacementClasses = [anExternalNameTable objectForKey:CPCibReplacementClasses];

if (replacementClasses)
Expand Down
3 changes: 2 additions & 1 deletion AppKit/Cib/_CPCibCustomResource.j
Expand Up @@ -80,7 +80,8 @@ var _CPCibCustomResourceClassNameKey = @"_CPCibCustomResourceClassNameKey",

- (id)awakeAfterUsingCoder:(CPCoder)aCoder
{
if ([aCoder respondsToSelector:@selector(bundle)])
if ([aCoder respondsToSelector:@selector(bundle)] &&
(![aCoder respondsToSelector:@selector(awakenCustomResources)] || [aCoder awakenCustomResources]))
if (_className === @"CPImage")
return [[CPImage alloc] initWithContentsOfFile:[[aCoder bundle] pathForResource:_resourceName] size:[_properties objectForKey:@"size"]];

Expand Down
9 changes: 8 additions & 1 deletion AppKit/Cib/_CPCibKeyedUnarchiver.j
Expand Up @@ -5,15 +5,17 @@
@implementation _CPCibKeyedUnarchiver : CPKeyedUnarchiver
{
CPBundle _bundle;
BOOL _awakenCustomResources;
}

- (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle
- (id)initForReadingWithData:(CPData)data bundle:(CPBundle)aBundle awakenCustomResources:(BOOL)shouldAwakenCustomResources
{
self = [super initForReadingWithData:data];

if (self)
{
_bundle = aBundle;
_awakenCustomResources = shouldAwakenCustomResources;

[self setDelegate:self];
}
Expand All @@ -26,6 +28,11 @@
return _bundle;
}

- (BOOL)awakenCustomResources
{
return _awakenCustomResources;
}

- (void)replaceObjectAtUID:(int)aUID withObject:(id)anObject
{
_objects[aUID] = anObject;
Expand Down

0 comments on commit a072112

Please sign in to comment.