Skip to content

Commit

Permalink
Added support for overriding and/or extending already registered prop…
Browse files Browse the repository at this point in the history
…erty definitions - resolves #28. Also added new property setter block type (ISSPropertySetterBlock) that returns a BOOL, and deprecated the old one (without the ISS prefix).
  • Loading branch information
tolo committed Aug 14, 2015
1 parent 9b8f4cb commit a5f2b2e
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 137 deletions.
13 changes: 7 additions & 6 deletions InterfaCSS Tests/ISSStyleSheetParserTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ - (NSString*) localizedStringWithKey:(NSString*)key {

@end


static ISSParcoaStyleSheetTestParser* defaultParser;


@interface ISSStyleSheetParserTests : XCTestCase

@end
Expand All @@ -50,16 +54,13 @@ @implementation ISSStyleSheetParserTests {
+ (void) setUp {
[super setUp];
//NSLog(@"%@", [ISSPropertyDefinition propertyDescriptionsForMarkdown]);

defaultParser = [[ISSParcoaStyleSheetTestParser alloc] init];
}

- (void) setUp {
[super setUp];

parser = [[ISSParcoaStyleSheetTestParser alloc] init];
}

- (void) tearDown {
[super tearDown];
parser = defaultParser;
}


Expand Down
38 changes: 35 additions & 3 deletions InterfaCSS Tests/InterfaCSSTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,17 @@ @interface InterfaCSSTests : XCTestCase

@implementation InterfaCSSTests

- (void) setUp {
[super setUp];
+ (void) loadDefaultStylesheet {
NSString* path = [[NSBundle bundleForClass:self.class] pathForResource:@"interfaCSSTests" ofType:@"css"];
[[InterfaCSS interfaCSS] loadStyleSheetFromFile:path];
}

- (void) tearDown {
+ (void) setUp {
[super setUp];
[self loadDefaultStylesheet];
}

+ (void) tearDown {
[super tearDown];
[InterfaCSS clearResetAndUnload];
}
Expand Down Expand Up @@ -662,4 +666,32 @@ - (void) testSimpleSpecificity {
ISSAssertEqualFloats(subView.alpha, 0.5f);
}

- (void) testOverridePropertyDefinitionAndFallback {
[InterfaCSS clearResetAndUnload]; // Need to reset again, to make sure property registration takes

ISSPropertyDefinition* def = [[ISSPropertyDefinition alloc] initWithName:@"text" aliases:nil type:ISSPropertyTypeString enumValues:nil enumBitMaskType:NO setterBlock:^BOOL(ISSPropertyDefinition *property, id viewObject, id value, NSArray *parameters) {
if( [viewObject tag] == 123 ) {
[viewObject setText:[value uppercaseString]];
return YES;
}
return NO;
} parameterEnumValues:nil useIntrospection:NO];

[[InterfaCSS sharedInstance].propertyRegistry registerCustomProperty:def];

[self.class loadDefaultStylesheet];


UILabel* label = [[UILabel alloc] init];
label.tag = 123;

label.styleClassISS = @"overridePropertyDefinitionStyle";
[label applyStylingISS];
XCTAssertEqualObjects(@"MONDAY", label.text);

label.tag = 0;
[label applyStylingISS:YES];
XCTAssertEqualObjects(@"Monday", label.text);
}

@end
5 changes: 5 additions & 0 deletions InterfaCSS Tests/TestData/interfaCSSTests.css
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,8 @@ UIView .testSpecificity2 {
.testSpecificity1 {
alpha: 0.25;
}


.overridePropertyDefinitionStyle {
text: "Monday";
}
43 changes: 25 additions & 18 deletions InterfaCSS/InterfaCSS.m
Original file line number Diff line number Diff line change
Expand Up @@ -76,34 +76,41 @@ + (InterfaCSS*) sharedInstance {
}

+ (void) clearResetAndUnload {
singleton.parser = nil;
[singleton.styleSheets removeAllObjects];
[singleton.styleSheetsVariables removeAllObjects];
[singleton.prototypes removeAllObjects];

[singleton clearAllCachedStyles];

[singleton disableAutoRefreshTimer];

setupForInitialState(singleton);
}

- (id) init {
@throw([NSException exceptionWithName:NSInternalInconsistencyException reason:@"Hold on there professor, use +[InterfaCSS interfaCSS] instead!" userInfo:nil]);
}

static void setupForInitialState(InterfaCSS* interfaCSS) {
interfaCSS->_preventOverwriteOfAttributedTextAttributes = NO;
interfaCSS->_useLenientSelectorParsing = NO;
interfaCSS->_stylesheetAutoRefreshInterval = 5.0;
interfaCSS->_processRefreshableStylesheetsLast = YES;
interfaCSS->_allowAutomaticRegistrationOfCustomTypeSelectorClasses = NO;
interfaCSS->_useSelectorSpecificity = NO;

interfaCSS->_parser = nil;

interfaCSS->_propertyRegistry = [[ISSPropertyRegistry alloc] init];

interfaCSS->_styleSheets = [[NSMutableArray alloc] init];
interfaCSS->_styleSheetsVariables = [[NSMutableDictionary alloc] init];

interfaCSS->_cachedStyleDeclarationsForElements = [NSMapTable weakToStrongObjectsMapTable];
interfaCSS->_prototypes = [[NSMutableDictionary alloc] init];

interfaCSS->_initializedWindows = [NSMapTable weakToStrongObjectsMapTable];
}

- (id) initInternal {
if( (self = [super init]) ) {
_stylesheetAutoRefreshInterval = 5.0;
_processRefreshableStylesheetsLast = YES;

_propertyRegistry = [[ISSPropertyRegistry alloc] init];

_styleSheets = [[NSMutableArray alloc] init];
_styleSheetsVariables = [[NSMutableDictionary alloc] init];

_cachedStyleDeclarationsForElements = [NSMapTable weakToStrongObjectsMapTable];
_prototypes = [[NSMutableDictionary alloc] init];

_initializedWindows = [NSMapTable weakToStrongObjectsMapTable];
setupForInitialState(self);

NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self selector:@selector(memoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
Expand Down
4 changes: 1 addition & 3 deletions InterfaCSS/Model/ISSPropertyDeclaration.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,7 @@ - (BOOL) applyPropertyValueOnTarget:(id)target {
return NO;
}

[self.property setValue:self.propertyValue onTarget:target andParameters:self.parameters];

return YES;
return [self.property setValue:self.propertyValue onTarget:target andParameters:self.parameters];
}


Expand Down
11 changes: 9 additions & 2 deletions InterfaCSS/Model/ISSPropertyDefinition.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@

@class ISSPropertyDefinition;

typedef void (^ISSPropertySetterBlock)(ISSPropertyDefinition* property, id viewObject, id value, NSArray* parameters);
/** @deprecated */
typedef void (^PropertySetterBlock)(ISSPropertyDefinition* property, id viewObject, id value, NSArray* parameters);

typedef BOOL (^ISSPropertySetterBlock)(ISSPropertyDefinition* property, id viewObject, id value, NSArray* parameters);


typedef NS_ENUM(NSInteger, ISSPropertyType) {
Expand Down Expand Up @@ -60,6 +63,8 @@ typedef NS_ENUM(NSInteger, ISSPropertyType) {

@property (nonatomic, readonly) NSString* displayDescription;

@property (nonatomic, strong) ISSPropertyDefinition* overriddenDefinition;


/**
* Creates a temporary, anonymous, property definition.
Expand Down Expand Up @@ -92,9 +97,11 @@ typedef NS_ENUM(NSInteger, ISSPropertyType) {
* If this is an enum property, specify the enum values in the `enumValues` parameter. If the enum values are of a bit mask type, specify `YES` in the `enumBitMaskType` parameter.
* If this is a parameterized property, specify the parameter value transformation dictionary in `parameterEnumValues`.
* To use a custom handling for setting the property value - specify a property setter block in the `setterBlock` parameter.
*
* @deprecated due to deprecation of setter block type.
*/
- (id) initWithName:(NSString*)name aliases:(NSArray*)aliases type:(ISSPropertyType)type enumValues:(NSDictionary*)enumValues
enumBitMaskType:(BOOL)enumBitMaskType setterBlock:(ISSPropertySetterBlock)setterBlock parameterEnumValues:(NSDictionary*)parameterEnumValues;
enumBitMaskType:(BOOL)enumBitMaskType setterBlock:(PropertySetterBlock)setterBlock parameterEnumValues:(NSDictionary*)parameterEnumValues;

/**
* Creates a property definition with an optional number of aliases, that optionally can set it's value via introspection (i.e. use declared or default setter method for property), instead of using KVC.
Expand Down
27 changes: 21 additions & 6 deletions InterfaCSS/Model/ISSPropertyDefinition.m
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,19 @@ - (id) initWithName:(NSString *)name aliases:(NSArray*)aliases type:(ISSProperty
return [self initWithName:name aliases:aliases type:type enumValues:enumValues enumBitMaskType:enumBitMaskType setterBlock:nil parameterEnumValues:nil useIntrospection:NO];
}

// Deprecated
- (id) initWithName:(NSString *)name aliases:(NSArray*)aliases type:(ISSPropertyType)type enumValues:(NSDictionary*)enumValues
enumBitMaskType:(BOOL)enumBitMaskType setterBlock:(ISSPropertySetterBlock)setterBlock parameterEnumValues:(NSDictionary*)parameterEnumValues {
return [self initWithName:name aliases:aliases type:type enumValues:enumValues enumBitMaskType:enumBitMaskType setterBlock:setterBlock parameterEnumValues:parameterEnumValues useIntrospection:NO];
enumBitMaskType:(BOOL)enumBitMaskType setterBlock:(PropertySetterBlock)setterBlock parameterEnumValues:(NSDictionary*)parameterEnumValues {

ISSPropertySetterBlock issPropertySetterBlock = nil;
if( setterBlock ) {
issPropertySetterBlock = ^(ISSPropertyDefinition* property, id viewObject, id value, NSArray* parameters) {
setterBlock(property, viewObject, value, parameters);
return YES;
};
}

return [self initWithName:name aliases:aliases type:type enumValues:enumValues enumBitMaskType:enumBitMaskType setterBlock:issPropertySetterBlock parameterEnumValues:parameterEnumValues useIntrospection:NO];
}

- (id) initWithName:(NSString *)name aliases:(NSArray*)aliases type:(ISSPropertyType)type enumValues:(NSDictionary*)enumValues
Expand Down Expand Up @@ -106,16 +116,21 @@ - (BOOL) setValueUsingKVC:(id)value onTarget:(id)obj {
- (BOOL) setValue:(id)value onTarget:(id)obj andParameters:(NSArray*)params {
if( [value isKindOfClass:ISSLazyValue.class] ) value = [value evaluateWithParameter:obj];
if( value && value != [NSNull null] ) {
BOOL result;
if( self.propertySetterBlock ) {
self.propertySetterBlock(self, obj, value, params);
return YES;
result = self.propertySetterBlock(self, obj, value, params);
}
else if( self.useIntrospection ) {
return [ISSRuntimeIntrospectionUtils invokeSetterForProperty:self.name withValue:value inObject:obj];
result = [ISSRuntimeIntrospectionUtils invokeSetterForProperty:self.name withValue:value inObject:obj];
}
else {
return [self setValueUsingKVC:value onTarget:obj];
result = [self setValueUsingKVC:value onTarget:obj];
}
// If property couldn't be set - try overridden definition, if available
if( !result && self.overriddenDefinition ) {
return [self.overriddenDefinition setValue:value onTarget:obj andParameters:params];
}
return result;
}
return NO;
}
Expand Down
Loading

0 comments on commit a5f2b2e

Please sign in to comment.