activegs-ios/Common.iphone/GTMUIView+SubtreeDescription.m

185 lines
5.8 KiB
Objective-C

//
// GTMUIView+SubtreeDescription.m
//
// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
#import "GTMUIView+SubtreeDescription.h"
#if 1
static void AppendLabelFloat(NSMutableString *s, NSString *label, float f) {
[s appendString:label];
// Respects gcc warning about using == with floats.
if (fabs(f - floor(f)) < 1.0e-8) { // Essentially integer.
int d = f;
// Respects gcc warning about casting floats to ints.
[s appendFormat:@"%d", d];
} else {
[s appendFormat:@"%3.1f", f];
}
}
static NSMutableString *SublayerDescriptionLine(CALayer *layer) {
NSMutableString *result = [NSMutableString string];
[result appendFormat:@"%@ %p {", [layer class], layer];
CGRect frame = [layer frame];
if (!CGRectIsEmpty(frame)) {
AppendLabelFloat(result, @"x:", frame.origin.x);
AppendLabelFloat(result, @" y:", frame.origin.y);
AppendLabelFloat(result, @" w:", frame.size.width);
AppendLabelFloat(result, @" h:", frame.size.height);
}
CGRect bounds = [layer bounds];
if (!CGRectIsEmpty(bounds))
{
AppendLabelFloat(result, @"bounds x:", bounds.origin.x);
AppendLabelFloat(result, @" y:", bounds.origin.y);
AppendLabelFloat(result, @" w:", bounds.size.width);
AppendLabelFloat(result, @" h:", bounds.size.height);
}
[result appendFormat:@"}"];
if ([layer isHidden]) {
[result appendString:@" hid"];
}
[result appendString:@"\n"];
return result;
}
// |sublayersDescription| has a guard so we'll only call this if it is safe
// to call.
static NSMutableString *SublayerDescriptionAtLevel(CALayer *layer, int level) {
NSMutableString *result = [NSMutableString string];
for (int i = 0; i < level; ++i) {
[result appendString:@" "];
}
[result appendString:SublayerDescriptionLine(layer)];
// |sublayers| is defined in the QuartzCore framework, which isn't guaranteed
// to be linked to this program. (So we don't include the header.)
NSArray *layers = [layer performSelector:NSSelectorFromString(@"sublayers")];
for (CALayer *l in layers) {
[result appendString:SublayerDescriptionAtLevel(l, level+1)];
}
return result;
}
@implementation UIView (SubtreeDescription)
// TODO: Consider flagging things which might help in debugging:
// - alpha < 10%
// - origin not zero
// - non-opaque
// - transform if not identity
// - view not entirely within ancestor views
// - (possibly) tag==0
- (NSString *)gtm_subtreeDescriptionLine {
NSMutableString *result = [NSMutableString string];
[result appendFormat:@"%@ %p {", [self class], self];
CGRect frame = [self frame];
if (!CGRectIsEmpty(frame)) {
AppendLabelFloat(result, @"x:", frame.origin.x);
AppendLabelFloat(result, @" y:", frame.origin.y);
AppendLabelFloat(result, @" w:", frame.size.width);
AppendLabelFloat(result, @" h:", frame.size.height);
}
CGRect bounds = [self bounds];
if (!CGRectIsEmpty(bounds))
{
AppendLabelFloat(result, @"-- bounds x:", bounds.origin.x);
AppendLabelFloat(result, @" y:", bounds.origin.y);
AppendLabelFloat(result, @" w:", bounds.size.width);
AppendLabelFloat(result, @" h:", bounds.size.height);
}
[result appendString:@"}"];
CGAffineTransform t = [self transform];
if (!CGAffineTransformIsIdentity(t))
{
AppendLabelFloat(result, @"-- matrix 11:", t.a);
AppendLabelFloat(result, @" 12:", t.b);
AppendLabelFloat(result, @" 21:", t.c);
AppendLabelFloat(result, @" 22:", t.d);
AppendLabelFloat(result, @" tx:", t.tx);
AppendLabelFloat(result, @" ty:", t.ty);
}
if ([self isKindOfClass:[UIScrollView class]])
{
UIScrollView* sv = (UIScrollView*)self;
float scale = sv.zoomScale;
AppendLabelFloat(result, @" scale:", scale);
}
AppendLabelFloat(result, @" alpha:", self.alpha);
if ([self isHidden]) {
[result appendString:@" hid"];
}
if ([self respondsToSelector:@selector(myViewDescriptionLine)]) {
NSString *customDescription =
[self performSelector:@selector(myViewDescriptionLine)];
if (customDescription != nil) {
[result appendFormat:@" %@", customDescription];
}
}
[result appendString:@"\n"];
return result;
}
- (NSString *)gtm_subtreeDescriptionAtLevel:(int)level {
NSMutableString *result = [NSMutableString string];
for (int i = 0; i < level; ++i) {
[result appendString:@" "];
}
[result appendString:[self gtm_subtreeDescriptionLine]];
for (UIView *v in [self subviews]) {
[result appendString:[v gtm_subtreeDescriptionAtLevel:level+1]];
}
return result;
}
- (NSString *)subtreeDescription {
NSMutableString *result =
[[[self gtm_subtreeDescriptionLine] mutableCopy] autorelease];
for (UIView *v in [self subviews]) {
[result appendString:[v gtm_subtreeDescriptionAtLevel:1]];
}
return result;
}
// for debugging dump the layer hierarchy, frames and isHidden.
- (NSString *)sublayersDescription {
CALayer *layer = [self layer];
SEL sublayers = NSSelectorFromString(@"sublayers");
if (![layer respondsToSelector:sublayers]) {
return @"*** Sorry: This app is not linked with the QuartzCore framework.";
}
NSMutableString *result = SublayerDescriptionLine(layer);
NSArray *layers = [layer performSelector:sublayers];
for (CALayer *l in layers) {
[result appendString:SublayerDescriptionAtLevel(l, 1)];
}
return result;
}
@end
#endif // DEBUG