Skip to content

Commit

Permalink
[css] initial debugging support via "description" type methods that w…
Browse files Browse the repository at this point in the history
…ill do a dry run of the style sheet and spit out objective-c for you to look at.
  • Loading branch information
Max Metral committed Feb 27, 2013
1 parent a2af952 commit 5c61300
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 59 deletions.
2 changes: 2 additions & 0 deletions examples/css/CSSDemo/RootViewController.m
Expand Up @@ -78,6 +78,8 @@ - (void)loadView {
[_dom registerView:box withCSSClass:@"colorBox" andId:[NSString stringWithFormat:@"box%d",i]];
}
[_activityIndicator startAnimating];

NSLog(@"%@", [_dom descriptionForAllViews]);
}

-(void)viewWillLayoutSubviews
Expand Down
21 changes: 21 additions & 0 deletions src/css/src/NIDOM.h
Expand Up @@ -88,6 +88,9 @@ _dom = [[NIDOM alloc] initWithStylesheet:stylesheet];

-(UIView*)viewById: (NSString*) viewId;

-(NSString*) descriptionForView: (UIView*) view withName: (NSString*) viewName;
-(NSString*) descriptionForAllViews;

@property (nonatomic,unsafe_unretained) id target;
@end

Expand Down Expand Up @@ -192,3 +195,21 @@ _dom = [[NIDOM alloc] initWithStylesheet:stylesheet];
*
* @fn NIDOM::target
*/

/** @name Debugging */

/**
* Describe what would be done to view given the existing registrations for it. In other words, you
* must call one of the register view variants first before asking for a description. The current
* implementations return actual objective-c code, using viewName as the target. This allows you to
* theoretically replace the CSS infrastructure with generated code, if you choose to. More importantly,
* it allows you to debug what's happening with view styling.
*
* @fn NIDOM::descriptionForView:withName:
*/

/**
* Call descriptionForView for all registered views, in the order they would be applied during refresh
*
* @fn NIDOM::descriptionForAllViews
*/
49 changes: 49 additions & 0 deletions src/css/src/NIDOM.m
Expand Up @@ -297,4 +297,53 @@ -(UIView *)viewById:(NSString *)viewId
return [_idToViewMap objectForKey:viewId];
}

///////////////////////////////////////////////////////////////////////////////////////////////////
-(NSString *)descriptionForView:(UIView *)view withName:(NSString *)viewName
{
NSMutableString *description = [[NSMutableString alloc] init];
BOOL appendedStyleInfo = NO;

for (NSString *selector in [_viewToSelectorsMap objectForKey:[self keyForView:view]]) {
BOOL appendedSelectorInfo = NO;
NSString *additional = nil;
if (self.parent) {
additional = [self.parent.stylesheet descriptionForView: view withClassName: selector inDOM:self andViewName: viewName];
if (additional && additional.length) {
if (!appendedStyleInfo) { appendedStyleInfo = YES; [description appendFormat:@"// Styles for %@\n", viewName]; }
if (!appendedSelectorInfo) { appendedSelectorInfo = YES; [description appendFormat:@"// Selector %@\n", selector]; }
[description appendString:additional];
}
}
additional = [_stylesheet descriptionForView:view withClassName: selector inDOM:self andViewName: viewName];
if (additional && additional.length) {
if (!appendedStyleInfo) { appendedStyleInfo = YES; [description appendFormat:@"// Styles for %@\n", viewName]; }
if (!appendedSelectorInfo) { appendedSelectorInfo = YES; [description appendFormat:@"// Selector %@\n", selector]; }
[description appendString:additional];
}
}
return description;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
-(NSString *)descriptionForAllViews {
NSMutableString *description = [[NSMutableString alloc] init];
int viewCount = 0;
for (UIView *view in _registeredViews) {
[description appendString:@"\n///////////////////////////////////////////////////////////////////////////////////////////////////\n"];
viewCount++;
// This is a little hokey - because we don't get individual view names we have to come up with some.
__block NSString *vid = nil;
[[_viewToSelectorsMap objectForKey:[self keyForView:view]] enumerateObjectsUsingBlock:^(NSString *selector, NSUInteger idx, BOOL *stop) {
if ([selector hasPrefix:@"#"]) {
vid = [selector substringFromIndex:1];
*stop = YES;
}
}];
if (vid) {
[description appendFormat:@"UIView *%@_%d = [dom viewById: @\"#%@\"];\n", [view class], viewCount, vid];
}
[description appendString:[self descriptionForView:view withName:[NSString stringWithFormat:@"%@_%d", [view class], viewCount]]];
}
return description;
}
@end
7 changes: 7 additions & 0 deletions src/css/src/NIStyleable.h
Expand Up @@ -60,4 +60,11 @@
*/
- (void)applyStyleWithRuleSet:(NICSSRuleset *)ruleSet forPseudoClass: (NSString*) pseudo inDOM: (NIDOM*) dom;

/**
* Return a string describing what would be done with the view. The current implementations return actual
* Objective-C using the view name as the message target. The intent is to allow developers to debug
* the logic, but also to be able to strip out the CSS infrastructure if desired and replace it with manual code.
*/
- (NSString*) descriptionWithRuleSet: (NICSSRuleset*) ruleSet forPseudoClass: (NSString*) pseudo inDOM: (NIDOM*) dom withViewName: (NSString*) name;

@end
11 changes: 11 additions & 0 deletions src/css/src/NIStylesheet.h
Expand Up @@ -64,6 +64,8 @@ extern NSString* const NIStylesheetDidChangeNotification;

- (void)applyStyleToView:(UIView *)view withClassName:(NSString *)className inDOM: (NIDOM*)dom;

- (NSString*)descriptionForView:(UIView *)view withClassName:(NSString *)className inDOM: (NIDOM*)dom andViewName: (NSString*) viewName;

- (NICSSRuleset *)rulesetForClassName:(NSString *)className;

/**
Expand Down Expand Up @@ -141,3 +143,12 @@ extern NSString* const NIStylesheetDidChangeNotification;
* @param className Either the view's class as a string using NSStringFromClass([view class]);
* or a CSS class selector such as ".myClassSelector".
*/

/** @name Debugging */

/**
* Build a string describing the rules that would be applied to the view given a css class name in a DOM.
* Current implementations output Objective-C code that use viewName as the target.
*
* @fn NIStylesheet::descriptionForView:withClassName:inDOM:andViewName:
*/
18 changes: 18 additions & 0 deletions src/css/src/NIStylesheet.m
Expand Up @@ -226,6 +226,24 @@ - (void)addStylesheet:(NIStylesheet *)stylesheet {
}
}

///////////////////////////////////////////////////////////////////////////////////////////////////
- (NSString*)descriptionForView:(UIView *)view withClassName:(NSString *)className inDOM:(NIDOM *)dom andViewName:(NSString *)viewName {
NSMutableString *description = [[NSMutableString alloc] init];
NICSSRuleset *ruleset = [self rulesetForClassName:className];
if (nil != ruleset) {
NSRange r = [className rangeOfString:@":"];
if ([view respondsToSelector:@selector(descriptionWithRuleSet:forPseudoClass:inDOM:withViewName:)]) {
if (r.location != NSNotFound) {
[description appendString:[(id<NIStyleable>)view descriptionWithRuleSet:ruleset forPseudoClass:[className substringFromIndex:r.location+1] inDOM:dom withViewName:viewName]];
} else {
[description appendString:[(id<NIStyleable>)view descriptionWithRuleSet:ruleset forPseudoClass:nil inDOM:dom withViewName:viewName]];
}
} else {
[description appendFormat:@"// Description not supported for %@ with selector %@\n", view, className];
}
}
return description;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
10 changes: 9 additions & 1 deletion src/css/src/UIView+NIStyleable.h
Expand Up @@ -40,13 +40,21 @@ extern NSString* const NICSSViewBackgroundColorKey;
- (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet DEPRECATED_ATTRIBUTE;

/**
* Applies the given rule set to this view. Call applyViewStyleWithRuleSet:inDOM: instead.
* Applies the given rule set to this view.
*
* This method is exposed primarily for subclasses to use when implementing the
* applyStyleWithRuleSet: method from NIStyleable.
*/
- (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM: (NIDOM*) dom;

/**
* Describes the given rule set when applied to this view.
*
* This method is exposed primarily for subclasses to use when implementing the
* descriptionWithRuleSetFor:forPseudoClass:inDOM:withViewName: method from NIStyleable.
*/
- (NSString*) descriptionWithRuleSetForView: (NICSSRuleset*) ruleSet forPseudoClass: (NSString*) pseudo inDOM: (NIDOM*) dom withViewName: (NSString*) name;

/**
* Build a view hierarchy. The array is a list of view specs, where viewSpec is a loosely formatted
* sequence delineated by UIViews. After a UIView, the type of the next object determines what is done
Expand Down

0 comments on commit 5c61300

Please sign in to comment.