Skip to content
This repository
Browse code

[css] initial debugging support via "description" type methods that w…

…ill do a dry run of the style sheet and spit out objective-c for you to look at.
  • Loading branch information...
commit 5c61300580d93a26418a5612d424ec62a2f08142 1 parent a2af952
Max Metral authored
2  examples/css/CSSDemo/RootViewController.m
@@ -78,6 +78,8 @@ - (void)loadView {
78 78 [_dom registerView:box withCSSClass:@"colorBox" andId:[NSString stringWithFormat:@"box%d",i]];
79 79 }
80 80 [_activityIndicator startAnimating];
  81 +
  82 + NSLog(@"%@", [_dom descriptionForAllViews]);
81 83 }
82 84
83 85 -(void)viewWillLayoutSubviews
21 src/css/src/NIDOM.h
@@ -88,6 +88,9 @@ _dom = [[NIDOM alloc] initWithStylesheet:stylesheet];
88 88
89 89 -(UIView*)viewById: (NSString*) viewId;
90 90
  91 +-(NSString*) descriptionForView: (UIView*) view withName: (NSString*) viewName;
  92 +-(NSString*) descriptionForAllViews;
  93 +
91 94 @property (nonatomic,unsafe_unretained) id target;
92 95 @end
93 96
@@ -192,3 +195,21 @@ _dom = [[NIDOM alloc] initWithStylesheet:stylesheet];
192 195 *
193 196 * @fn NIDOM::target
194 197 */
  198 +
  199 +/** @name Debugging */
  200 +
  201 +/**
  202 + * Describe what would be done to view given the existing registrations for it. In other words, you
  203 + * must call one of the register view variants first before asking for a description. The current
  204 + * implementations return actual objective-c code, using viewName as the target. This allows you to
  205 + * theoretically replace the CSS infrastructure with generated code, if you choose to. More importantly,
  206 + * it allows you to debug what's happening with view styling.
  207 + *
  208 + * @fn NIDOM::descriptionForView:withName:
  209 + */
  210 +
  211 +/**
  212 + * Call descriptionForView for all registered views, in the order they would be applied during refresh
  213 + *
  214 + * @fn NIDOM::descriptionForAllViews
  215 + */
49 src/css/src/NIDOM.m
@@ -297,4 +297,53 @@ -(UIView *)viewById:(NSString *)viewId
297 297 return [_idToViewMap objectForKey:viewId];
298 298 }
299 299
  300 +///////////////////////////////////////////////////////////////////////////////////////////////////
  301 +-(NSString *)descriptionForView:(UIView *)view withName:(NSString *)viewName
  302 +{
  303 + NSMutableString *description = [[NSMutableString alloc] init];
  304 + BOOL appendedStyleInfo = NO;
  305 +
  306 + for (NSString *selector in [_viewToSelectorsMap objectForKey:[self keyForView:view]]) {
  307 + BOOL appendedSelectorInfo = NO;
  308 + NSString *additional = nil;
  309 + if (self.parent) {
  310 + additional = [self.parent.stylesheet descriptionForView: view withClassName: selector inDOM:self andViewName: viewName];
  311 + if (additional && additional.length) {
  312 + if (!appendedStyleInfo) { appendedStyleInfo = YES; [description appendFormat:@"// Styles for %@\n", viewName]; }
  313 + if (!appendedSelectorInfo) { appendedSelectorInfo = YES; [description appendFormat:@"// Selector %@\n", selector]; }
  314 + [description appendString:additional];
  315 + }
  316 + }
  317 + additional = [_stylesheet descriptionForView:view withClassName: selector inDOM:self andViewName: viewName];
  318 + if (additional && additional.length) {
  319 + if (!appendedStyleInfo) { appendedStyleInfo = YES; [description appendFormat:@"// Styles for %@\n", viewName]; }
  320 + if (!appendedSelectorInfo) { appendedSelectorInfo = YES; [description appendFormat:@"// Selector %@\n", selector]; }
  321 + [description appendString:additional];
  322 + }
  323 + }
  324 + return description;
  325 +}
  326 +
  327 +///////////////////////////////////////////////////////////////////////////////////////////////////
  328 +-(NSString *)descriptionForAllViews {
  329 + NSMutableString *description = [[NSMutableString alloc] init];
  330 + int viewCount = 0;
  331 + for (UIView *view in _registeredViews) {
  332 + [description appendString:@"\n///////////////////////////////////////////////////////////////////////////////////////////////////\n"];
  333 + viewCount++;
  334 + // This is a little hokey - because we don't get individual view names we have to come up with some.
  335 + __block NSString *vid = nil;
  336 + [[_viewToSelectorsMap objectForKey:[self keyForView:view]] enumerateObjectsUsingBlock:^(NSString *selector, NSUInteger idx, BOOL *stop) {
  337 + if ([selector hasPrefix:@"#"]) {
  338 + vid = [selector substringFromIndex:1];
  339 + *stop = YES;
  340 + }
  341 + }];
  342 + if (vid) {
  343 + [description appendFormat:@"UIView *%@_%d = [dom viewById: @\"#%@\"];\n", [view class], viewCount, vid];
  344 + }
  345 + [description appendString:[self descriptionForView:view withName:[NSString stringWithFormat:@"%@_%d", [view class], viewCount]]];
  346 + }
  347 + return description;
  348 +}
300 349 @end
7 src/css/src/NIStyleable.h
@@ -60,4 +60,11 @@
60 60 */
61 61 - (void)applyStyleWithRuleSet:(NICSSRuleset *)ruleSet forPseudoClass: (NSString*) pseudo inDOM: (NIDOM*) dom;
62 62
  63 +/**
  64 + * Return a string describing what would be done with the view. The current implementations return actual
  65 + * Objective-C using the view name as the message target. The intent is to allow developers to debug
  66 + * the logic, but also to be able to strip out the CSS infrastructure if desired and replace it with manual code.
  67 + */
  68 +- (NSString*) descriptionWithRuleSet: (NICSSRuleset*) ruleSet forPseudoClass: (NSString*) pseudo inDOM: (NIDOM*) dom withViewName: (NSString*) name;
  69 +
63 70 @end
11 src/css/src/NIStylesheet.h
@@ -64,6 +64,8 @@ extern NSString* const NIStylesheetDidChangeNotification;
64 64
65 65 - (void)applyStyleToView:(UIView *)view withClassName:(NSString *)className inDOM: (NIDOM*)dom;
66 66
  67 +- (NSString*)descriptionForView:(UIView *)view withClassName:(NSString *)className inDOM: (NIDOM*)dom andViewName: (NSString*) viewName;
  68 +
67 69 - (NICSSRuleset *)rulesetForClassName:(NSString *)className;
68 70
69 71 /**
@@ -141,3 +143,12 @@ extern NSString* const NIStylesheetDidChangeNotification;
141 143 * @param className Either the view's class as a string using NSStringFromClass([view class]);
142 144 * or a CSS class selector such as ".myClassSelector".
143 145 */
  146 +
  147 +/** @name Debugging */
  148 +
  149 +/**
  150 + * Build a string describing the rules that would be applied to the view given a css class name in a DOM.
  151 + * Current implementations output Objective-C code that use viewName as the target.
  152 + *
  153 + * @fn NIStylesheet::descriptionForView:withClassName:inDOM:andViewName:
  154 + */
18 src/css/src/NIStylesheet.m
@@ -226,6 +226,24 @@ - (void)addStylesheet:(NIStylesheet *)stylesheet {
226 226 }
227 227 }
228 228
  229 +///////////////////////////////////////////////////////////////////////////////////////////////////
  230 +- (NSString*)descriptionForView:(UIView *)view withClassName:(NSString *)className inDOM:(NIDOM *)dom andViewName:(NSString *)viewName {
  231 + NSMutableString *description = [[NSMutableString alloc] init];
  232 + NICSSRuleset *ruleset = [self rulesetForClassName:className];
  233 + if (nil != ruleset) {
  234 + NSRange r = [className rangeOfString:@":"];
  235 + if ([view respondsToSelector:@selector(descriptionWithRuleSet:forPseudoClass:inDOM:withViewName:)]) {
  236 + if (r.location != NSNotFound) {
  237 + [description appendString:[(id<NIStyleable>)view descriptionWithRuleSet:ruleset forPseudoClass:[className substringFromIndex:r.location+1] inDOM:dom withViewName:viewName]];
  238 + } else {
  239 + [description appendString:[(id<NIStyleable>)view descriptionWithRuleSet:ruleset forPseudoClass:nil inDOM:dom withViewName:viewName]];
  240 + }
  241 + } else {
  242 + [description appendFormat:@"// Description not supported for %@ with selector %@\n", view, className];
  243 + }
  244 + }
  245 + return description;
  246 +}
229 247
230 248 ///////////////////////////////////////////////////////////////////////////////////////////////////
231 249 ///////////////////////////////////////////////////////////////////////////////////////////////////
10 src/css/src/UIView+NIStyleable.h
@@ -40,7 +40,7 @@ extern NSString* const NICSSViewBackgroundColorKey;
40 40 - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet DEPRECATED_ATTRIBUTE;
41 41
42 42 /**
43   - * Applies the given rule set to this view. Call applyViewStyleWithRuleSet:inDOM: instead.
  43 + * Applies the given rule set to this view.
44 44 *
45 45 * This method is exposed primarily for subclasses to use when implementing the
46 46 * applyStyleWithRuleSet: method from NIStyleable.
@@ -48,6 +48,14 @@ extern NSString* const NICSSViewBackgroundColorKey;
48 48 - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM: (NIDOM*) dom;
49 49
50 50 /**
  51 + * Describes the given rule set when applied to this view.
  52 + *
  53 + * This method is exposed primarily for subclasses to use when implementing the
  54 + * descriptionWithRuleSetFor:forPseudoClass:inDOM:withViewName: method from NIStyleable.
  55 + */
  56 +- (NSString*) descriptionWithRuleSetForView: (NICSSRuleset*) ruleSet forPseudoClass: (NSString*) pseudo inDOM: (NIDOM*) dom withViewName: (NSString*) name;
  57 +
  58 +/**
51 59 * Build a view hierarchy. The array is a list of view specs, where viewSpec is a loosely formatted
52 60 * sequence delineated by UIViews. After a UIView, the type of the next object determines what is done
53 61 * with it:
320 src/css/src/UIView+NIStyleable.m
@@ -68,34 +68,109 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet {
68 68 [self applyViewStyleWithRuleSet:ruleSet inDOM:nil];
69 69 }
70 70
  71 +-(NSString *)descriptionWithRuleSetForView:(NICSSRuleset *)ruleSet forPseudoClass:(NSString *)pseudo inDOM:(NIDOM *)dom withViewName:(NSString *)name
  72 +{
  73 + return [self applyOrDescribe:NO ruleSet:ruleSet inDOM:dom withViewName:name];
  74 +}
  75 +
  76 +-(NSString *)descriptionWithRuleSet:(NICSSRuleset *)ruleSet forPseudoClass:(NSString *)pseudo inDOM:(NIDOM *)dom withViewName:(NSString *)name
  77 +{
  78 + return [self descriptionWithRuleSetForView:ruleSet forPseudoClass:pseudo inDOM:dom withViewName:name];
  79 +}
  80 +
71 81 ///////////////////////////////////////////////////////////////////////////////////////////////////
72 82 - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
73   - if ([ruleSet hasBackgroundColor]) { self.backgroundColor = ruleSet.backgroundColor; }
74   - if ([ruleSet hasOpacity]) { self.alpha = ruleSet.opacity; }
75   - if ([ruleSet hasBorderRadius]) { self.layer.cornerRadius = ruleSet.borderRadius; }
76   - if ([ruleSet hasBorderWidth]) { self.layer.borderWidth = ruleSet.borderWidth; }
77   - if ([ruleSet hasBorderColor]) { self.layer.borderColor = ruleSet.borderColor.CGColor; }
78   - if ([ruleSet hasAutoresizing]) { self.autoresizingMask = ruleSet.autoresizing; }
79   - if ([ruleSet hasVisible]) { self.hidden = !ruleSet.visible; }
  83 + [self applyOrDescribe:YES ruleSet:ruleSet inDOM:dom withViewName:nil];
  84 +}
80 85
  86 +///////////////////////////////////////////////////////////////////////////////////////////////////
  87 +- (NSString*)applyOrDescribe: (BOOL) apply ruleSet: (NICSSRuleset*) ruleSet inDOM: (NIDOM*)dom withViewName: (NSString*) name {
  88 + NSMutableString *desc = apply ? nil : [[NSMutableString alloc] init];
  89 + // [desc appendFormat:@"%@. = %f;\n"];
  90 + if ([ruleSet hasBackgroundColor]) {
  91 + if (apply) {
  92 + self.backgroundColor = ruleSet.backgroundColor;
  93 + } else {
  94 + CGFloat r,g,b,a;
  95 + [ruleSet.backgroundColor getRed:&r green:&g blue:&b alpha:&a];
  96 + [desc appendFormat:@"%@.backgroundColor = [UIColor colorWithRed: %f green: %f blue: %f alpha: %f];\n", name, r, g, b, a];
  97 + }
  98 + }
  99 + if ([ruleSet hasOpacity]) {
  100 + if (apply) {
  101 + self.alpha = ruleSet.opacity;
  102 + } else {
  103 + [desc appendFormat:@"%@.alpha = %f;", name, ruleSet.opacity];
  104 + }
  105 + }
  106 + if ([ruleSet hasBorderRadius]) {
  107 + if (apply) {
  108 + self.layer.cornerRadius = ruleSet.borderRadius;
  109 + } else {
  110 + [desc appendFormat:@"%@.layer.cornerRadius = %f;\n", name, ruleSet.borderRadius];
  111 + }
  112 + }
  113 + if ([ruleSet hasBorderWidth]) {
  114 + if (apply) {
  115 + self.layer.borderWidth = ruleSet.borderWidth;
  116 + } else {
  117 + [desc appendFormat:@"%@.layer.borderWidth = %f;\n", name, ruleSet.borderWidth];
  118 + }
  119 + }
  120 + if ([ruleSet hasBorderColor]) {
  121 + if (apply) {
  122 + self.layer.borderColor = ruleSet.borderColor.CGColor;
  123 + } else {
  124 + CGFloat r,g,b,a;
  125 + [ruleSet.borderColor getRed:&r green:&g blue:&b alpha:&a];
  126 + [desc appendFormat:@"%@.layer.borderColor = [UIColor colorWithRed: %f green: %f blue: %f alpha: %f].CGColor;\n", name, r, g, b, a];
  127 + }
  128 + }
  129 + if ([ruleSet hasAutoresizing]) {
  130 + if (apply) {
  131 + self.autoresizingMask = ruleSet.autoresizing;
  132 + } else {
  133 + [desc appendFormat:@"%@.autoresizingMask = (UIViewAutoresizing) %d;\n", name, ruleSet.autoresizing];
  134 + }
  135 + }
  136 + if ([ruleSet hasVisible]) {
  137 + if (apply) {
  138 + self.hidden = !ruleSet.visible;
  139 + } else {
  140 + [desc appendFormat:@"%@.hidden = %@;\n", name, ruleSet.visible ? @"NO" : @"YES"];
  141 + }
  142 + }
  143 +
81 144 ///////////////////////////////////////////////////////////////////////////////////////////////////
82 145 // View sizing
83 146 ///////////////////////////////////////////////////////////////////////////////////////////////////
84 147 // Special case auto/auto height and width
85 148 if ([ruleSet hasWidth] && [ruleSet hasHeight] &&
86 149 ruleSet.width.type == CSS_AUTO_UNIT && ruleSet.height.type == CSS_AUTO_UNIT) {
87   - [self sizeToFit];
  150 + if (apply) {
  151 + [self sizeToFit];
  152 + } else {
  153 + [desc appendFormat:@"[%@ sizeToFit];\n", name];
  154 + }
88 155 } else {
89 156 if ([ruleSet hasWidth]) {
90 157 NICSSUnit u = ruleSet.width;
91 158 CGFloat startHeight = self.frameHeight;
92 159 switch (u.type) {
93 160 case CSS_AUTO_UNIT:
94   - [self sizeToFit]; // sizeToFit the width, but retain height. Behavior somewhat undefined...
95   - self.frameHeight = startHeight;
  161 + if (apply) {
  162 + [self sizeToFit]; // sizeToFit the width, but retain height. Behavior somewhat undefined...
  163 + self.frameHeight = startHeight;
  164 + } else {
  165 + [desc appendFormat:@"[%@ sizeToFit];\n%@.frameHeight = %f;\n", name, name, startHeight];
  166 + }
96 167 break;
97 168 case CSS_PERCENTAGE_UNIT:
98   - self.frameWidth = self.superview.bounds.size.width * u.value;
  169 + if (apply) {
  170 + self.frameWidth = self.superview.bounds.size.width * u.value;
  171 + } else {
  172 + [desc appendFormat:@"%@.frameWidth = %f;\n", name, self.superview.bounds.size.width * u.value];
  173 + }
99 174 break;
100 175 case CSS_PIXEL_UNIT:
101 176 // Because padding and margin are (a) complicated to implement and (b) not relevant in a non-flow layout,
@@ -103,9 +178,17 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
103 178 // it's very useful. If someone wants to layer on padding primitives to deal with this in a more CSSy way,
104 179 // go for it.
105 180 if (u.value < 0) {
106   - self.frameWidth = self.superview.frameWidth + u.value;
  181 + if (apply) {
  182 + self.frameWidth = self.superview.frameWidth + u.value;
  183 + } else {
  184 + [desc appendFormat:@"%@.frameWidth = %f;\n", name, self.superview.frameWidth + u.value];
  185 + }
107 186 } else {
108   - self.frameWidth = u.value;
  187 + if (apply) {
  188 + self.frameWidth = u.value;
  189 + } else {
  190 + [desc appendFormat:@"%@.frameWidth = %f;\n", name, u.value];
  191 + }
109 192 }
110 193 break;
111 194 }
@@ -115,11 +198,19 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
115 198 CGFloat startWidth = self.frameWidth;
116 199 switch (u.type) {
117 200 case CSS_AUTO_UNIT:
118   - [self sizeToFit];
119   - self.frameWidth = startWidth;
  201 + if (apply) {
  202 + [self sizeToFit];
  203 + self.frameWidth = startWidth;
  204 + } else {
  205 + [desc appendFormat:@"[%@ sizeToFit];\n%@.frameWidth = %f;\n", name, name, startWidth];
  206 + }
120 207 break;
121 208 case CSS_PERCENTAGE_UNIT:
122   - self.frameHeight = self.superview.bounds.size.height * u.value;
  209 + if (apply) {
  210 + self.frameHeight = self.superview.bounds.size.height * u.value;
  211 + } else {
  212 + [desc appendFormat:@"%@.frameHeight = %f;\n", name, self.superview.bounds.size.height * u.value];
  213 + }
123 214 break;
124 215 case CSS_PIXEL_UNIT:
125 216 // Because padding and margin are (a) complicated to implement and (b) not relevant in a non-flow layout,
@@ -127,9 +218,17 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
127 218 // it's very useful. If someone wants to layer on padding primitives to deal with this in a more CSSy way,
128 219 // go for it.
129 220 if (u.value < 0) {
130   - self.frameHeight = self.superview.frameHeight + u.value;
  221 + if (apply) {
  222 + self.frameHeight = self.superview.frameHeight + u.value;
  223 + } else {
  224 + [desc appendFormat:@"%@.frameHeight = %f;\n", name, self.superview.frameHeight + u.value];
  225 + }
131 226 } else {
132   - self.frameHeight = u.value;
  227 + if (apply) {
  228 + self.frameHeight = u.value;
  229 + } else {
  230 + [desc appendFormat:@"%@.frameHeight = %f;\n", name, u.value];
  231 + }
133 232 }
134 233 break;
135 234 }
@@ -141,19 +240,27 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
141 240 ///////////////////////////////////////////////////////////////////////////////////////////////////
142 241 if ([ruleSet hasMaxWidth]) {
143 242 CGFloat max = NICSSUnitToPixels(ruleSet.maxWidth,self.frameWidth);
144   - if (self.frameWidth > max) { self.frameWidth = max; }
  243 + if (self.frameWidth > max) {
  244 + if (apply) { self.frameWidth = max; } else { [desc appendFormat:@"%@.frameWidth = %f;\n", name, max]; }
  245 + }
145 246 }
146 247 if ([ruleSet hasMaxHeight]) {
147 248 CGFloat max = NICSSUnitToPixels(ruleSet.maxHeight,self.frameHeight);
148   - if (self.frameHeight > max) { self.frameHeight = max; }
  249 + if (self.frameHeight > max) {
  250 + if (apply) { self.frameHeight = max; } else { [desc appendFormat:@"%@.frameHeight = %f;\n", name, max]; }
  251 + }
149 252 }
150 253 if ([ruleSet hasMinWidth]) {
151 254 CGFloat min = NICSSUnitToPixels(ruleSet.minWidth,self.frameWidth);
152   - if (self.frameWidth < min) { self.frameWidth = min; }
  255 + if (self.frameWidth < min) {
  256 + if (apply) { self.frameWidth = min; } else { [desc appendFormat:@"%@.frameWidth = %f;\n", name, min]; }
  257 + }
153 258 }
154 259 if ([ruleSet hasMinHeight]) {
155 260 CGFloat min = NICSSUnitToPixels(ruleSet.minHeight,self.frameHeight);
156   - if (self.frameHeight < min) { self.frameHeight = min; }
  261 + if (self.frameHeight < min) {
  262 + if (apply) { self.frameHeight = min; } else { [desc appendFormat:@"%@.frameHeight = %f;\n", name, min]; }
  263 + }
157 264 }
158 265
159 266 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -163,10 +270,18 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
163 270 NICSSUnit u = ruleSet.top;
164 271 switch (u.type) {
165 272 case CSS_PERCENTAGE_UNIT:
166   - self.frameMinY = self.superview.bounds.size.height * u.value;
  273 + if (apply) {
  274 + self.frameMinY = self.superview.bounds.size.height * u.value;
  275 + } else {
  276 + [desc appendFormat:@"%@.frameMinY = %f;\n", name, self.superview.bounds.size.height * u.value];
  277 + }
167 278 break;
168 279 case CSS_PIXEL_UNIT:
169   - self.frameMinY = u.value;
  280 + if (apply) {
  281 + self.frameMinY = u.value;
  282 + } else {
  283 + [desc appendFormat:@"%@.frameMinY = %f;\n", name, u.value];
  284 + }
170 285 break;
171 286 default:
172 287 NIDASSERT(u.type == CSS_PERCENTAGE_UNIT || u.type == CSS_PIXEL_UNIT);
@@ -177,10 +292,18 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
177 292 NICSSUnit u = ruleSet.left;
178 293 switch (u.type) {
179 294 case CSS_PERCENTAGE_UNIT:
180   - self.frameMinX = self.superview.bounds.size.width * u.value;
  295 + if (apply) {
  296 + self.frameMinX = self.superview.bounds.size.width * u.value;
  297 + } else {
  298 + [desc appendFormat:@"%@.frameMinX = %f;\n", name, self.superview.bounds.size.width * u.value];
  299 + }
181 300 break;
182 301 case CSS_PIXEL_UNIT:
183   - self.frameMinX = u.value;
  302 + if (apply) {
  303 + self.frameMinX = u.value;
  304 + } else {
  305 + [desc appendFormat:@"%@.frameMinX = %f;\n", name, u.value];
  306 + }
184 307 break;
185 308 default:
186 309 NIDASSERT(u.type == CSS_PERCENTAGE_UNIT || u.type == CSS_PIXEL_UNIT);
@@ -192,10 +315,18 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
192 315 NICSSUnit u = ruleSet.right;
193 316 switch (u.type) {
194 317 case CSS_PERCENTAGE_UNIT:
195   - self.frameMaxX = self.superview.bounds.size.width * u.value;
  318 + if (apply) {
  319 + self.frameMaxX = self.superview.bounds.size.width * u.value;
  320 + } else {
  321 + [desc appendFormat:@"%@.frameMaxX = %f;\n", name, self.superview.bounds.size.width * u.value];
  322 + }
196 323 break;
197 324 case CSS_PIXEL_UNIT:
198   - self.frameMaxX = self.superview.bounds.size.width - u.value;
  325 + if (apply) {
  326 + self.frameMaxX = self.superview.bounds.size.width - u.value;
  327 + } else {
  328 + [desc appendFormat:@"%@.frameMaxX = %f;\n", name, self.superview.bounds.size.width - u.value];
  329 + }
199 330 break;
200 331 default:
201 332 NIDASSERT(u.type == CSS_PERCENTAGE_UNIT || u.type == CSS_PIXEL_UNIT);
@@ -206,10 +337,18 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
206 337 NICSSUnit u = ruleSet.bottom;
207 338 switch (u.type) {
208 339 case CSS_PERCENTAGE_UNIT:
209   - self.frameMaxY = self.superview.bounds.size.height * u.value;
  340 + if (apply) {
  341 + self.frameMaxY = self.superview.bounds.size.height * u.value;
  342 + } else {
  343 + [desc appendFormat:@"%@.frameMaxY = %f;\n", name, self.superview.bounds.size.height * u.value];
  344 + }
210 345 break;
211 346 case CSS_PIXEL_UNIT:
212   - self.frameMaxY = self.superview.bounds.size.height - u.value;
  347 + if (apply) {
  348 + self.frameMaxY = self.superview.bounds.size.height - u.value;
  349 + } else {
  350 + [desc appendFormat:@"%@.frameMaxY = %f;\n", name, self.superview.bounds.size.height - u.value];
  351 + }
213 352 break;
214 353 default:
215 354 NIDASSERT(u.type == CSS_PERCENTAGE_UNIT || u.type == CSS_PIXEL_UNIT);
@@ -219,10 +358,19 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
219 358 if ([ruleSet hasFrameHorizontalAlign]) {
220 359 switch (ruleSet.frameHorizontalAlign) {
221 360 case UITextAlignmentCenter:
222   - self.frameMidX = self.superview.bounds.size.width / 2.0;
  361 + if (apply) {
  362 + self.frameMidX = self.superview.bounds.size.width / 2.0;
  363 + } else {
  364 + [desc appendFormat:@"%@.frameMidX = %f;\n", name, self.superview.bounds.size.width / 2.0];
  365 + }
223 366 break;
224 367 case UITextAlignmentLeft:
225   - self.frameMinX = 0;
  368 + if (apply) {
  369 + self.frameMinX = 0;
  370 + } else {
  371 + [desc appendFormat:@"%@.frameMinX = 0;\n", name];
  372 + }
  373 + break;
226 374 case UITextAlignmentRight:
227 375 self.frameMaxX = self.superview.bounds.size.width;
228 376 break;
@@ -234,12 +382,25 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
234 382 if ([ruleSet hasFrameVerticalAlign]) {
235 383 switch (ruleSet.frameVerticalAlign) {
236 384 case UIViewContentModeCenter:
237   - self.frameMidY = self.superview.bounds.size.height / 2.0;
  385 + if (apply) {
  386 + self.frameMidY = self.superview.bounds.size.height / 2.0;
  387 + } else {
  388 + [desc appendFormat:@"%@.frameMidY = %f;\n", name, self.superview.bounds.size.height / 2.0];
  389 + }
238 390 break;
239 391 case UIViewContentModeTop:
240   - self.frameMinY = 0;
  392 + if (apply) {
  393 + self.frameMinY = 0;
  394 + } else {
  395 + [desc appendFormat:@"%@.frameMinY = 0;\n", name];
  396 + }
  397 + break;
241 398 case UIViewContentModeBottom:
242   - self.frameMaxY = self.superview.bounds.size.height;
  399 + if (apply) {
  400 + self.frameMaxY = self.superview.bounds.size.height;
  401 + } else {
  402 + [desc appendFormat:@"%@.frameMaxY = %f;\n", name, self.superview.bounds.size.height];
  403 + }
243 404 break;
244 405 default:
245 406 NIDASSERT(NO);
@@ -287,7 +448,11 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
287 448 if (self.superview != relative.superview) {
288 449 anchor = [self convertPoint:anchor fromView:relative.superview];
289 450 }
290   - self.frameMidY = anchor.y;
  451 + if (apply) {
  452 + self.frameMidY = anchor.y;
  453 + } else {
  454 + [desc appendFormat:@"%@.frameMidY = %f;\n", name, anchor.y];
  455 + }
291 456 break;
292 457 case CSS_PERCENTAGE_UNIT:
293 458 case CSS_PIXEL_UNIT:
@@ -296,7 +461,11 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
296 461 if (self.superview != relative.superview) {
297 462 anchor = [self convertPoint:anchor fromView:relative.superview];
298 463 }
299   - self.frameMinY = anchor.y + NICSSUnitToPixels(top, relative.frameHeight);
  464 + if (apply) {
  465 + self.frameMinY = anchor.y + NICSSUnitToPixels(top, relative.frameHeight);
  466 + } else {
  467 + [desc appendFormat:@"%@.frameMinY = %f;\n", name, anchor.y + NICSSUnitToPixels(top, relative.frameHeight)];
  468 + }
300 469 break;
301 470 }
302 471 } else if (ruleSet.hasMarginBottom) {
@@ -308,7 +477,11 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
308 477 if (self.superview != relative.superview) {
309 478 anchor = [self convertPoint:anchor fromView:relative.superview];
310 479 }
311   - self.frameMidY = anchor.y;
  480 + if (apply) {
  481 + self.frameMidY = anchor.y;
  482 + } else {
  483 + [desc appendFormat:@"%@.frameMidY = %f;\n", name, anchor.y];
  484 + }
312 485 break;
313 486 case CSS_PERCENTAGE_UNIT:
314 487 case CSS_PIXEL_UNIT:
@@ -317,7 +490,11 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
317 490 if (self.superview != relative.superview) {
318 491 anchor = [self convertPoint:anchor fromView:relative.superview];
319 492 }
320   - self.frameMaxY = anchor.y - NICSSUnitToPixels(bottom, relative.frameHeight);
  493 + if (apply) {
  494 + self.frameMaxY = anchor.y - NICSSUnitToPixels(bottom, relative.frameHeight);
  495 + } else {
  496 + [desc appendFormat:@"%@.frameMaxY = %f;", name, anchor.y - NICSSUnitToPixels(bottom, relative.frameHeight)];
  497 + }
321 498 break;
322 499 }
323 500 }
@@ -331,7 +508,11 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
331 508 if (self.superview != relative.superview) {
332 509 anchor = [self convertPoint:anchor fromView:relative.superview];
333 510 }
334   - self.frameMidX = anchor.x;
  511 + if (apply) {
  512 + self.frameMidX = anchor.x;
  513 + } else {
  514 + [desc appendFormat:@"%@.frameMidX = %f;\n", name, anchor.x];
  515 + }
335 516 break;
336 517 case CSS_PERCENTAGE_UNIT:
337 518 case CSS_PIXEL_UNIT:
@@ -340,7 +521,11 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
340 521 if (self.superview != relative.superview) {
341 522 anchor = [self convertPoint:anchor fromView:relative.superview];
342 523 }
343   - self.frameMinX = anchor.x + NICSSUnitToPixels(left, relative.frameWidth);
  524 + if (apply) {
  525 + self.frameMinX = anchor.x + NICSSUnitToPixels(left, relative.frameWidth);
  526 + } else {
  527 + [desc appendFormat:@"%@.frameMinX = %f;\n", name, anchor.x + NICSSUnitToPixels(left, relative.frameWidth)];
  528 + }
344 529 break;
345 530 }
346 531 } else if (ruleSet.hasMarginRight) {
@@ -352,7 +537,11 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
352 537 if (self.superview != relative.superview) {
353 538 anchor = [self convertPoint:anchor fromView:relative.superview];
354 539 }
355   - self.frameMidX = anchor.x;
  540 + if (apply) {
  541 + self.frameMidX = anchor.x;
  542 + } else {
  543 + [desc appendFormat:@"%@.frameMidX = %f;\n", name, anchor.x];
  544 + }
356 545 break;
357 546 case CSS_PERCENTAGE_UNIT:
358 547 case CSS_PIXEL_UNIT:
@@ -361,12 +550,18 @@ - (void)applyViewStyleWithRuleSet:(NICSSRuleset *)ruleSet inDOM:(NIDOM *)dom {
361 550 if (self.superview != relative.superview) {
362 551 anchor = [self convertPoint:anchor fromView:relative.superview];
363 552 }
364   - self.frameMaxX = anchor.x - NICSSUnitToPixels(right, relative.frameWidth);
  553 + if (apply) {
  554 + self.frameMaxX = anchor.x - NICSSUnitToPixels(right, relative.frameWidth);
  555 + } else {
  556 + [desc appendFormat:@"%@.frameMaxX = %f;", name, anchor.x - NICSSUnitToPixels(right, relative.frameWidth)];
  557 +
  558 + }
365 559 break;
366 560 }
367 561 }
368 562 }
369 563 }
  564 + return desc;
370 565 }
371 566
372 567 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -537,9 +732,9 @@ -(void)_buildSubviews:(NSArray *)viewSpecs inDOM:(NIDOM *)dom withViewArray:(NSM
537 732 directiveValue = [kv objectForKey:NICSSViewIdKey];
538 733 if (directiveValue) {
539 734 NSAssert([directiveValue isKindOfClass:[NSString class]], @"The value of NICSSViewIdKey must be an NSString*");
540   - if (![directiveValue hasPrefix:@"#"]) {
541   - directiveValue = [@"#" stringByAppendingString:directiveValue];
542   - }
  735 + if (![directiveValue hasPrefix:@"#"]) {
  736 + directiveValue = [@"#" stringByAppendingString:directiveValue];
  737 + }
543 738 active.viewId = directiveValue;
544 739 }
545 740 directiveValue = [kv objectForKey:NICSSViewCssClassKey];
@@ -556,7 +751,7 @@ -(void)_buildSubviews:(NSArray *)viewSpecs inDOM:(NIDOM *)dom withViewArray:(NSM
556 751 if (directiveValue) {
557 752 NSAssert([directiveValue isKindOfClass:[NSString class]] || [directiveValue isKindOfClass:[NIUserInterfaceString class]], @"The value of NICSSViewCssClassKey must be an NSString* or NIUserInterfaceString*");
558 753 if ([directiveValue isKindOfClass:[NSString class]]) {
559   - directiveValue = [[NIUserInterfaceString alloc] initWithKey:directiveValue defaultValue:directiveValue];
  754 + directiveValue = [[NIUserInterfaceString alloc] initWithKey:directiveValue defaultValue:directiveValue];
560 755 }
561 756 if ([directiveValue isKindOfClass:[NIUserInterfaceString class]]) {
562 757 [((NIUserInterfaceString*)directiveValue) attach:active.view];
@@ -579,23 +774,32 @@ -(void)_buildSubviews:(NSArray *)viewSpecs inDOM:(NIDOM *)dom withViewArray:(NSM
579 774 directiveValue = [kv objectForKey:NICSSViewTargetSelectorKey];
580 775 if (directiveValue) {
581 776 NSAssert([directiveValue isKindOfClass:[NSInvocation class]] || [directiveValue isKindOfClass:[NSString class]], @"NICSSViewTargetSelectorKey must be an NSInvocation*, or an NSString* if you're adventurous and NI_DYNAMIC_VIEWS is defined.");
582   -
  777 +
583 778 #ifdef NI_DYNAMIC_VIEWS
584 779 // NSSelectorFromString has Apple rejection written all over it, even though it's documented. Since its intended
585 780 // use is primarily rapid development right now, use the #ifdef to turn it on.
586 781 if ([directiveValue isKindOfClass:[NSString class]]) {
587 782 // Let's make an invocation out of this puppy.
588   - SEL selector = NSSelectorFromString(directiveValue);
589   - directiveValue = NIInvocationWithInstanceTarget(dom.target, selector);
  783 + @try {
  784 + SEL selector = NSSelectorFromString(directiveValue);
  785 + directiveValue = NIInvocationWithInstanceTarget(dom.target, selector);
  786 + }
  787 + @catch (NSException *exception) {
  788 +#ifdef DEBUG
  789 + NIDPRINT(@"Unknown selector %@ specified on %@.", directiveValue, dom.target);
  790 +#endif
  791 + }
590 792 }
591 793 #endif
592   -
593   - NSInvocation *n = (NSInvocation*) directiveValue;
594   - if ([active.view respondsToSelector:@selector(addTarget:action:forControlEvents:)]) {
595   - [((id)active.view) addTarget: n.target action: n.selector forControlEvents: UIControlEventTouchUpInside];
596   - } else {
597   - NSString *error = [NSString stringWithFormat:@"Cannot apply NSInvocation to class %@", NSStringFromClass(active.class)];
598   - NSAssert(NO, error);
  794 +
  795 + if ([directiveValue isKindOfClass:[NSInvocation class]]) {
  796 + NSInvocation *n = (NSInvocation*) directiveValue;
  797 + if ([active.view respondsToSelector:@selector(addTarget:action:forControlEvents:)]) {
  798 + [((id)active.view) addTarget: n.target action: n.selector forControlEvents: UIControlEventTouchUpInside];
  799 + } else {
  800 + NSString *error = [NSString stringWithFormat:@"Cannot apply NSInvocation to class %@", NSStringFromClass(active.class)];
  801 + NSAssert(NO, error);
  802 + }
599 803 }
600 804 }
601 805 directiveValue = [kv objectForKey:NICSSViewSubviewsKey];
@@ -603,7 +807,7 @@ -(void)_buildSubviews:(NSArray *)viewSpecs inDOM:(NIDOM *)dom withViewArray:(NSM
603 807 NSAssert([directiveValue isKindOfClass: [NSArray class]], @"NICSSViewSubviewsKey must be an NSArray*");
604 808 [active.view _buildSubviews:directiveValue inDOM:dom withViewArray:subviews];
605 809 } else if (directiveValue)
606   - directiveValue = [kv objectForKey:NICSSViewAccessibilityLabelKey];
  810 + directiveValue = [kv objectForKey:NICSSViewAccessibilityLabelKey];
607 811 if (directiveValue) {
608 812 NSAssert([directiveValue isKindOfClass:[NSString class]], @"NICSSViewAccessibilityLabelKey must be an NSString*");
609 813 active.view.accessibilityLabel = directiveValue;

0 comments on commit 5c61300

Please sign in to comment.
Something went wrong with that request. Please try again.