diff --git a/Build/ignoreme b/Build/ignoreme deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/samples/Style/TTCSSStyleSheets/Classes/StyleSheetViewController.m b/samples/Style/TTCSSStyleSheets/Classes/StyleSheetViewController.m index 41c37ab804..7209033ca8 100644 --- a/samples/Style/TTCSSStyleSheets/Classes/StyleSheetViewController.m +++ b/samples/Style/TTCSSStyleSheets/Classes/StyleSheetViewController.m @@ -17,6 +17,7 @@ #import "StyleSheetViewController.h" #import "SampleCSSStyleSheet.h" +#import "extThree20CSSStyle/TTCSSRuleSet.h" /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -50,23 +51,34 @@ - (void)loadView { } self.title = @"Three20 CSS extension"; - self.view.backgroundColor = TTCSS(@"body", backgroundColor); + self.view.backgroundColor = TTCSS( @"body", background_color ); // Using helper macro UILabel* headerLabel = [[UILabel alloc] initWithFrame:CGRectZero]; headerLabel.text = @"Header text"; + + // When using TTCSS you specify the Rule Set Name and the CSS property. headerLabel.font = TTCSS(@"h1", font); headerLabel.textColor = TTCSS(@"h1", color); - headerLabel.backgroundColor = TTCSS(@"h1", backgroundColor); - headerLabel.shadowColor = TTCSS(@"h1", shadowColor); - headerLabel.shadowOffset = TTCSS(@"h1", shadowOffset); + headerLabel.backgroundColor = TTCSS(@"h1", background_color); + + // Some CSS property have sub properties. + headerLabel.shadowColor = TTCSS(@"h1", text_shadow).shadowColor; + headerLabel.shadowOffset = TTCSS(@"h1", text_shadow).shadowOffset; + [headerLabel sizeToFit]; [self.view addSubview:headerLabel]; // Using UILabel addition UILabel* headerLabel2 = [[UILabel alloc] initWithFrame:CGRectZero]; headerLabel2.text = @"Header 2 text"; - [headerLabel2 applyCssSelector:@"h2"]; + + // Use the Helper Function TTApplyCSS and specify the Rule Set Name then the object to apply. + TTApplyCSS( @"h2", headerLabel2 ); + + // This will work too! + [headerLabel applyCssSelector:@"h2"]; + [headerLabel2 sizeToFit]; CGFloat top = headerLabel.frame.size.height; CGRect frame = headerLabel2.frame; diff --git a/samples/Style/TTCSSStyleSheets/TTCSSStyleSheets.xcodeproj/project.pbxproj b/samples/Style/TTCSSStyleSheets/TTCSSStyleSheets.xcodeproj/project.pbxproj index 4f6cae27ef..25a30133cb 100755 --- a/samples/Style/TTCSSStyleSheets/TTCSSStyleSheets.xcodeproj/project.pbxproj +++ b/samples/Style/TTCSSStyleSheets/TTCSSStyleSheets.xcodeproj/project.pbxproj @@ -33,6 +33,20 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 187835D313D5F7C2004600D3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6E3793D711B9B59D0011C497 /* Three20Network.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 662D81EF12630516005851C2; + remoteInfo = "Three20Network-Xcode3.2.5"; + }; + 187835D513D5F7C2004600D3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6E3793D711B9B59D0011C497 /* Three20Network.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 662D81B2126304EB005851C2; + remoteInfo = "Three20NetworkUnitTests-Xcode3.2.5"; + }; 6E036BCC11B38E520025E8EE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6E036BC711B38E520025E8EE /* extThree20CSSStyle.xcodeproj */; @@ -355,7 +369,9 @@ isa = PBXGroup; children = ( 6E3793EF11B9B59D0011C497 /* libThree20Network.a */, + 187835D413D5F7C2004600D3 /* libThree20Network-Xcode3.2.5.a */, 6E3793F111B9B59D0011C497 /* NetworkUnitTests.octest */, + 187835D613D5F7C2004600D3 /* NetworkUnitTests-Xcode3.2.5.octest */, ); name = Products; sourceTree = ""; @@ -546,6 +562,20 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ + 187835D413D5F7C2004600D3 /* libThree20Network-Xcode3.2.5.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libThree20Network-Xcode3.2.5.a"; + remoteRef = 187835D313D5F7C2004600D3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 187835D613D5F7C2004600D3 /* NetworkUnitTests-Xcode3.2.5.octest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "NetworkUnitTests-Xcode3.2.5.octest"; + remoteRef = 187835D513D5F7C2004600D3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 6E036BCD11B38E520025E8EE /* libextThree20CSSStyle.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; diff --git a/samples/TTCatalog/Classes/LauncherViewTestController.m b/samples/TTCatalog/Classes/LauncherViewTestController.m index 5b07f7949b..5e0d59e470 100644 --- a/samples/TTCatalog/Classes/LauncherViewTestController.m +++ b/samples/TTCatalog/Classes/LauncherViewTestController.m @@ -28,40 +28,44 @@ - (void)loadView { _launcherView.backgroundColor = [UIColor blackColor]; _launcherView.delegate = self; _launcherView.columnCount = 4; - _launcherView.pages = [NSArray arrayWithObjects: - [NSArray arrayWithObjects: - [[[TTLauncherItem alloc] initWithTitle:@"Button 1" + _launcherView.persistenceMode = TTLauncherPersistenceModeAll; + + if (![_launcherView restoreLauncherItems]) { + _launcherView.pages = [NSArray arrayWithObjects: + [NSArray arrayWithObjects: + [[[TTLauncherItem alloc] initWithTitle:@"Button 1" image:@"bundle://Icon.png" URL:nil canDelete:YES] autorelease], - [[[TTLauncherItem alloc] initWithTitle:@"Button 2" + [[[TTLauncherItem alloc] initWithTitle:@"Button 2" image:@"bundle://Icon.png" URL:nil canDelete:YES] autorelease], - [[[TTLauncherItem alloc] initWithTitle:@"Button 3" + [[[TTLauncherItem alloc] initWithTitle:@"Button 3" image:@"bundle://Icon.png" URL:@"fb://item3" canDelete:YES] autorelease], - [[[TTLauncherItem alloc] initWithTitle:@"Button 4" + [[[TTLauncherItem alloc] initWithTitle:@"Button 4" image:@"bundle://Icon.png" URL:@"fb://item4" canDelete:YES] autorelease], - [[[TTLauncherItem alloc] initWithTitle:@"Button 5" + [[[TTLauncherItem alloc] initWithTitle:@"Button 5" image:@"bundle://Icon.png" URL:@"fb://item5" canDelete:YES] autorelease], - [[[TTLauncherItem alloc] initWithTitle:@"Button 6" + [[[TTLauncherItem alloc] initWithTitle:@"Button 6" image:@"bundle://Icon.png" URL:@"fb://item6" canDelete:YES] autorelease], - [[[TTLauncherItem alloc] initWithTitle:@"Button 7" + [[[TTLauncherItem alloc] initWithTitle:@"Button 7" image:@"bundle://Icon.png" URL:@"fb://item7" canDelete:YES] autorelease], - nil], - [NSArray arrayWithObjects: - [[[TTLauncherItem alloc] initWithTitle:@"Button 8" + nil], + [NSArray arrayWithObjects: + [[[TTLauncherItem alloc] initWithTitle:@"Button 8" image:@"bundle://Icon.png" URL:nil canDelete:YES] autorelease], - [[[TTLauncherItem alloc] initWithTitle:@"Button 9" + [[[TTLauncherItem alloc] initWithTitle:@"Button 9" image:@"bundle://Icon.png" URL:nil canDelete:YES] autorelease], - nil], - nil - ]; + nil], + nil + ]; + } [self.view addSubview:_launcherView]; TTLauncherItem* item = [_launcherView itemWithURL:@"fb://item3"]; diff --git a/src/Three20/Three20.xcodeproj/project.pbxproj b/src/Three20/Three20.xcodeproj/project.pbxproj index baf543d89b..c9badb0f26 100755 --- a/src/Three20/Three20.xcodeproj/project.pbxproj +++ b/src/Three20/Three20.xcodeproj/project.pbxproj @@ -20,6 +20,20 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 18C011EC13D5EE01006DFF7A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6EE7389D1184ADB400A35176 /* Three20Network.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 662D81EF12630516005851C2; + remoteInfo = "Three20Network-Xcode3.2.5"; + }; + 18C011EE13D5EE01006DFF7A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6EE7389D1184ADB400A35176 /* Three20Network.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 662D81B2126304EB005851C2; + remoteInfo = "Three20NetworkUnitTests-Xcode3.2.5"; + }; 66FC2E291265264C00F56B19 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -362,7 +376,9 @@ isa = PBXGroup; children = ( 6EE738A31184ADB400A35176 /* libThree20Network.a */, + 18C011ED13D5EE01006DFF7A /* libThree20Network-Xcode3.2.5.a */, 6EE738A51184ADB400A35176 /* NetworkUnitTests.octest */, + 18C011EF13D5EE01006DFF7A /* NetworkUnitTests-Xcode3.2.5.octest */, ); name = Products; sourceTree = ""; @@ -487,6 +503,20 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ + 18C011ED13D5EE01006DFF7A /* libThree20Network-Xcode3.2.5.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libThree20Network-Xcode3.2.5.a"; + remoteRef = 18C011EC13D5EE01006DFF7A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 18C011EF13D5EE01006DFF7A /* NetworkUnitTests-Xcode3.2.5.octest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "NetworkUnitTests-Xcode3.2.5.octest"; + remoteRef = 18C011EE13D5EE01006DFF7A /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 6E6454A71184D42800F08CB1 /* libThree20Style.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; diff --git a/src/Three20Core/Sources/Three20Version.m b/src/Three20Core/Sources/Three20Version.m index 2f34fd5c1e..527a39d51e 100644 --- a/src/Three20Core/Sources/Three20Version.m +++ b/src/Three20Core/Sources/Three20Version.m @@ -18,6 +18,6 @@ /*! \mainpage Three20 API Documentation * - * Generated from Three20 Release 1.0.5. + * Generated from Three20 Release 1.0.7. */ -NSString* const Three20Version = @"1.0.6.2"; +NSString* const Three20Version = @"1.0.7"; diff --git a/src/Three20Network/Sources/TTURLCache.m b/src/Three20Network/Sources/TTURLCache.m index 7458bfe1ac..83fa0ede7d 100644 --- a/src/Three20Network/Sources/TTURLCache.m +++ b/src/Three20Network/Sources/TTURLCache.m @@ -264,8 +264,7 @@ - (UIImage*)loadImageFromBundle:(NSString*)URL { /////////////////////////////////////////////////////////////////////////////////////////////////// - (UIImage*)loadImageFromDocuments:(NSString*)URL { NSString* path = TTPathForDocumentsResource([URL substringFromIndex:12]); - NSData* data = [NSData dataWithContentsOfFile:path]; - return [UIImage imageWithData:data]; + return [UIImage imageWithContentsOfFile:path]; } diff --git a/src/Three20Network/Sources/TTURLImageResponse.m b/src/Three20Network/Sources/TTURLImageResponse.m index 43e5f8e5f5..fed7d97c9d 100644 --- a/src/Three20Network/Sources/TTURLImageResponse.m +++ b/src/Three20Network/Sources/TTURLImageResponse.m @@ -61,12 +61,13 @@ - (NSError*)request:(TTURLRequest*)request processResponse:(NSHTTPURLResponse*)r // TODO(jverkoey Feb 10, 2010): This logic doesn't entirely make sense. Why don't we just store // the data in the cache if there was a cache miss, and then just retain the image data we // downloaded? This needs to be tested in production. - UIImage* image = [[TTURLCache sharedCache] imageForURL:request.urlPath fromDisk:NO]; - + UIImage* image = nil; + if(!(request.cachePolicy | TTURLRequestCachePolicyNoCache)) { + image = [[TTURLCache sharedCache] imageForURL:request.urlPath fromDisk:NO]; + } if (nil == image) { image = [UIImage imageWithData:data]; } - if (nil != image) { if (!request.respondedFromCache) { // XXXjoe Working on option to scale down really large images to a smaller size to save memory diff --git a/src/Three20Network/Three20Network.xcodeproj/project.pbxproj b/src/Three20Network/Three20Network.xcodeproj/project.pbxproj index e0763eeb32..39f2f3af07 100755 --- a/src/Three20Network/Three20Network.xcodeproj/project.pbxproj +++ b/src/Three20Network/Three20Network.xcodeproj/project.pbxproj @@ -42,7 +42,6 @@ 664B29C212848AAD0008D569 /* TTErrorCodes.m in Sources */ = {isa = PBXBuildFile; fileRef = 664B29C012848AAD0008D569 /* TTErrorCodes.m */; }; 664B29C312848AAD0008D569 /* TTErrorCodes.m in Sources */ = {isa = PBXBuildFile; fileRef = 664B29C012848AAD0008D569 /* TTErrorCodes.m */; }; 66C16B1C1263059A00A7825A /* libThree20Network-Xcode3.2.5.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 662D81EF12630516005851C2 /* libThree20Network-Xcode3.2.5.a */; }; - 66C16B21126305AB00A7825A /* libThree20Core-Xcode3.2.5.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 66C16AC31263027400A7825A /* libThree20Core-Xcode3.2.5.a */; }; 66F955B0126662E300BEF6F0 /* NetworkURLCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 66F955AF126662E300BEF6F0 /* NetworkURLCacheTests.m */; }; 66F955B1126662E300BEF6F0 /* NetworkURLCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 66F955AF126662E300BEF6F0 /* NetworkURLCacheTests.m */; }; 66F955BA1266647A00BEF6F0 /* both.png in Resources */ = {isa = PBXBuildFile; fileRef = 66F955B71266647A00BEF6F0 /* both.png */; }; @@ -87,34 +86,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 662D824C12630805005851C2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6EE7366611849C5800A35176 /* Three20Core.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 664961541262EE5000C2C80E; - remoteInfo = "UnitTests-Xcode3.2.5"; - }; - 662D82E012639FCA005851C2 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6EE7366611849C5800A35176 /* Three20Core.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 664961541262EE5000C2C80E; - remoteInfo = "UnitTests-Xcode3.2.5"; - }; - 66C16AC21263027400A7825A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6EE7366611849C5800A35176 /* Three20Core.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 6650CAA21262F6E2003FF804; - remoteInfo = "Three20Core-Xcode3.2.5"; - }; - 66C16AC61263027400A7825A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6EE7366611849C5800A35176 /* Three20Core.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 664961641262EE5000C2C80E; - remoteInfo = "UnitTests-Xcode3.2.5"; - }; 66C16B26126305F500A7825A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -214,7 +185,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 66C16B21126305AB00A7825A /* libThree20Core-Xcode3.2.5.a in Frameworks */, 66C16B1C1263059A00A7825A /* libThree20Network-Xcode3.2.5.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -439,9 +409,7 @@ isa = PBXGroup; children = ( 6EE7366C11849C5800A35176 /* libThree20Core.a */, - 66C16AC31263027400A7825A /* libThree20Core-Xcode3.2.5.a */, 6EE7366E11849C5800A35176 /* CoreUnitTests.octest */, - 66C16AC71263027400A7825A /* CoreUnitTests-Xcode3.2.5.octest */, ); name = Products; sourceTree = ""; @@ -522,7 +490,6 @@ buildRules = ( ); dependencies = ( - 662D824D12630805005851C2 /* PBXTargetDependency */, 66C16B27126305F500A7825A /* PBXTargetDependency */, ); name = "Three20NetworkUnitTests-Xcode3.2.5"; @@ -542,7 +509,6 @@ buildRules = ( ); dependencies = ( - 662D82E112639FCA005851C2 /* PBXTargetDependency */, ); name = "Three20Network-Xcode3.2.5"; productName = Three20; @@ -625,20 +591,6 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ - 66C16AC31263027400A7825A /* libThree20Core-Xcode3.2.5.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libThree20Core-Xcode3.2.5.a"; - remoteRef = 66C16AC21263027400A7825A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 66C16AC71263027400A7825A /* CoreUnitTests-Xcode3.2.5.octest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = "CoreUnitTests-Xcode3.2.5.octest"; - remoteRef = 66C16AC61263027400A7825A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 6EE7366C11849C5800A35176 /* libThree20Core.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -798,16 +750,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 662D824D12630805005851C2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "UnitTests-Xcode3.2.5"; - targetProxy = 662D824C12630805005851C2 /* PBXContainerItemProxy */; - }; - 662D82E112639FCA005851C2 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "UnitTests-Xcode3.2.5"; - targetProxy = 662D82E012639FCA005851C2 /* PBXContainerItemProxy */; - }; 66C16B27126305F500A7825A /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 662D81C912630516005851C2 /* Three20Network-Xcode3.2.5 */; diff --git a/src/Three20UI/Headers/TTImageView.h b/src/Three20UI/Headers/TTImageView.h index 6e75e4fb07..d456c9627f 100644 --- a/src/Three20UI/Headers/TTImageView.h +++ b/src/Three20UI/Headers/TTImageView.h @@ -76,6 +76,11 @@ */ @property (nonatomic, assign) id delegate; +/** + * The TTURLRequest requester used to load this image. + */ +@property (nonatomic, readonly) TTURLRequest* request; + /** * Cancel any pending request, remove the image, and redraw the view. */ diff --git a/src/Three20UI/Headers/TTImageViewDelegate.h b/src/Three20UI/Headers/TTImageViewDelegate.h index a94324b7c9..ecea9b5264 100644 --- a/src/Three20UI/Headers/TTImageViewDelegate.h +++ b/src/Three20UI/Headers/TTImageViewDelegate.h @@ -38,4 +38,11 @@ */ - (void)imageView:(TTImageView*)imageView didFailLoadWithError:(NSError*)error; +/** + * Called before the image view send a network request. + * At this point we have the opportunity to configure the requester + * with some custom options (to use ETAGs, for example). + */ +- (void)imageView:(TTImageView*)imageView willSendARequest:(TTURLRequest*)requester; + @end diff --git a/src/Three20UI/Headers/TTLauncherPersistenceMode.h b/src/Three20UI/Headers/TTLauncherPersistenceMode.h new file mode 100644 index 0000000000..fcee1eade5 --- /dev/null +++ b/src/Three20UI/Headers/TTLauncherPersistenceMode.h @@ -0,0 +1,21 @@ +// +// Copyright 2009-2011 Facebook +// +// 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. +// + +typedef enum { + TTLauncherPersistenceModeNone, // no persistence + TTLauncherPersistenceModeAll, // persists all pages & buttons +} TTLauncherPersistenceMode; + diff --git a/src/Three20UI/Headers/TTLauncherView.h b/src/Three20UI/Headers/TTLauncherView.h index 391fc7fa6d..ea76f021ca 100644 --- a/src/Three20UI/Headers/TTLauncherView.h +++ b/src/Three20UI/Headers/TTLauncherView.h @@ -17,6 +17,9 @@ #import #import +// UI +#import "Three20UI/TTLauncherPersistenceMode.h" + @protocol TTLauncherViewDelegate; @class TTPageControl; @class TTLauncherButton; @@ -51,6 +54,9 @@ BOOL _springing; BOOL _editable; + NSString* _persistenceKey; + TTLauncherPersistenceMode _persistenceMode; + id _delegate; } @@ -71,6 +77,20 @@ @property (nonatomic, readonly) BOOL editing; @property (nonatomic, assign) BOOL editable; +/** + * The key to use for storing persistence information. + * + * @default launcherViewPages + */ +@property (nonatomic, copy) NSString* persistenceKey; + +/** + * How buttons are automatically persisted on termination and restored on launch. + * + * @default TTLauncherPersistenceModeNone + */ +@property (nonatomic) TTLauncherPersistenceMode persistenceMode; + - (void)addItem:(TTLauncherItem*)item animated:(BOOL)animated; - (void)removeItem:(TTLauncherItem*)item animated:(BOOL)animated; @@ -85,6 +105,21 @@ - (void)endEditing; +/** + * Persists all pages & buttons to user defaults. + */ +- (void)persistLauncherItems; + +/** + * Restores all pages & button from user defaults and returns if sucess + */ +- (BOOL)restoreLauncherItems; + +/** + * Erases all data stored in user defaults. + */ +- (void)resetDefaults; + /** * Dims the launcher view except for a transparent circle around the given item. The given text * will also be shown center-aligned below or above the circle, as appropriate. The item can be diff --git a/src/Three20UI/Headers/TTScrollView.h b/src/Three20UI/Headers/TTScrollView.h index 4fb55b532c..4c9e3c5b84 100755 --- a/src/Three20UI/Headers/TTScrollView.h +++ b/src/Three20UI/Headers/TTScrollView.h @@ -77,6 +77,11 @@ NSUInteger _touchCount; CGFloat _overshoot; + // Scroll animation. + // Set the engine to animate the next relayout. + BOOL _nextLayoutAnimated; + NSTimeInterval _centerPageAnimationDuration; + // The first touch in this view. UITouch* _touch1; @@ -91,10 +96,22 @@ } /** - * The current page index. + * Retrieve or set the current page index. + * If you inform anew value for this page, the Scroll View will + * load this page on the center of the view. + * This operatin is not animated, you should use setCenterPageIndex:animated: + * if you want to control the animation. */ @property (nonatomic) NSInteger centerPageIndex; +/** + * Set the duration for the animation performed by the setCenterPageIndex:animated: + * method. + * + * @default Is the value setted on the TT_TRANSITION_DURATION constant. + */ +@property (assign) NSTimeInterval centerPageAnimationDuration; + /** * Whether or not the current page is zoomed. */ @@ -105,10 +122,19 @@ * out. (read-only) * * The value of this property is YES if user is making a zoom gesture, otherwise it is NO - * */ @property (nonatomic, readonly) BOOL zooming; +/** + * A Boolean value that indicates whether the user is scrolling the + * view with his finger. If the scroll is scrolling by animation this + * value is NO. (read-only) + */ +@property (readonly) BOOL isDragging; + +/** + * The scroller is performing an "hold" action. + */ @property (nonatomic, readonly) BOOL holding; /** @@ -118,21 +144,29 @@ @property (nonatomic,readonly,getter=isDecelerating) BOOL decelerating; /** + * A Boolean value that determines whether scrolling is enabled. + * * @default YES */ @property (nonatomic) BOOL scrollEnabled; -/** +/* + * A Boolean value that determines whether zooming is enabled. + * * @default YES */ @property (nonatomic) BOOL zoomEnabled; /** + * A Boolean value that determines whether rotation is enabled. + * * @default YES */ @property (nonatomic) BOOL rotateEnabled; /** + * A CGFloat value that determines the gap between the pages. + * * @default 40 */ @property (nonatomic) CGFloat pageSpacing; @@ -214,6 +248,13 @@ - (void)zoomToDistance:(CGFloat)distance; +/** + * Set the current center page and optionally animate the transition. + * Only animate if the distance between the actual page and the informed + * is one. Example: If is one page 1 and you inform page 3, will not animate. + */ +- (void)setCenterPageIndex:(NSInteger)centerPageIndex animated:(BOOL)animated; + /** * Cancels any active touches and resets everything to an untouched state. */ diff --git a/src/Three20UI/Headers/TTTableView.h b/src/Three20UI/Headers/TTTableView.h index 0feebd2a1b..e71c293086 100644 --- a/src/Three20UI/Headers/TTTableView.h +++ b/src/Three20UI/Headers/TTTableView.h @@ -49,4 +49,7 @@ - (void)tableView:(UITableView*)tableView touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event; - (void)tableView:(UITableView*)tableView touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event; +@optional +- (void)tableView:(UITableView*)tableView touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event; + @end diff --git a/src/Three20UI/Headers/TTTableViewController.h b/src/Three20UI/Headers/TTTableViewController.h index 407b96edff..f08a3377b7 100644 --- a/src/Three20UI/Headers/TTTableViewController.h +++ b/src/Three20UI/Headers/TTTableViewController.h @@ -28,8 +28,6 @@ UIView* _errorView; UIView* _emptyView; - NSTimer* _bannerTimer; - UIView* _menuView; UITableViewCell* _menuCell; diff --git a/src/Three20UI/Headers/Three20UI.h b/src/Three20UI/Headers/Three20UI.h index 55771c6c3b..bcf7666c88 100644 --- a/src/Three20UI/Headers/Three20UI.h +++ b/src/Three20UI/Headers/Three20UI.h @@ -46,9 +46,11 @@ #import "Three20UI/TTScrollViewDelegate.h" #import "Three20UI/TTScrollViewDataSource.h" +// Launcher #import "Three20UI/TTLauncherView.h" #import "Three20UI/TTLauncherViewDelegate.h" #import "Three20UI/TTLauncherItem.h" +#import "Three20UI/TTLauncherPersistenceMode.h" #import "Three20UI/TTLabel.h" #import "Three20UI/TTStyledTextLabel.h" diff --git a/src/Three20UI/Sources/TTImageView.m b/src/Three20UI/Sources/TTImageView.m index 3457224814..18e2d5211a 100644 --- a/src/Three20UI/Sources/TTImageView.m +++ b/src/Three20UI/Sources/TTImageView.m @@ -44,6 +44,7 @@ @implementation TTImageView @synthesize image = _image; @synthesize defaultImage = _defaultImage; @synthesize autoresizesToImage = _autoresizesToImage; +@synthesize request = _request; @synthesize delegate = _delegate; @@ -209,6 +210,11 @@ - (void)reload { TTURLRequest* request = [TTURLRequest requestWithURL:_urlPath delegate:self]; request.response = [[[TTURLImageResponse alloc] init] autorelease]; + // Give the delegate one chance to configure the requester. + if ([_delegate respondsToSelector:@selector(imageView:willSendARequest:)]) { + [_delegate imageView:self willSendARequest:request]; + } + if (![request send]) { // Put the default image in place while waiting for the request to load if (_defaultImage && nil == self.image) { diff --git a/src/Three20UI/Sources/TTLauncherView.m b/src/Three20UI/Sources/TTLauncherView.m index 5356169632..2760397151 100644 --- a/src/Three20UI/Sources/TTLauncherView.m +++ b/src/Three20UI/Sources/TTLauncherView.m @@ -23,6 +23,7 @@ #import "Three20UI/TTPageControl.h" #import "Three20UI/UIViewAdditions.h" + // UI (private) #import "Three20UI/private/TTLauncherScrollView.h" #import "Three20UI/private/TTLauncherHighlightView.h" @@ -69,6 +70,8 @@ @implementation TTLauncherView @synthesize editing = _editing; @synthesize delegate = _delegate; @synthesize editable = _editable; +@synthesize persistenceMode = _persistenceMode; +@synthesize persistenceKey = _persistenceKey; /////////////////////////////////////////////////////////////////////////////////////////////////// - (id)initWithFrame:(CGRect)frame { @@ -99,6 +102,9 @@ - (id)initWithFrame:(CGRect)frame { self.autoresizesSubviews = YES; self.columnCount = kDefaultColumnCount; self.editable = YES; + self.persistenceKey = @"launcherViewPages"; + self.persistenceMode = TTLauncherPersistenceModeNone; + } return self; @@ -985,11 +991,50 @@ - (void)endEditing { [self layoutButtons]; + if (self.persistenceMode == TTLauncherPersistenceModeAll) { + [self persistLauncherItems]; + } + if ([_delegate respondsToSelector:@selector(launcherViewDidEndEditing:)]) { [_delegate launcherViewDidEndEditing:self]; } } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)persistLauncherItems { + NSData* pagesData = [NSKeyedArchiver archivedDataWithRootObject:self.pages]; + [[NSUserDefaults standardUserDefaults] setValue:pagesData forKey:self.persistenceKey]; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (BOOL)restoreLauncherItems { + if (self.persistenceMode == TTLauncherPersistenceModeAll) { + NSData* pagesData = [[NSUserDefaults standardUserDefaults] objectForKey:self.persistenceKey]; + + NSObject* pages; + if (pagesData!=nil) { + pages = [NSKeyedUnarchiver unarchiveObjectWithData:pagesData]; + } + + if (pagesData!=nil && pages!=nil && [pages isKindOfClass:[NSArray class]]) { + self.pages = (NSArray*)pages; + return YES; + } + } + + return NO; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)resetDefaults { + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + + [defaults removeObjectForKey:_persistenceKey]; + [defaults synchronize]; +} + + /////////////////////////////////////////////////////////////////////////////////////////////////// - (void)beginHighlightItem:(TTLauncherItem*)item withText:(NSString*)text { diff --git a/src/Three20UI/Sources/TTModelViewController.m b/src/Three20UI/Sources/TTModelViewController.m index cfbf1c8862..49cebec3d4 100644 --- a/src/Three20UI/Sources/TTModelViewController.m +++ b/src/Three20UI/Sources/TTModelViewController.m @@ -210,6 +210,7 @@ - (void)viewWillAppear:(BOOL)animated { - (void)didReceiveMemoryWarning { if (_hasViewAppeared && !_isViewAppearing) { [super didReceiveMemoryWarning]; + [self resetViewStates]; [self refresh]; } else { diff --git a/src/Three20UI/Sources/TTScrollView.m b/src/Three20UI/Sources/TTScrollView.m index 28d523ebc7..d832ed2090 100755 --- a/src/Three20UI/Sources/TTScrollView.m +++ b/src/Three20UI/Sources/TTScrollView.m @@ -64,6 +64,10 @@ @implementation TTScrollView @synthesize zoomScale = _zoomScale; @synthesize zooming = _executingZoomGesture; +@synthesize isDragging = _dragging; + +@synthesize centerPageAnimationDuration = _centerPageAnimationDuration; + /////////////////////////////////////////////////////////////////////////////////////////////////// - (id)initWithFrame:(CGRect)frame { @@ -84,6 +88,7 @@ - (id)initWithFrame:(CGRect)frame { _orientation = UIDeviceOrientationPortrait; _decelerationRate = 0.9; // Inertia, how faster slow the residual movement. _maximumZoomScale = 4.0; // Maximum zoom scale default value. + _centerPageAnimationDuration = TT_TRANSITION_DURATION; for (NSInteger i = 0; i < _maxPages; ++i) { [_pages addObject:[NSNull null]]; @@ -485,7 +490,7 @@ - (void)adjustPageEdgesForPageAtIndex:(NSInteger)pageIndex { /////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)moveToPageAtIndex:(NSInteger)pageIndex resetEdges:(BOOL)resetEdges { +- (void)moveToPageAtIndex:(NSInteger)pageIndex resetEdges:(BOOL)resetEdges animated:(BOOL)animated { if (resetEdges) { _pageEdges = _pageStartEdges = UIEdgeInsetsZero; _zooming = NO; @@ -521,13 +526,22 @@ - (void)moveToPageAtIndex:(NSInteger)pageIndex resetEdges:(BOOL)resetEdges { _pageArrayIndex = [self arrayIndexForPageIndex:pageIndex relativeToIndex:_centerPageIndex]; _centerPageIndex = pageIndex; [self setNeedsLayout]; + + // Should animate the next relayout? + _nextLayoutAnimated = animated; } } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)moveToPageAtIndex:(NSInteger)pageIndex resetEdges:(BOOL)resetEdges { + [self moveToPageAtIndex:pageIndex resetEdges:resetEdges animated:NO]; +} /////////////////////////////////////////////////////////////////////////////////////////////////// - (void)layoutPage { UIView* page = [self pageAtIndex:_centerPageIndex create:YES]; + + // Layout. if (nil != page) { CGAffineTransform rotation = TTRotateTransformForOrientation(_orientation); CGPoint offset = [self offsetForOrientation:_pageEdges.left y:_pageEdges.top]; @@ -538,13 +552,37 @@ - (void)layoutPage { page.transform = [self rotateTransform:CGAffineTransformScale( CGAffineTransformMakeTranslation(offset.x, offset.y), zoom, zoom)]; + + // Should animate the relayout? + if ( _nextLayoutAnimated ) { + [UIView beginAnimations:@"pageAnimation" context:nil]; + [UIView setAnimationDuration:_centerPageAnimationDuration]; + } page.frame = CGRectMake(offset.x + frame.origin.x*zoom, offset.y + frame.origin.y*zoom, frame.size.width*zoom, frame.size.height*zoom); + // Should animate the relayout? + if ( _nextLayoutAnimated ) { + [UIView commitAnimations]; + } + } else { + page.transform = rotation; + + // Should animate the relayout? + if ( _nextLayoutAnimated ) { + [UIView beginAnimations:@"pageAnimation" context:nil]; + [UIView setAnimationDuration:_centerPageAnimationDuration]; + } + page.frame = CGRectMake(offset.x + frame.origin.x, offset.y + frame.origin.y, frame.size.width, frame.size.height); + + // Should animate the relayout? + if ( _nextLayoutAnimated ) { + [UIView commitAnimations]; + } } } } @@ -559,6 +597,9 @@ - (void)layoutAdjacentPages { NSInteger minPageIndex = _centerPageIndex - kOffscreenPages; NSInteger maxPageIndex = _centerPageIndex + kOffscreenPages; + // Determine the direction. + BOOL isGoingLeft = _centerPageIndex < _visiblePageIndex; + CGRect centerFrame = [self frameOfPageAtIndex:_centerPageIndex]; CGFloat centerPageOverflow = [self overflowForFrame:centerFrame] * self.zoomFactor; @@ -576,9 +617,21 @@ - (void)layoutAdjacentPages { CGPoint offset = [self offsetForOrientation:x y:0]; page.transform = rotation; + + // Should animate the the "going right" relayout? + if ( _nextLayoutAnimated && !isGoingLeft ) { + [UIView beginAnimations:@"pageAnimation" context:nil]; + [UIView setAnimationDuration:_centerPageAnimationDuration]; + } + page.frame = CGRectMake(offset.x + frame.origin.x, offset.y + frame.origin.y, frame.size.width, frame.size.height); page.hidden = pinched; + + // Should animate the the "going right" relayout? + if ( _nextLayoutAnimated && !isGoingLeft) { + [UIView commitAnimations]; + } } } @@ -597,9 +650,22 @@ - (void)layoutAdjacentPages { CGPoint offset = [self offsetForOrientation:x y:0]; page.transform = rotation; + + // Should animate the "going left" relayout? + if ( _nextLayoutAnimated && isGoingLeft ) { + [UIView beginAnimations:@"pageAnimation" context:nil]; + [UIView setAnimationDuration:_centerPageAnimationDuration]; + } + page.frame = CGRectMake(offset.x + frame.origin.x, offset.y + frame.origin.y, frame.size.width, frame.size.height); page.hidden = pinched; + + // Should animate the "going left" relayout? + if ( _nextLayoutAnimated && isGoingLeft) { + [UIView commitAnimations]; + } + } } } @@ -1541,6 +1607,9 @@ - (void)layoutSubviews { _visiblePageIndex = _centerPageIndex; [_delegate scrollView:self didMoveToPageAtIndex:_centerPageIndex]; } + + // Reset the layout animated flag. + _nextLayoutAnimated = NO; } @@ -1588,6 +1657,13 @@ - (void)setDataSource:(id)dataSource { [self reloadData]; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)setCenterPageIndex:(NSInteger)centerPageIndex animated:(BOOL)animated { + // TODO: Fix limitation, for now only animate the distance of one page .. :( + animated = ( _centerPageIndex-centerPageIndex >= -1 || _centerPageIndex+centerPageIndex <= 1 ); + + [self moveToPageAtIndex:centerPageIndex resetEdges:!_touchCount animated:animated]; +} /////////////////////////////////////////////////////////////////////////////////////////////////// - (void)setCenterPageIndex:(NSInteger)centerPageIndex { diff --git a/src/Three20UI/Sources/TTTableView.m b/src/Three20UI/Sources/TTTableView.m index 2746cf1682..4911969943 100644 --- a/src/Three20UI/Sources/TTTableView.m +++ b/src/Three20UI/Sources/TTTableView.m @@ -102,6 +102,15 @@ - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { // } } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesMoved:touches withEvent:event]; + + if ([self.delegate respondsToSelector:@selector(tableView:touchesMoved:withEvent:)]) { + id delegate = (id)self.delegate; + [delegate tableView:self touchesMoved:touches withEvent:event]; + } +} /////////////////////////////////////////////////////////////////////////////////////////////////// - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { diff --git a/src/Three20UI/Sources/TTTableViewController.m b/src/Three20UI/Sources/TTTableViewController.m index ec9d989f23..ed36ced4ff 100644 --- a/src/Three20UI/Sources/TTTableViewController.m +++ b/src/Three20UI/Sources/TTTableViewController.m @@ -229,6 +229,15 @@ - (void)hideMenuAnimationDidStop:(NSString*)animationID finished:(NSNumber*)fini - (void)loadView { [super loadView]; self.tableView; + + // If this view was unloaded and is now being reloaded, and it was previously + // showing a table banner, then redisplay that banner now. + if (_tableBannerView) { + UIView* savedTableBannerView = [_tableBannerView retain]; + [self setTableBannerView:nil animated:NO]; + [self setTableBannerView:savedTableBannerView animated:NO]; + [savedTableBannerView release]; + } } @@ -239,8 +248,6 @@ - (void)viewDidUnload { _tableView.dataSource = nil; TT_RELEASE_SAFELY(_tableDelegate); TT_RELEASE_SAFELY(_tableView); - [_tableBannerView removeFromSuperview]; - TT_RELEASE_SAFELY(_tableBannerView); [_tableOverlayView removeFromSuperview]; TT_RELEASE_SAFELY(_tableOverlayView); [_loadingView removeFromSuperview]; @@ -253,6 +260,9 @@ - (void)viewDidUnload { TT_RELEASE_SAFELY(_menuView); [_menuCell removeFromSuperview]; TT_RELEASE_SAFELY(_menuCell); + + // Do not release _tableBannerView, because we have no way to recreate it on demand if + // this view gets reloaded. } @@ -687,7 +697,6 @@ - (void)setTableBannerView:(UIView*)tableBannerView { /////////////////////////////////////////////////////////////////////////////////////////////////// - (void)setTableBannerView:(UIView*)tableBannerView animated:(BOOL)animated { - TT_INVALIDATE_TIMER(_bannerTimer); if (tableBannerView != _tableBannerView) { if (_tableBannerView) { if (animated) { @@ -705,7 +714,6 @@ - (void)setTableBannerView:(UIView*)tableBannerView animated:(BOOL)animated { self.tableView.contentInset = UIEdgeInsetsMake(0, 0, TTSTYLEVAR(tableBannerViewHeight), 0); self.tableView.scrollIndicatorInsets = self.tableView.contentInset; _tableBannerView.frame = [self rectForBannerView]; - _tableBannerView.userInteractionEnabled = NO; _tableBannerView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin); [self addSubviewOverTableView:_tableBannerView]; diff --git a/src/Three20UI/Three20UI.xcodeproj/project.pbxproj b/src/Three20UI/Three20UI.xcodeproj/project.pbxproj index 9452ee2b3e..95037af928 100755 --- a/src/Three20UI/Three20UI.xcodeproj/project.pbxproj +++ b/src/Three20UI/Three20UI.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 66F2E85712D426AF006FB485 /* TTTableFooterInfiniteScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 66F2E85512D426AF006FB485 /* TTTableFooterInfiniteScrollView.m */; }; 66F2E85F12D426DA006FB485 /* TTTableViewNetworkEnabledDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 66F2E85D12D426DA006FB485 /* TTTableViewNetworkEnabledDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 66F2E86512D426EF006FB485 /* TTTableViewNetworkEnabledDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 66F2E86312D426EF006FB485 /* TTTableViewNetworkEnabledDelegate.m */; }; + 6DB1E37D13CA885B00A72466 /* TTLauncherPersistenceMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 6DB1E37C13CA885B00A72466 /* TTLauncherPersistenceMode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E60820111B0C31400C93CD4 /* TTNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E6081FF11B0C31400C93CD4 /* TTNavigationController.m */; }; 6E60820311B0C32600C93CD4 /* TTNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E60820211B0C32600C93CD4 /* TTNavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E6454741184D2CD00F08CB1 /* Three20UI.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E6454731184D2CD00F08CB1 /* Three20UI.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -443,6 +444,7 @@ 66F2E85512D426AF006FB485 /* TTTableFooterInfiniteScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTTableFooterInfiniteScrollView.m; path = Sources/TTTableFooterInfiniteScrollView.m; sourceTree = ""; }; 66F2E85D12D426DA006FB485 /* TTTableViewNetworkEnabledDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTTableViewNetworkEnabledDelegate.h; path = Headers/TTTableViewNetworkEnabledDelegate.h; sourceTree = ""; }; 66F2E86312D426EF006FB485 /* TTTableViewNetworkEnabledDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTTableViewNetworkEnabledDelegate.m; path = Sources/TTTableViewNetworkEnabledDelegate.m; sourceTree = ""; }; + 6DB1E37C13CA885B00A72466 /* TTLauncherPersistenceMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTLauncherPersistenceMode.h; path = Headers/TTLauncherPersistenceMode.h; sourceTree = ""; }; 6E6081FF11B0C31400C93CD4 /* TTNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTNavigationController.m; path = Sources/TTNavigationController.m; sourceTree = ""; }; 6E60820211B0C32600C93CD4 /* TTNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTNavigationController.h; path = Headers/TTNavigationController.h; sourceTree = ""; }; 6E64543D1184BE1B00F08CB1 /* Project.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Project.xcconfig; path = Configurations/Project.xcconfig; sourceTree = ""; }; @@ -1561,6 +1563,7 @@ 6E64583E1184E26500F08CB1 /* Launcher */ = { isa = PBXGroup; children = ( + 6DB1E37C13CA885B00A72466 /* TTLauncherPersistenceMode.h */, 6E6454D61184D4C500F08CB1 /* TTLauncherView.h */, 6E6456121184D4DA00F08CB1 /* TTLauncherView.m */, 6E6454D71184D4C500F08CB1 /* TTLauncherViewDelegate.h */, @@ -1859,6 +1862,7 @@ 666E18F51294543F001C1D97 /* TTSplitViewController.h in Headers */, 66F2E85412D426A5006FB485 /* TTTableFooterInfiniteScrollView.h in Headers */, 66F2E85F12D426DA006FB485 /* TTTableViewNetworkEnabledDelegate.h in Headers */, + 6DB1E37D13CA885B00A72466 /* TTLauncherPersistenceMode.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/Three20UICommon/Sources/UIViewControllerAdditions.m b/src/Three20UICommon/Sources/UIViewControllerAdditions.m index d6b351ed1b..dbc7fbb6f4 100644 --- a/src/Three20UICommon/Sources/UIViewControllerAdditions.m +++ b/src/Three20UICommon/Sources/UIViewControllerAdditions.m @@ -299,16 +299,22 @@ - (void)delayDidEnd { /////////////////////////////////////////////////////////////////////////////////////////////////// - (void)showBars:(BOOL)show animated:(BOOL)animated { -#ifdef __IPHONE_3_2 - if ([[UIApplication sharedApplication] - respondsToSelector:@selector(setStatusBarHidden:withAnimation:)]) - [[UIApplication sharedApplication] setStatusBarHidden:!show - withAnimation:(animated - ? UIStatusBarAnimationFade - : UIStatusBarAnimationNone)]; - else -#endif - [[UIApplication sharedApplication] setStatusBarHidden:!show animated:animated]; + + BOOL statusBarHidden = [[[[NSBundle mainBundle] infoDictionary] + objectForKey:@"UIStatusBarHidden"] boolValue]; + + if (!statusBarHidden) { + #ifdef __IPHONE_3_2 + if ([[UIApplication sharedApplication] + respondsToSelector:@selector(setStatusBarHidden:withAnimation:)]) + [[UIApplication sharedApplication] setStatusBarHidden:!show + withAnimation:(animated + ? UIStatusBarAnimationFade + :UIStatusBarAnimationNone)]; + else + #endif + [[UIApplication sharedApplication] setStatusBarHidden:!show animated:animated]; + } if (animated) { [UIView beginAnimations:nil context:NULL]; diff --git a/src/common/Configurations/Library.xcconfig b/src/common/Configurations/Library.xcconfig index fca6eb4639..dc10fbd026 100644 --- a/src/common/Configurations/Library.xcconfig +++ b/src/common/Configurations/Library.xcconfig @@ -38,6 +38,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 3.0 SDKROOT = iphoneos // Required for older iOS devices (iPhone 3G) ARCHS = $(ARCHS_STANDARD_32_BIT) +ARCHS[sdk=iphoneos*] = armv6 armv7 // Linker Flags diff --git a/src/common/Configurations/Project.xcconfig b/src/common/Configurations/Project.xcconfig index b1d750d9a6..2cef1da7a4 100644 --- a/src/common/Configurations/Project.xcconfig +++ b/src/common/Configurations/Project.xcconfig @@ -21,3 +21,4 @@ IPHONEOS_DEPLOYMENT_TARGET = 3.0 SDKROOT = iphoneos // Required for older iOS devices (iPhone 3G) ARCHS = $(ARCHS_STANDARD_32_BIT) +ARCHS[sdk=iphoneos*] = armv6 armv7 \ No newline at end of file diff --git a/src/extThree20CSSStyle/Headers/TTCSSApplyProtocol.h b/src/extThree20CSSStyle/Headers/TTCSSApplyProtocol.h new file mode 100644 index 0000000000..e1fffd89d7 --- /dev/null +++ b/src/extThree20CSSStyle/Headers/TTCSSApplyProtocol.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 - SEQOY.org and Paulo Oliveira ( http://www.seqoy.org ) + * + * 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 "extThree20CSSStyle/TTCSSRuleSet.h" + +/** + * TTCSSApplyProtocol defines an common interface to classes that style itself + * using CSS readed properties. This classes should implement this protocol + * and his appropriate methods. + */ +@protocol TTCSSApplyProtocol +@required + +/** + * Receive an Set of Rules from some CSS selector to apply. This method + * receive an TTCSSRuleSet with all properties ready to be set. + */ +-(void)applyCssRules:(TTCSSRuleSet*)anRuleSet; + +/** + * Set a CSS stylesheet selector. + */ +- (void)applyCssSelector:(NSString *)selector; + +@end diff --git a/src/extThree20CSSStyle/Headers/TTCSSFunctions.h b/src/extThree20CSSStyle/Headers/TTCSSFunctions.h new file mode 100644 index 0000000000..de67f6c334 --- /dev/null +++ b/src/extThree20CSSStyle/Headers/TTCSSFunctions.h @@ -0,0 +1,28 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 +#import + +/** + * Helper function to convert an CSS readed colors to UIColor. + */ +UIColor* TTColorFromCssValues( NSArray* cssValues ); + +/** + * Helper function to convert an CSS readed size to CGFloat. + */ +CGFloat TTValueFromCssValues( NSString* value ); diff --git a/src/extThree20CSSStyle/Headers/TTCSSGlobalStyle.h b/src/extThree20CSSStyle/Headers/TTCSSGlobalStyle.h index d15733b396..1f5ea2a483 100644 --- a/src/extThree20CSSStyle/Headers/TTCSSGlobalStyle.h +++ b/src/extThree20CSSStyle/Headers/TTCSSGlobalStyle.h @@ -20,26 +20,45 @@ #define TTCSSSTYLESHEET ([[TTDefaultCSSStyleSheet globalCSSStyleSheet] styleSheet]) #define TTCSS_color(_SELECTOR, _STATE) \ -([TTCSSSTYLESHEET colorWithCssSelector:_SELECTOR forState:_STATE]) + ([TTCSSSTYLESHEET colorWithCssSelector:_SELECTOR forState:_STATE]) #define TTCSS_backgroundColor(_SELECTOR, _STATE) \ -([TTCSSSTYLESHEET backgroundColorWithCssSelector:_SELECTOR forState:_STATE]) + ([TTCSSSTYLESHEET backgroundColorWithCssSelector:_SELECTOR forState:_STATE]) #define TTCSS_font(_SELECTOR, _STATE) \ -([TTCSSSTYLESHEET fontWithCssSelector:_SELECTOR forState:_STATE]) + ([TTCSSSTYLESHEET fontWithCssSelector:_SELECTOR forState:_STATE]) #define TTCSS_shadowColor(_SELECTOR, _STATE) \ -([TTCSSSTYLESHEET textShadowColorWithCssSelector:_SELECTOR forState:_STATE]) + ([TTCSSSTYLESHEET textShadowColorWithCssSelector:_SELECTOR forState:_STATE]) #define TTCSS_shadowOffset(_SELECTOR, _STATE) \ -([TTCSSSTYLESHEET textShadowOffsetWithCssSelector:_SELECTOR forState:_STATE]) + ([TTCSSSTYLESHEET textShadowOffsetWithCssSelector:_SELECTOR forState:_STATE]) #define TTCSS_shadowRadius(_SELECTOR, _STATE) \ -([TTCSSSTYLESHEET textShadowRadiusWithCssSelector:_SELECTOR forState:_STATE]) + ([TTCSSSTYLESHEET textShadowRadiusWithCssSelector:_SELECTOR forState:_STATE]) // _VARNAME must be one of: color, backgroundColor, font, shadowColor, shadowOffset, shadowRadius #define TTCSSSTATE(_SELECTOR, _VARNAME, _STATE) \ -TTCSS_##_VARNAME(_SELECTOR, _STATE) + TTCSS_##_VARNAME(_SELECTOR, _STATE) -#define TTCSS(_SELECTOR, _VARNAME) \ -TTCSSSTATE(_SELECTOR, _VARNAME, UIControlStateNormal) +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Retrieve a Full CSS Rule (TTCSSRuleSet) for specified selector. + */ +#define TTCSSRule(selector) (TTCSSRuleSet*)[[TTDefaultCSSStyleSheet\ + globalCSSStyleSheet] css:selector] + +/** + * Retrieve an value for a property of an Rule Set (TTCSSRuleSet) for specified selector. + */ +#define TTCSS(selector,property) [TTCSSRule(selector) property] + +/** + * Apply an CSS style to specified object. + * The object must conform with the TTCSSApplyProtocol. + */ +#define TTApplyCSS(selector,object) [[TTDefaultCSSStyleSheet globalCSSStyleSheet]\ + applyCssFromSelector:selector\ + toObject:object] diff --git a/src/extThree20CSSStyle/Headers/TTCSSRuleSet.h b/src/extThree20CSSStyle/Headers/TTCSSRuleSet.h new file mode 100644 index 0000000000..048c71685e --- /dev/null +++ b/src/extThree20CSSStyle/Headers/TTCSSRuleSet.h @@ -0,0 +1,264 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 +#import + +#import "TTCSSTextShadowModel.h" + +@interface TTCSSRuleSet : NSObject { + NSString *selector; + + // Colors. + UIColor *color; + UIColor *background_color; + + // Font properties. + NSString *font_family; + NSString *font_weight; + NSNumber *font_size; + + // Alignment and Justification. + NSString *text_align; + + // Text Shadow. + TTCSSTextShadowModel* text_shadow; + NSNumber* text_shadow_opacity; + + // Background properties. + NSString *background_image; + + // Visibility. + NSString *visibility; + + // Positioning and size. + NSString *width; + NSString *height; + NSString *top; + NSString *left; + NSString *right; + NSString *bottom; + + // Object alignment. + NSString *vertical_align; + + // Margins. + NSString *margin_right; + NSString *margin_left; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Properties. + +/** + * The identifier for this rule set. Also knowed as selector + */ +@property (copy) NSString *selector; + +/** + * A font family name only specifies a name given to a set of font faces, + * it does not specify an individual face. + * You can call [UIFont familyNames] to retrieve a list of + * available fonts on your system. Font family name is case-sensitive, + * make sure to inform correctly. + * See CSS3 Font Family + * for more information.
+ * Default value is the first Default Font Family. + */ +@property (copy) NSString *font_family; + +/** + * The ‘font-weight’ property specifies weight of glyphs in the font. + * In iOS each font has different font weight descriptions (such as Medium, Light, Oblique, etc.). + * You can call [UIFont familyNames] to retrieve a list of available fonts on your system. + * Default value is nil.
+ *
+ * Example:
+ * To use the font Helvetica-BoldOblique you should + * inform BoldOblique as font-weight and Helvetica as font_family. + *
+ * Font weight name is case-sensitive, make sure to inform correctly. + */ +@property (copy) NSString *font_weight; + +/** + * This property indicates the desired height of glyphs from the font. + * This value is always interpreted in points, regardless of what you specify. + * This is due to the tricky nature of varying DPI on the various iPhone OS devices. + * Default value is the Default System Font Size ([UIFont systemFontSize]). + */ +@property (copy) NSNumber *font_size; + +/** + * This property describes how inline contents of a block are horizontally + * aligned. Values have the following meanings:
+ * - left: Align text along the left edge.
+ * - center: Align text equally along both sides of the center line.
+ * - right: Align text along the right edge.
+ *
+ * Use the textAlign method to retrieve an iOS formatted UITextAlignment + * based on this values. + */ +@property (copy) NSString* text_align; + +/** + * This property specifies the size of an element’s rendering box. + * Possible Values:
+ * - auto: The width is determinant on the values of other properties. + * - length: Refers to an absolute measurement for the computed + * element box width. Negative values are not allowed. + * - percentage: Refers to a percentage of the width of the containing + * element block.
+ * Examples:
+ * "75px", "50%" + */ +@property (copy) NSString* width; + +/** + * /copydef width + */ +@property (copy) NSString* height; + +@property (copy) NSString* top; +@property (copy) NSString* left; +@property (copy) NSString* right; +@property (copy) NSString* bottom; + +/** + * The visibility property specifies whether or not an element is visible. + * Possible Values:
+ * - visible: The element is visible. This is default. + * - hidden: The element is invisible. + */ +@property (copy) NSString* visibility; + +/** + * An TTCSSTextShadowModel object that define a text shadow properties. + */ +@property (retain) TTCSSTextShadowModel* text_shadow; + +/** + * Specifies the opacity of the receiver’s text shadow. + * The default value is 0. + */ +@property (copy) NSNumber* text_shadow_opacity; + +/** + * This property describes the foreground color of an element. + * Default value is a transparent color. + */ +@property (retain) id color; + +/** + * This property describes the background color of an element. + * Default value is a transparent color. + */ +@property (retain) id background_color; + +/** + * This property sets the background image(s) of an element. + * Default value is nil. + */ +@property (copy) NSString *background_image; + +/** + * This property sets the vertical alignment of an element. + * Values have the following meanings:
+ * - top: The top of the element is aligned with the top of the + * tallest element on the line.
+ * - middle: The element is placed in the middle of the parent element.
+ * - bottom: The bottom of the element is aligned with the lowest element on the line.
+ *
+ * Use the contentVerticalAlignment method to retrieve an iOS formatted + * UIControlContentVerticalAlignment based on this values. + */ +@property (copy) NSString* vertical_align; + +/** + * This property specifies the left margin of an element. + * Possible Values:
+ * - auto: The left margin is calculated automatically. + * - length: Specifies a fixed left margin in px. + * - percentage: Specifies a left margin in percent. + * Examples:
+ * "75px", "50%" + */ +@property (copy) NSString* margin_left; + +/** + * This property specifies the right margin of an element. + * Possible Values:
+ * - auto: The right margin is calculated automatically. + * - length: Specifies a fixed right margin in px. + * - percentage: Specifies a left margin in percent. + * Examples:
+ * "75px", "50%" + */ +@property (copy) NSString* margin_right; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Init Methods. ++(id)initWithSelectorName:(NSString*)anRuleSetName; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Data Methods. + +/** + * Return an formatted UIFont object based on the defined properties. + * Will return nil if can't format. + */ +-(UIFont*)font; + +/** + * Return an formatted UITextAlignment based on the defined 'text_align' property. + * If isn't setted return default left alignment. + */ +-(UITextAlignment)textAlign; + +/** + * Return an formatted CGSize based on the defined 'width' + * and 'height' properties. + */ +-(CGSize)size; + +/** + * Return an formatted CGPoint based on the defined 'top' + * and 'left' properties. + */ +-(CGPoint)origin; + +/** + * Return an Boolean value that determines whether the receiver is hidden based + * on the 'visibility' property. + */ +-(BOOL)hidden; + +/** + * Return an formatted UIControlContentVerticalAlignment based on the defined + * 'vertical_align' property. If isn't setted return default top alignment. + */ +-(UIControlContentVerticalAlignment)contentVerticalAlignment; + +/** + * Return an formatted UIControlContentHorizontalAlignment based on the defined + * 'margin-left' and margin-right properties. + * If isn't setted return default left alignment. + */ +-(UIControlContentHorizontalAlignment)contentHorizontalAlignment; +@end diff --git a/src/extThree20CSSStyle/Headers/TTCSSStyleSheet.h b/src/extThree20CSSStyle/Headers/TTCSSStyleSheet.h index 32c3e1a8a9..efcf8aac6b 100644 --- a/src/extThree20CSSStyle/Headers/TTCSSStyleSheet.h +++ b/src/extThree20CSSStyle/Headers/TTCSSStyleSheet.h @@ -16,6 +16,7 @@ #import #import +#import "extThree20CSSStyle/TTDataPopulatorDelegate.h" /** * A general purpose CSS style sheet object for accessing a CSS style sheet's properties. @@ -25,17 +26,26 @@ * * Example apps: three20/samples/Style/TTCSSStyleSheets */ -@interface TTCSSStyleSheet : NSObject { +@class TTCSSRuleSet; +@interface TTCSSStyleSheet : NSObject { @private + + // The "crude" Styles readed from CSS file. NSDictionary* _cssStyles; - NSMutableDictionary* _cachedCssStyles; + // An collection of loaded TTCSSRuleSet. + NSDictionary* _cssRulesSet; - NSDictionary* _colorLookupTable; + // CSS mapped properties. + NSDictionary* _propertiesMap; } @property (nonatomic, readonly) NSDictionary* cssStyles; +/** + * An collection of loaded TTCSSRuleSet. + */ +@property (readonly) NSDictionary* cssRulesSet; /** * Load the style sheet into memory from disk. @@ -51,35 +61,74 @@ /** - * Get (text) color from a specific rule set. + * Get (text) color from a specific rule set, also accept an specific state. */ - (UIColor*)colorWithCssSelector:(NSString*)selector forState:(UIControlState)state; /** - * Get background-color from a specific rule set. + * Get (text) color from a specific rule set. + */ +- (UIColor*)colorWithCssSelector:(NSString*)selector; + +/** + * Get background-color from a specific rule set, also accept an specific state. */ - (UIColor*)backgroundColorWithCssSelector:(NSString*)selector forState:(UIControlState)state; /** - * Get font from a specific rule set. + * Get background-color from a specific rule set. + */ +- (UIColor*)backgroundColorWithCssSelector:(NSString*)selector; + +/** + * Get font from a specific rule set, also accept an specific state. */ - (UIFont*)fontWithCssSelector:(NSString*)selector forState:(UIControlState)state; /** - * Get text shadow color from a specific rule set. + * Get font from a specific rule set and 'normal' state. + */ +- (UIFont*)fontWithCssSelector:(NSString*)selector; + +/** + * Get text shadow color from a specific rule set, also accept an specific state. */ - (UIColor*)textShadowColorWithCssSelector:(NSString*)selector forState:(UIControlState)state; /** - * Get text shadow offset from a specific rule set. + * Get text shadow color from a specific rule set. + */ +- (UIColor*)textShadowColorWithCssSelector:(NSString*)selector; + +/** + * Get text shadow offset from a specific rule set, also accept an specific state. */ - (CGSize)textShadowOffsetWithCssSelector:(NSString*)selector forState:(UIControlState)state; +/** + * Get text shadow offset from a specific rule set. + */ +- (CGSize)textShadowOffsetWithCssSelector:(NSString*)selector; + /** * Get text shadow radius from a specific rule set. */ +- (CGFloat)textShadowRadiusWithCssSelector:(NSString*)selector; + +/** + * Get text shadow radius from a specific rule set, also accept an specific state. + */ - (CGFloat)textShadowRadiusWithCssSelector:(NSString*)selector forState:(UIControlState)state; +/** + * CSS Rule Set. + */ +-(TTCSSRuleSet*)css:(NSString*)selectorName; + +/** + * CSS Rule Set, also accept an specific state. + */ +-(TTCSSRuleSet*)css:(NSString*)selectorName forState:(UIControlState)state; /** * Release all cached data. diff --git a/src/extThree20CSSStyle/Headers/TTCSSTextShadowModel.h b/src/extThree20CSSStyle/Headers/TTCSSTextShadowModel.h new file mode 100644 index 0000000000..08be8367d8 --- /dev/null +++ b/src/extThree20CSSStyle/Headers/TTCSSTextShadowModel.h @@ -0,0 +1,55 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 + +@interface TTCSSTextShadowModel : NSObject { + + UIColor* shadowColor; + NSNumber* shadowBlur; + CGSize shadowOffset; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Properties. + +/** + * This is given as a pair of length values indicating x- and y- distances to use as offset. + * The default offset size is (0, -1), which indicates a shadow one point above the text. + */ +@property (assign) CGSize shadowOffset; + +/** + * The shadowBlur specifies the blur radius used to render the receiver’s shadow. + * This value coud not be rendered on iOS older than 3.2. + * The default value is 3.0. + */ +@property (copy) NSNumber* shadowBlur; + +/* + * Define the color to create the shadow effect. + * The default value for this property is transparent, + * which indicates that no shadow is drawn. + */ +@property (retain) id shadowColor; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Init Methods. ++(id)initWithShadowColor:(id)anColor andShadowOffset:(CGSize)anOffset; ++(id)initWithShadowColor:(id)anColor andShadowOffset:(CGSize)anOffset andShadowBlur:(NSNumber*)blur; + +@end diff --git a/src/extThree20CSSStyle/Headers/TTDataConverter.h b/src/extThree20CSSStyle/Headers/TTDataConverter.h new file mode 100644 index 0000000000..afbc867c9f --- /dev/null +++ b/src/extThree20CSSStyle/Headers/TTDataConverter.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2011 - SEQOY.org and Paulo Oliveira ( http://www.seqoy.org ) + * JUMP GIT Repository: https://github.com/seqoy/jump + * + * 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 + +/** + * \nosubgrouping + * This class contains an collection of methods to convert different Objective C objects. + * This is a little versio of this class with a small subset of useful methods to + * use with 'TTCSS' Classes. See JUMP Framework to retrieve the full version. + */ +@interface TTDataConverter : NSObject {} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Convert Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// +/** @name Convert Methods + */ +///@{ + +/** + * Take an NSString Object and try to convert to NSNumber. + * @param anObject An NSString to try to convert. + * @return Converted object or if an conversion isn't possible will return nil. + */ ++(NSNumber*)convertToNSNumberThisObject:(id)anObject; + +///@} +@end + diff --git a/src/extThree20CSSStyle/Headers/TTDataPopulator.h b/src/extThree20CSSStyle/Headers/TTDataPopulator.h new file mode 100644 index 0000000000..fe2f0a8ef8 --- /dev/null +++ b/src/extThree20CSSStyle/Headers/TTDataPopulator.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011 - SEQOY.org and Paulo Oliveira ( http://www.seqoy.org ) + * JUMP GIT Repository: https://github.com/seqoy/jump + * + * 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 +#import +#import "extThree20CSSStyle/TTDataConverter.h" +#import "extThree20CSSStyle/TTDataPopulatorDelegate.h" + +/** + * \nosubgrouping + * TTDataPopulator is used to populate Model Objects with Data contained in dictionaries. + * This is a little versio of this class with a small subset of useful methods to + * use with 'TTCSS' Classes. See JUMP Framework to retrieve the full version. + */ +@interface TTDataPopulator : NSObject { + id delegate; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Properties. +@property (assign) id delegate; + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Populate Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// + +//// //// //// //// //// //// //// //// //// //// //// //// //// //// //// +/** @name Populate Methods + */ +///@{ + +/** + * Populate the informed object with data. + * @param anObject The object to populate. + * @param withData An NSDictionary with data. + * @param usingMap An NSDictionary that represent an map that describe + * how to populate the object. + */ ++(id)populateObject:(id)anObject withData:(NSDictionary*)anDictionary usingMap:(NSDictionary*)anMap; + +/** + * Populate the informed object with data. + * @param anObject The object to populate. + * @param withData An NSDictionary with data. + * @param usingMap An NSDictionary that represent an map that describe + * how to populate the object. + * @param anDelegate to extend the TTDataPopulator class. See TTDataPopulatorDelegate + * documentation for more information. + */ ++(id)populateObject:(id)anObject withData:(NSDictionary*)anDictionary usingMap:(NSDictionary*)anMap + withDelegate:(id)anDelegate; + +///@} +@end + diff --git a/src/extThree20CSSStyle/Headers/TTDataPopulatorDelegate.h b/src/extThree20CSSStyle/Headers/TTDataPopulatorDelegate.h new file mode 100644 index 0000000000..8a2fc3a7b6 --- /dev/null +++ b/src/extThree20CSSStyle/Headers/TTDataPopulatorDelegate.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011 - SEQOY.org and Paulo Oliveira ( http://www.seqoy.org ) + * + * 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. + */ + +@protocol TTDataPopulatorDelegate +@optional + +/** + * When the Data Populator can't automatically convert some specific type. He will call this method + * and let you extend the class converting you specific type. + * @param firstObject is original object that we need to convert. + * @param firstObjectClass is the class of the original object. + * @param convertToClass is the class that we need to receive whe converted. + * @return Should return converted object or nil if can't convert. + */ +-(id)tryToConvert:(id)object ofClass:(Class)objectClass toClass:(Class)convertToClass; + +@end diff --git a/src/extThree20CSSStyle/Headers/TTDefaultCSSStyleSheet.h b/src/extThree20CSSStyle/Headers/TTDefaultCSSStyleSheet.h new file mode 100644 index 0000000000..ac72f698cb --- /dev/null +++ b/src/extThree20CSSStyle/Headers/TTDefaultCSSStyleSheet.h @@ -0,0 +1,68 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 "Three20Style/TTDefaultStyleSheet.h" + +@class TTCSSStyleSheet; +@class TTCSSRuleSet; +@protocol TTCSSApplyProtocol; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface TTDefaultCSSStyleSheet : TTDefaultStyleSheet { +@private + TTCSSStyleSheet* _styleSheet; + + // Maintain an control of CSS Files already loaded and cached. + NSMutableSet* _cachedCssFiles; + +} + +@property (nonatomic, readonly) TTCSSStyleSheet* styleSheet; + +/** + * Load an CSS Style Sheet from disk and cache his data. + * If the file is already cached no data will be loaded again, + * if you need to reload the file use addStyleSheetFromDisk:ignoreCache: + */ +- (BOOL)addStyleSheetFromDisk:(NSString*)filename; + +/** + * Load an CSS Style Sheet from disk and cache his data. + * @param cache YES will ignore if is already cached and reload the data if needed. + */ +- (BOOL)addStyleSheetFromDisk:(NSString*)filename ignoreCache:(BOOL)cache; + ++ (TTDefaultCSSStyleSheet*)globalCSSStyleSheet; + +/** + * CSS Rule Set. + */ +-(TTCSSRuleSet*)css:(NSString*)selectorName; + +/** + * CSS Rule Set, also accept an specific state. + */ +-(TTCSSRuleSet*)css:(NSString*)selectorName forState:(UIControlState)state; + +/** + * Apply the rules for the specified selector to the informed object. This object + * must conform with the TTCSSApplyProtocol to read and properly apply the CSS rules. + */ +-(void)applyCssFromSelector:(NSString*)selectorName toObject:(id)anObject; + +@end diff --git a/src/extThree20CSSStyle/Sources/TTDefaultCSSStyleSheet.h b/src/extThree20CSSStyle/Headers/UILabel+CSSAdditions.h similarity index 64% rename from src/extThree20CSSStyle/Sources/TTDefaultCSSStyleSheet.h rename to src/extThree20CSSStyle/Headers/UILabel+CSSAdditions.h index 7af86a52e8..c06415bd39 100644 --- a/src/extThree20CSSStyle/Sources/TTDefaultCSSStyleSheet.h +++ b/src/extThree20CSSStyle/Headers/UILabel+CSSAdditions.h @@ -13,20 +13,9 @@ // See the License for the specific language governing permissions and // limitations under the License. // +#import -#import "Three20Style/TTDefaultStyleSheet.h" - -@class TTCSSStyleSheet; - -@interface TTDefaultCSSStyleSheet : TTDefaultStyleSheet { -@private - TTCSSStyleSheet* _styleSheet; -} - -@property (nonatomic, readonly) TTCSSStyleSheet* styleSheet; - -- (BOOL)addStyleSheetFromDisk:(NSString*)filename; - -+ (TTDefaultCSSStyleSheet*)globalCSSStyleSheet; +#import "extThree20CSSStyle/UIView+CSSAdditions.h" +@interface UILabel(TTCSSAdditions) @end diff --git a/src/extThree20CSSStyle/Headers/UILabelAdditions.h b/src/extThree20CSSStyle/Headers/UILabelAdditions.h index 987f77d074..fc6956dbf0 100644 --- a/src/extThree20CSSStyle/Headers/UILabelAdditions.h +++ b/src/extThree20CSSStyle/Headers/UILabelAdditions.h @@ -14,14 +14,5 @@ // limitations under the License. // -#import -#import - -@interface UILabel (TTCSSCategory) - -/** - * Set a css stylesheet selector, will set font, colors and shadow. - */ -- (void)applyCssSelector:(NSString *)selector; - -@end +// For compatibility issues we import the UILabel additions. +#import "extThree20CSSStyle/UILabel+CSSAdditions.h" diff --git a/src/extThree20CSSStyle/Headers/UIView+CSSAdditions.h b/src/extThree20CSSStyle/Headers/UIView+CSSAdditions.h new file mode 100644 index 0000000000..15d775d62c --- /dev/null +++ b/src/extThree20CSSStyle/Headers/UIView+CSSAdditions.h @@ -0,0 +1,30 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 + +#import "extThree20CSSStyle/TTCSSRuleSet.h" +#import "extThree20CSSStyle/TTCSSApplyProtocol.h" + +@interface UIView(TTCSSAdditions) + +/** + * Convenient Init method to create an UIView and apply + * an CSS Rule Set on one pass. + */ +-(id)initWithFrame:(CGRect)anFrame andApplyCssFromSelector:(NSString*)anSelector; + + +@end diff --git a/src/extThree20CSSStyle/Headers/extThree20CSSStyle+Additions.h b/src/extThree20CSSStyle/Headers/extThree20CSSStyle+Additions.h index 46c75bfb53..87fd4b0163 100644 --- a/src/extThree20CSSStyle/Headers/extThree20CSSStyle+Additions.h +++ b/src/extThree20CSSStyle/Headers/extThree20CSSStyle+Additions.h @@ -18,6 +18,7 @@ #import "extThree20CSSStyle/extThree20CSSStyle.h" // Additions -#import "extThree20CSSStyle/UILabelAdditions.h" +#import "extThree20CSSStyle/UIView+CSSAdditions.h" +#import "extThree20CSSStyle/UILabel+CSSAdditions.h" #import "extThree20CSSStyle/TTTextStyleAdditions.h" #import "extThree20CSSStyle/TTShadowStyleAdditions.h" diff --git a/src/extThree20CSSStyle/Headers/extThree20CSSStyle.h b/src/extThree20CSSStyle/Headers/extThree20CSSStyle.h index 3cbdafb0f4..bcacb3de3b 100644 --- a/src/extThree20CSSStyle/Headers/extThree20CSSStyle.h +++ b/src/extThree20CSSStyle/Headers/extThree20CSSStyle.h @@ -21,3 +21,12 @@ #import "extThree20CSSStyle/TTCSSGlobalStyle.h" #import "extThree20CSSStyle/TTCSSStyleSheet.h" #import "extThree20CSSStyle/TTDefaultCSSStyleSheet.h" + +// CSS Models +#import "extThree20CSSStyle/TTCSSTextShadowModel.h" +#import "extThree20CSSStyle/TTCSSRuleSet.h" + +// Data Processing +#import "extThree20CSSStyle/TTDataConverter.h" +#import "extThree20CSSStyle/TTDataPopulator.h" +#import "extThree20CSSStyle/TTDataPopulatorDelegate.h" diff --git a/src/extThree20CSSStyle/README.mdown b/src/extThree20CSSStyle/README.mdown index 02c856161a..1be8d4c90e 100644 --- a/src/extThree20CSSStyle/README.mdown +++ b/src/extThree20CSSStyle/README.mdown @@ -83,15 +83,37 @@ style sheet with all of the default TTDefaultStyleSheet values. You can then com style sheet upon this one using addStyleSheetFromDisk:. For an example of this in action, see TTFacebook in the `three20/samples` directory. +### The Rule Set Object + +The Rule Set Object is an model that store data for each CSS Selector parsed. This object +contains the CSS properties as Objective-C objects ready to use on your application. +See the documentation for TTCSSRuleSet and TTCSSTextShadowModel for more information. + Known Limitations ----------------- +### Font families and font weights. +You need to always use iOS font family names and iOS font weights. For example, to use Helvetica +Bold on iOS you should create your CSS like this: + + .font { + font-family: Helvetica; + font-weight: Bold; + } + +This names are case-sensitive, you must make sure to respect the iOS font names. + ### Font Sizes Font-size is always interpreted in points, regardless of what you specify. This is due to the tricky nature of varying DPI on the various iPhone OS devices. +### Text Shadows + +In iOS older the 3.2 the "blur" property always interpreted as "0". This is due to the technical limitations +of specifying blur for text shadows for UILabels. + Supported CSS Properties and Values ----------------------------------- @@ -103,8 +125,8 @@ Supported CSS Properties and Values #FFF or #FF00FF or rgb(255, 0, 255) or rgba(0, 255, 255, 0.5) or - Any of the standard names found in the W3C for css3. - http://www.w3.org/TR/css3-color/ + Any of the Extended color keywords found in the W3C for css3. + http://www.w3.org/TR/css3-color/#svg-color Also, iPhone OS standard colors: lightTextColor darkTextColor @@ -134,13 +156,34 @@ Fonts are defined with a set of properties that collectively create the final UI ### Text Shadow - text-shadow: px px px + text-shadow-opacity: + text-shadow: px px textShadowColorWithCssSelector textShadowOffsetWithCssSelector - textShadowRadiusWithCssSelector The `text-shadow` property is defined in one chunk, but read using two distinct methods. +The third parameter could be ignored on older iOS versions, see "Text Shadows" in the +`Known Limitations` section for the technical reasons. + + +### Alignment and Justification + + text-align: (left|center|right) + +This property describes how inline contents of a block are horizontally aligned. + +### Positioning and Size + + top: px + left: px + width: px + height: px + +### Visibilty + + visibilty: (visible|hidden) + Examples -------- @@ -166,7 +209,25 @@ Add the following code in your app delegate's `applicationDidFinishLaunching`. TT_RELEASE_SAFELY(styleSheet); -Now you can freely customize the styles of your app using `stylesheet.css`. You can freely -add new styles to the CSS, but with the current design you will also need to add an accessor -to a custom object that inherits from `TTDefaultCSSStyleSheet`. See the source for -`TTDefaultCSSStyleSheet` for examples of how to interact with the style sheet object. +Now you can freely customize the styles of your app using `stylesheet.css`. You can access +the CSS rules and his properties using two convenient functions: + +### TTCSS function + +Allows you to retrieve the selector and some specific property. + + // Read the color from the CSS 'headerFont'. + UIColor *headerFontColor = TTCSS( @"headerFont", color ); + +### TTCSSRule function + +Retrieve an TTCSSRuleSet object for specified property. So you can access every property directly. + + // Read the color rule set 'headerFont'. + TTCSSRuleSet *headerFont = TTCSSRuleSet( @"headerFont" ); + + UIColor *headerFontColor = headerFont.color; + + +You also could add an accessor to a custom object that inherits from `TTDefaultCSSStyleSheet`. See the source for +`TTDefaultCSSStyleSheet` for an example. diff --git a/src/extThree20CSSStyle/Sources/TTCSSFunctions.m b/src/extThree20CSSStyle/Sources/TTCSSFunctions.m new file mode 100644 index 0000000000..7eab3fc49d --- /dev/null +++ b/src/extThree20CSSStyle/Sources/TTCSSFunctions.m @@ -0,0 +1,268 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 "extThree20CSSStyle/TTCSSFunctions.h" +#import "extThree20CSSStyle/TTDataConverter.h" +#import "Three20Style/TTGlobalStyle.h" + +// Core +#import "Three20Core/TTCorePreprocessorMacros.h" +#import "Three20Core/TTDebug.h" +#import "Three20Core/TTGlobalCorePaths.h" + + +// CSS3 Color Lookuptable (4.3. Extended color keywords): http://www.w3.org/TR/css3-color/#svg-color +#define __colorLookupTable [NSDictionary dictionaryWithObjectsAndKeys:\ + RGBCOLOR(0xFF, 0x00, 0xFF), @"fuschia",\ + RGBCOLOR(240,248,255), @"aliceblue",\ + RGBCOLOR(250,235,215), @"antiquewhite",\ + RGBCOLOR(0,255,255), @"aqua",\ + RGBCOLOR(127,255,212), @"aquamarine",\ + RGBCOLOR(240,255,255), @"azure",\ + RGBCOLOR(245,245,220), @"beige",\ + RGBCOLOR(255,228,196), @"bisque",\ + RGBCOLOR(0,0,0), @"black",\ + RGBCOLOR(255,235,205), @"blanchedalmond",\ + RGBCOLOR(0,0,255), @"blue",\ + RGBCOLOR(138,43,226), @"blueviolet",\ + RGBCOLOR(165,42,42), @"brown",\ + RGBCOLOR(222,184,135), @"burlywood",\ + RGBCOLOR(95,158,160), @"cadetblue",\ + RGBCOLOR(127,255,0), @"chartreuse",\ + RGBCOLOR(210,105,30), @"chocolate",\ + RGBCOLOR(255,127,80), @"coral",\ + RGBCOLOR(100,149,237), @"cornflowerblue",\ + RGBCOLOR(255,248,220), @"cornsilk",\ + RGBCOLOR(220,20,60), @"crimson",\ + RGBCOLOR(0,255,255), @"cyan",\ + RGBCOLOR(0,0,139), @"darkblue",\ + RGBCOLOR(0,139,139), @"darkcyan",\ + RGBCOLOR(184,134,11), @"darkgoldenrod",\ + RGBCOLOR(169,169,169), @"darkgray",\ + RGBCOLOR(0,100,0), @"darkgreen",\ + RGBCOLOR(169,169,169), @"darkgrey",\ + RGBCOLOR(189,183,107), @"darkkhaki",\ + RGBCOLOR(139,0,139), @"darkmagenta",\ + RGBCOLOR(85,107,47), @"darkolivegreen",\ + RGBCOLOR(255,140,0), @"darkorange",\ + RGBCOLOR(153,50,204), @"darkorchid",\ + RGBCOLOR(139,0,0), @"darkred",\ + RGBCOLOR(233,150,122), @"darksalmon",\ + RGBCOLOR(143,188,143), @"darkseagreen",\ + RGBCOLOR(72,61,139), @"darkslateblue",\ + RGBCOLOR(47,79,79), @"darkslategray",\ + RGBCOLOR(47,79,79), @"darkslategrey",\ + RGBCOLOR(0,206,209), @"darkturquoise",\ + RGBCOLOR(148,0,211), @"darkviolet",\ + RGBCOLOR(255,20,147), @"deeppink",\ + RGBCOLOR(0,191,255), @"deepskyblue",\ + RGBCOLOR(105,105,105), @"dimgray",\ + RGBCOLOR(105,105,105), @"dimgrey",\ + RGBCOLOR(30,144,255), @"dodgerblue",\ + RGBCOLOR(178,34,34), @"firebrick",\ + RGBCOLOR(255,250,240), @"floralwhite",\ + RGBCOLOR(34,139,34), @"forestgreen",\ + RGBCOLOR(255,0,255), @"fuchsia",\ + RGBCOLOR(220,220,220), @"gainsboro",\ + RGBCOLOR(248,248,255), @"ghostwhite",\ + RGBCOLOR(255,215,0), @"gold",\ + RGBCOLOR(218,165,32), @"goldenrod",\ + RGBCOLOR(128,128,128), @"gray",\ + RGBCOLOR(0,128,0), @"green",\ + RGBCOLOR(173,255,47), @"greenyellow",\ + RGBCOLOR(128,128,128), @"grey",\ + RGBCOLOR(240,255,240), @"honeydew",\ + RGBCOLOR(255,105,180), @"hotpink",\ + RGBCOLOR(205,92,92), @"indianred",\ + RGBCOLOR(75,0,130), @"indigo",\ + RGBCOLOR(255,255,240), @"ivory",\ + RGBCOLOR(240,230,140), @"khaki",\ + RGBCOLOR(230,230,250), @"lavender",\ + RGBCOLOR(255,240,245), @"lavenderblush",\ + RGBCOLOR(124,252,0), @"lawngreen",\ + RGBCOLOR(255,250,205), @"lemonchiffon",\ + RGBCOLOR(173,216,230), @"lightblue",\ + RGBCOLOR(240,128,128), @"lightcoral",\ + RGBCOLOR(224,255,255), @"lightcyan",\ + RGBCOLOR(250,250,210), @"lightgoldenrodyellow",\ + RGBCOLOR(211,211,211), @"lightgray",\ + RGBCOLOR(144,238,144), @"lightgreen",\ + RGBCOLOR(211,211,211), @"lightgrey",\ + RGBCOLOR(255,182,193), @"lightpink",\ + RGBCOLOR(255,160,122), @"lightsalmon",\ + RGBCOLOR(32,178,170), @"lightseagreen",\ + RGBCOLOR(135,206,250), @"lightskyblue",\ + RGBCOLOR(119,136,153), @"lightslategray",\ + RGBCOLOR(119,136,153), @"lightslategrey",\ + RGBCOLOR(176,196,222), @"lightsteelblue",\ + RGBCOLOR(255,255,224), @"lightyellow",\ + RGBCOLOR(0,255,0), @"lime",\ + RGBCOLOR(50,205,50), @"limegreen",\ + RGBCOLOR(250,240,230), @"linen",\ + RGBCOLOR(255,0,255), @"magenta",\ + RGBCOLOR(128,0,0), @"maroon",\ + RGBCOLOR(102,205,170), @"mediumaquamarine",\ + RGBCOLOR(0,0,205), @"mediumblue",\ + RGBCOLOR(186,85,211), @"mediumorchid",\ + RGBCOLOR(147,112,219), @"mediumpurple",\ + RGBCOLOR(60,179,113), @"mediumseagreen",\ + RGBCOLOR(123,104,238), @"mediumslateblue",\ + RGBCOLOR(0,250,154), @"mediumspringgreen",\ + RGBCOLOR(72,209,204), @"mediumturquoise",\ + RGBCOLOR(199,21,133), @"mediumvioletred",\ + RGBCOLOR(25,25,112), @"midnightblue",\ + RGBCOLOR(245,255,250), @"mintcream",\ + RGBCOLOR(255,228,225), @"mistyrose",\ + RGBCOLOR(255,228,181), @"moccasin",\ + RGBCOLOR(255,222,173), @"navajowhite",\ + RGBCOLOR(0,0,128), @"navy",\ + RGBCOLOR(253,245,230), @"oldlace",\ + RGBCOLOR(128,128,0), @"olive",\ + RGBCOLOR(107,142,35), @"olivedrab",\ + RGBCOLOR(255,165,0), @"orange",\ + RGBCOLOR(255,69,0), @"orangered",\ + RGBCOLOR(218,112,214), @"orchid",\ + RGBCOLOR(238,232,170), @"palegoldenrod",\ + RGBCOLOR(152,251,152), @"palegreen",\ + RGBCOLOR(175,238,238), @"paleturquoise",\ + RGBCOLOR(219,112,147), @"palevioletred",\ + RGBCOLOR(255,239,213), @"papayawhip",\ + RGBCOLOR(255,218,185), @"peachpuff",\ + RGBCOLOR(205,133,63), @"peru",\ + RGBCOLOR(255,192,203), @"pink",\ + RGBCOLOR(221,160,221), @"plum",\ + RGBCOLOR(176,224,230), @"powderblue",\ + RGBCOLOR(128,0,128), @"purple",\ + RGBCOLOR(255,0,0), @"red",\ + RGBCOLOR(188,143,143), @"rosybrown",\ + RGBCOLOR(65,105,225), @"royalblue",\ + RGBCOLOR(139,69,19), @"saddlebrown",\ + RGBCOLOR(250,128,114), @"salmon",\ + RGBCOLOR(244,164,96), @"sandybrown",\ + RGBCOLOR(46,139,87), @"seagreen",\ + RGBCOLOR(255,245,238), @"seashell",\ + RGBCOLOR(160,82,45), @"sienna",\ + RGBCOLOR(192,192,192), @"silver",\ + RGBCOLOR(135,206,235), @"skyblue",\ + RGBCOLOR(106,90,205), @"slateblue",\ + RGBCOLOR(112,128,144), @"slategray",\ + RGBCOLOR(112,128,144), @"slategrey",\ + RGBCOLOR(255,250,250), @"snow",\ + RGBCOLOR(0,255,127), @"springgreen",\ + RGBCOLOR(70,130,180), @"steelblue",\ + RGBCOLOR(210,180,140), @"tan",\ + RGBCOLOR(0,128,128), @"teal",\ + RGBCOLOR(216,191,216), @"thistle",\ + RGBCOLOR(255,99,71), @"tomato",\ + RGBCOLOR(64,224,208), @"turquoise",\ + RGBCOLOR(238,130,238), @"violet",\ + RGBCOLOR(245,222,179), @"wheat",\ + RGBCOLOR(245,245,245), @"whitesmoke",\ + RGBCOLOR(255,255,0), @"yellow",\ + RGBCOLOR(154,205,50), @"yellowgreen",\ + RGBACOLOR(0xFF, 0xFF, 0xFF, 0x00), @"transparent",\ + [UIColor whiteColor], @"white",\ + [UIColor lightTextColor], @"lightTextColor",\ + [UIColor darkTextColor], @"darkTextColor",\ + [UIColor groupTableViewBackgroundColor], @"groupTableViewBackgroundColor",\ + [UIColor viewFlipsideBackgroundColor], @"viewFlipsideBackgroundColor",\ + nil] + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Colors +/////////////////////////////////////////////////////////////////////////////////////////////////// +UIColor* TTColorFromCssValues( NSArray* cssValues ) { + UIColor* anColor = nil; + + // Validate CSS Color. Anything more or less is unsupported, and therefore this + // property is ignored according to the W3C guidelines. + BOOL validCss = [cssValues count] == 1 + || [cssValues count] == 5 // rgb( x x x ) + || [cssValues count] == 6; // rgba( x x x x ) + if ( !validCss ) + [NSException raise:@"TTCSSColorFormatter" format:@"Invalid CSS color values: '%@'", cssValues]; + + if ([cssValues count] == 1) { + NSString* cssString = [cssValues objectAtIndex:0]; + + if ([cssString characterAtIndex:0] == '#') { + unsigned long colorValue = 0; + + // #FFF + if ([cssString length] == 4) { + colorValue = strtol([cssString UTF8String] + 1, nil, 16); + colorValue = ((colorValue & 0xF00) << 12) | ((colorValue & 0xF00) << 8) + | ((colorValue & 0xF0) << 8) | ((colorValue & 0xF0) << 4) + | ((colorValue & 0xF) << 4) | (colorValue & 0xF); + + // #FFFFFF + } else if ([cssString length] == 7) { + colorValue = strtol([cssString UTF8String] + 1, nil, 16); + } + + anColor = RGBCOLOR(((colorValue & 0xFF0000) >> 16), + ((colorValue & 0xFF00) >> 8), + (colorValue & 0xFF)); + + } else if ([cssString isEqualToString:@"none"]) { + anColor = nil; + + } else { + UIColor *color = [__colorLookupTable objectForKey:cssString]; + // If not found, raise error. + if ( !color ) + [NSException raise:@"TTCSSColorFormatter" + format:@"'%@' isn't a valid W3C CSS Extended color keywords.", cssString]; + // Return correct. + return color; + } + + } else if ([cssValues count] == 5 && [[cssValues objectAtIndex:0] isEqualToString:@"rgb("]) { + // rgb( x x x ) + anColor = RGBCOLOR([[cssValues objectAtIndex:1] floatValue], + [[cssValues objectAtIndex:2] floatValue], + [[cssValues objectAtIndex:3] floatValue]); + + } else if ([cssValues count] == 6 && [[cssValues objectAtIndex:0] isEqualToString:@"rgba("]) { + // rgba( x x x x ) + anColor = RGBACOLOR([[cssValues objectAtIndex:1] floatValue], + [[cssValues objectAtIndex:2] floatValue], + [[cssValues objectAtIndex:3] floatValue], + [[cssValues objectAtIndex:4] floatValue]); + } + + return anColor; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Sizes. +/////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Helper function to convert an CSS readed size to CGFloat. + */ +CGFloat TTValueFromCssValues( NSString* value ) { + // Pixel measure. + if ( ! NSEqualRanges( [value rangeOfString:@"px"], (NSRange){NSNotFound,0} )) { + value = [value stringByReplacingOccurrencesOfString:@"px" withString:@""]; + return [[TTDataConverter convertToNSNumberThisObject:value] floatValue]; + } + return 0; +} + diff --git a/src/extThree20CSSStyle/Sources/TTCSSParser.m b/src/extThree20CSSStyle/Sources/TTCSSParser.m index 66f3eb2b94..0e128f0761 100644 --- a/src/extThree20CSSStyle/Sources/TTCSSParser.m +++ b/src/extThree20CSSStyle/Sources/TTCSSParser.m @@ -88,8 +88,8 @@ - (void)dealloc { /////////////////////////////////////////////////////////////////////////////////////////////////// - (void)consumeToken:(int)token text:(char*)text { - NSString* string = [[NSString stringWithCString: text - encoding: NSUTF8StringEncoding] lowercaseString]; + NSString* string = [NSString stringWithCString: text + encoding: NSUTF8StringEncoding]; switch (token) { case CSSHASH: case CSSIDENT: { diff --git a/src/extThree20CSSStyle/Sources/TTCSSRuleSet.m b/src/extThree20CSSStyle/Sources/TTCSSRuleSet.m new file mode 100644 index 0000000000..60f0692112 --- /dev/null +++ b/src/extThree20CSSStyle/Sources/TTCSSRuleSet.m @@ -0,0 +1,341 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 "extThree20CSSStyle/TTCSSRuleSet.h" +#import "extThree20CSSStyle/TTCSSFunctions.h" + +// Style +#import "Three20Style/TTGlobalStyle.h" +#import "Three20Style/TTStyle.h" + +// Core +#import "Three20Core/TTCorePreprocessorMacros.h" +#import "Three20Core/TTGlobalCore.h" +#import "Three20Core/TTDebug.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +@implementation TTCSSRuleSet +@synthesize selector, font_size, font_family, font_weight; +@synthesize color, background_color, background_image; +@synthesize text_shadow, text_shadow_opacity, text_align; +@synthesize width, height, visibility; +@synthesize top, left, right, bottom; +@synthesize vertical_align, margin_right, margin_left; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Init Methods. + +/////////////////////////////////////////////////////////////////////////////////////////////////// ++(id)initWithSelectorName:(NSString*)anRuleSetName { + TTCSSRuleSet *instance = [[TTCSSRuleSet new] autorelease]; + instance.selector = anRuleSetName; + return instance; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(id)init { + self = [super init]; + if (self != nil) { + + // Default values. + self.background_color = [UIColor clearColor]; + self.color = [UIColor clearColor]; + + // Font size is the Default Sytem Font Size. + self.font_size = [NSNumber numberWithFloat:[UIFont systemFontSize]]; + + // Default Font Family. + self.font_family = [[UIFont systemFontOfSize:[UIFont systemFontSize]] familyName]; + + // Default alignment is left. + self.text_align = @"left"; + + // Default visiblity is visible. + self.visibility = @"visible"; + + // Default vertical aligment is top. + self.vertical_align = @"top"; + } + return self; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)dealloc { + TT_RELEASE_SAFELY( font_family ); + TT_RELEASE_SAFELY( selector ); + TT_RELEASE_SAFELY( font_size ); + TT_RELEASE_SAFELY( font_weight ); + TT_RELEASE_SAFELY( text_shadow ); + TT_RELEASE_SAFELY( color ); + TT_RELEASE_SAFELY( width ); + TT_RELEASE_SAFELY( height ); + TT_RELEASE_SAFELY( top ); + TT_RELEASE_SAFELY( left ); + TT_RELEASE_SAFELY( right ); + TT_RELEASE_SAFELY( bottom ); + TT_RELEASE_SAFELY( background_color ); + TT_RELEASE_SAFELY( background_image ); + TT_RELEASE_SAFELY( text_shadow_opacity ); + TT_RELEASE_SAFELY( visibility ); + TT_RELEASE_SAFELY( vertical_align ); + TT_RELEASE_SAFELY( margin_right ); + TT_RELEASE_SAFELY( margin_left ); + [super dealloc]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Private Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(NSError*)formatError:(NSString*)description { + return [NSError errorWithDomain:NSStringFromClass([self class]) code:1 + userInfo:[NSDictionary dictionaryWithObject:description + forKey:NSLocalizedDescriptionKey]]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Validate Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(BOOL)validateVertical_align:(id *)ioValue error:(NSError **)outError { + // Validate correct values. + if ( ![[NSArray arrayWithObjects:@"top", @"middle", @"bottom", nil] + containsObject:(NSString*)*ioValue] ) { + *outError = [self formatError:@"'vertical_align' must be 'top', 'middle' or 'bottom'!"]; + return NO; + } + return YES; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(BOOL)validateText_align:(id *)ioValue error:(NSError **)outError { + // Validate correct values. + if ( ![[NSArray arrayWithObjects:@"left", @"center", @"right", nil] + containsObject:(NSString*)*ioValue] ) { + *outError = [self formatError:@"'text_align' must be 'left', 'center' or 'right'!"]; + return NO; + } + return YES; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(BOOL)validateVisibility:(id *)ioValue error:(NSError **)outError { + // Validate correct values. + if ( ![[NSArray arrayWithObjects:@"visible", @"hidden", nil] + containsObject:(NSString*)*ioValue] ) { + *outError = [self formatError:@"'visibility' must be 'visible' or 'hidden'!"]; + return NO; + } + return YES; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(BOOL)validateFont_family:(id *)ioValue error:(NSError **)outError { + // Validate correct system fonts. + if ( ![[UIFont familyNames] containsObject:(NSString*)*ioValue] ) { + NSString *error = [NSString stringWithFormat:@"iOS don't support the '%@' font family.", + (NSString*)*ioValue]; + *outError = [self formatError:error]; + + return NO; + } + return YES; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Validate colors. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(BOOL)validateValue:(id *)ioValue forKey:(NSString *)inKey error:(NSError **)outError { + // Colors validation. + if ( [inKey isEqualToString:@"color"] || [inKey isEqualToString:@"background_color"] ) { + + // nil is Ok. + if ( ioValue == nil ) + return YES; + + /////////////////////////////////// + // Validate correct types. + if ( ( [*ioValue isKindOfClass:[NSArray class]] || + [*ioValue isKindOfClass:[NSString class]] || + [*ioValue isKindOfClass:[UIColor class]] )) { + return YES; + } + + /////////////////////////////////// + // Else Error. + NSString *e; + e = [NSString stringWithFormat:@"'%@' must be of class 'NSArray', 'NSString' or 'UIColor'", + inKey ]; + *outError = [self formatError:e]; + return NO; + } + + // Other validations. + return [super validateValue:ioValue forKey:inKey error:outError]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Set Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)setUIColorProperty:(UIColor**)anColor withValue:(id)anValue { + + ///////////////////////////////// + // Release. + if ( *anColor ) + TT_RELEASE_SAFELY( *anColor ); + + /////////////////////////////////////// + // Array of color? + if ( [anValue isKindOfClass:[NSArray class]] ) { + + // Set. + *anColor = [TTColorFromCssValues(anValue) retain]; + + } + + /////////////////////////////////////// + // String color? + else if ( [anValue isKindOfClass:[NSString class]] ) { + + // Set. + *anColor = [TTColorFromCssValues([NSArray arrayWithObject:anValue]) retain]; + } + + /////////////////////////////////////// + // UIColor? + else if ( [anValue isKindOfClass:[UIColor class]] ) { + + // Set. + *anColor = [anValue retain]; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)setColor:(id)anColor { + [self setUIColorProperty:&color withValue:anColor]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)setBackground_color:(id)anColor { + [self setUIColorProperty:&background_color withValue:anColor]; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Data Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Return an formatted UIFont object based on the defined properties. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(UIFont*)font { + // If not enough properties return nil. + if ( !font_family && !font_size ) { + TTDWARNING ( @"Can't format UIFont, 'font_family' or 'font_size' isn't defined." ); + return nil; + } + + ////////////////////////////////// + // Font weight. + NSString *fullFontWeight = ( font_weight == nil + ? @"" + : [NSString stringWithFormat:@"-%@", [font_weight capitalizedString]] ); + + ////////////////////////////////// + // Font Name. + NSString *fullFontName = [NSString stringWithFormat:@"%@%@", [font_family capitalizedString], + fullFontWeight]; + + ////////////////////////////////// + // Create and return UIFont. + return [UIFont fontWithName:fullFontName size:[font_size floatValue]]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Return an formatted UITextAlignment based on the defined 'text_align' property. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(UITextAlignment)textAlign { + if ([text_align isEqualToString:@"left"]) { + return UITextAlignmentLeft; + } + else if ([text_align isEqualToString:@"center"]) { + return UITextAlignmentCenter; + } + else if ([text_align isEqualToString:@"right"]) { + return UITextAlignmentRight; + } + return UITextAlignmentLeft; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Return an formatted CGSize based on the defined width and height properties. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(CGSize)size { + return CGSizeMake(TTValueFromCssValues(self.width), TTValueFromCssValues(self.height)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Return an formatted CGPoint based on the defined top and left properties. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(CGPoint)origin { + return CGPointMake(TTValueFromCssValues(self.left), TTValueFromCssValues(self.top)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Return an Boolean value that determines whether the receiver is hidden +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(BOOL)hidden { + return [self.visibility isEqualToString:@"hidden"]; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Return an formatted UIControlContentVerticalAlignment based on the defined +// 'vertical_align' property. If isn't setted return default top alignment. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(UIControlContentVerticalAlignment)contentVerticalAlignment { + if ([vertical_align isEqualToString:@"top"]) { + return UIControlContentVerticalAlignmentTop; + } + else if ([vertical_align isEqualToString:@"middle"]) { + return UIControlContentVerticalAlignmentCenter; + } + else if ([vertical_align isEqualToString:@"bottom"]) { + return UIControlContentVerticalAlignmentBottom; + } + return UIControlContentVerticalAlignmentTop; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Return an formatted UIControlContentHorizontalAlignment based on the defined +// 'margin-left' and margin-right properties. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(UIControlContentHorizontalAlignment)contentHorizontalAlignment { + if ([margin_right isEqualToString:@"auto"] && ![margin_left isEqualToString:@"auto"]) { + return UIControlContentHorizontalAlignmentLeft; + } + else if ([margin_right isEqualToString:@"auto"] && [margin_left isEqualToString:@"auto"]) { + return UIControlContentHorizontalAlignmentCenter; + } + else if (![margin_right isEqualToString:@"auto"] && [margin_left isEqualToString:@"auto"]) { + return UIControlContentHorizontalAlignmentRight; + } + return UIControlContentHorizontalAlignmentLeft; +} +@end diff --git a/src/extThree20CSSStyle/Sources/TTCSSStyleSheet.m b/src/extThree20CSSStyle/Sources/TTCSSStyleSheet.m index 4da4b9b663..a3a2fde629 100644 --- a/src/extThree20CSSStyle/Sources/TTCSSStyleSheet.m +++ b/src/extThree20CSSStyle/Sources/TTCSSStyleSheet.m @@ -15,9 +15,13 @@ // #import "extThree20CSSStyle/TTCSSStyleSheet.h" +#import "extThree20CSSStyle/TTCSSRuleSet.h" +#import "extThree20CSSStyle/TTDataPopulator.h" +#import "extThree20CSSStyle/TTDataConverter.h" #import "extThree20CSSStyle/TTCSSParser.h" + // Style #import "Three20Style/TTGlobalStyle.h" #import "Three20Style/TTStyle.h" @@ -48,6 +52,7 @@ @implementation TTCSSStyleSheet @synthesize cssStyles = _cssStyles; +@synthesize cssRulesSet = _cssRulesSet; /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -72,9 +77,9 @@ - (void)dealloc { name: UIApplicationDidReceiveMemoryWarningNotification object: nil]; + TT_RELEASE_SAFELY(_cssRulesSet); TT_RELEASE_SAFELY(_cssStyles); - TT_RELEASE_SAFELY(_cachedCssStyles); - TT_RELEASE_SAFELY(_colorLookupTable); + TT_RELEASE_SAFELY(_propertiesMap); [super dealloc]; } @@ -100,7 +105,7 @@ - (void)didReceiveMemoryWarning:(void*)object { /////////////////////////////////////////////////////////////////////////////////////////////////// - (BOOL)loadFromFilename:(NSString*)filename { TT_RELEASE_SAFELY(_cssStyles); - TT_RELEASE_SAFELY(_cachedCssStyles); + TT_RELEASE_SAFELY(_cssRulesSet); BOOL didLoadSuccessfully = NO; @@ -110,8 +115,8 @@ - (BOOL)loadFromFilename:(NSString*)filename { NSDictionary* results = [parser parseFilename:filename]; TT_RELEASE_SAFELY(parser); - _cssStyles = [results retain]; - _cachedCssStyles = [[NSMutableDictionary alloc] initWithCapacity:[_cssStyles count]]; + _cssStyles = [results retain]; + _cssRulesSet = [[NSMutableDictionary alloc] initWithCapacity:[_cssStyles count]]; didLoadSuccessfully = YES; } @@ -128,10 +133,14 @@ - (void)addStyleSheet:(TTCSSStyleSheet*)styleSheet { } // Clear the cache first. - TT_RELEASE_SAFELY(_cachedCssStyles); - _cachedCssStyles = [[NSMutableDictionary alloc] initWithCapacity:[_cssStyles count]]; + TT_RELEASE_SAFELY(_cssRulesSet); + _cssRulesSet = [[NSMutableDictionary alloc] initWithCapacity:[_cssStyles count]]; + + // Should init the styles? + if ( !_cssStyles ) + _cssStyles = [NSDictionary new]; - NSMutableDictionary* newStyles = [_cssStyles mutableCopy]; + NSMutableDictionary* newStyles = [_cssStyles mutableCopy]; for (NSString* selector in styleSheet.cssStyles) { NSDictionary* addingRuleSet = [styleSheet.cssStyles objectForKey:selector]; @@ -160,352 +169,296 @@ - (void)addStyleSheet:(TTCSSStyleSheet*)styleSheet { /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark Object Cache - +#pragma mark Populate Methods. + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(NSDictionary*)propertiesMap { + if ( !_propertiesMap ) { + _propertiesMap = [[NSDictionary dictionaryWithObjectsAndKeys: + @"color", @"color", + @"font_family", @"font", + @"font_family", @"font-family", + @"font_weight", @"font-weight", + @"font_size", @"font-size", + @"background_color", @"background-color", + @"background_image", @"background-image", + @"text_shadow", @"text-shadow", + @"text_align", @"text-align", + @"width", @"width", + @"visibility", @"visibility", + @"height", @"height", + @"top", @"top", + @"left", @"left", + @"right", @"right", + @"bottom", @"bottom", + @"text_shadow_opacity", @"text-shadow-opacity", + @"margin_left", @"margin-left", + @"margin_right", @"margin-right", + @"vertical_align", @"vertical-align", + + nil] retain]; + } + return _propertiesMap; +} /////////////////////////////////////////////////////////////////////////////////////////////////// -- (id)objectForCssSelector:(NSString*)selector propertyName:(NSString*)propertyName { - NSDictionary* ruleSet = [_cachedCssStyles objectForKey:selector]; - if (nil != ruleSet) { - return [ruleSet objectForKey:propertyName]; - } - - return nil; -} +// When the Data Populator can't automatically convert some specific type. He will call +// this method and let you extend the class converting you specific type. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(id)tryToConvert:(id)object ofClass:(Class)objectClass toClass:(Class)convertToClass { + + ///////// /////// /////// /////// /////// /////// /////// /////// /////// /////// + // Text Shadow Model. + if ( convertToClass == [TTCSSTextShadowModel class] ) { + + // Anything more or less is unsupported, and therefore this property is ignored + // according to the W3C guidelines. + NSArray* values = object; + TTDASSERT([values count] >= 4); + if ([values count] >= 4) { + TTCSSTextShadowModel *shadowModel; + // Create an Shadow Model from data and return. + shadowModel = [TTCSSTextShadowModel initWithShadowColor:[values subarrayWithRange: + NSMakeRange(3,[values count] - 3)] + andShadowOffset:CGSizeMake([[values objectAtIndex:0] floatValue], + [[values objectAtIndex:1] floatValue]) + andShadowBlur:[values objectAtIndex:3]]; + // Return. + return shadowModel; + } + } + + ///////// /////// /////// /////// /////// /////// /////// /////// /////// /////// + // Strings. + if ( convertToClass == [NSString class] ) { + if ( [object isKindOfClass:[NSArray class]] ) { + NSMutableString *merged = [NSMutableString string]; + for ( NSString* part in object ) { + [merged appendString:part]; + } + // Return merged. + return merged; + } + else if ( [object isKindOfClass:[NSString class]] ) { + return object; + } + else { + return nil; + } + } + ///////// /////// /////// /////// /////// /////// /////// /////// /////// /////// + // Some crude data is returned as an NSArray... + if ( [object isKindOfClass:[NSArray class]] ) { -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)setObjectForCssSelector: (NSString*)selector - propertyName: (NSString*)propertyName - object: (id)object { - TTDASSERT(TTIsStringWithAnyText(selector)); - NSMutableDictionary* ruleSet = [_cachedCssStyles objectForKey:selector]; - if (nil == ruleSet) { - ruleSet = [[NSMutableDictionary alloc] init]; - [_cachedCssStyles setObject:ruleSet forKey:selector]; + // If have more than one element, return the full array. + if ( [object count] > 1 ) + return object; - // Can release here because it's now being retained by _processedCssStyles - [ruleSet release]; - } + // If not, we just need the first element. + id element = [object objectAtIndex:0]; - [ruleSet setObject:object forKey:propertyName]; -} + // Only one parameter is NSNumber, is the size of the font. Sometimes + // this value come with a 'pt' on it. + // We don't need it right? So we clean the string and convert to NSNumber. + if ( convertToClass == [NSNumber class] ) { + // Clean it. + element = [(NSString*)element stringByReplacingOccurrencesOfString:@"pt" + withString:@""]; + // Convert to number. + return [TTDataConverter convertToNSNumberThisObject:element]; + } -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (NSString*)selector:(NSString*)selector forState:(UIControlState)state { - selector = [selector lowercaseString]; - switch (state) { - default: - case UIControlStateNormal: - break; - - case UIControlStateHighlighted: { - selector = [selector stringByAppendingString:@":hover"]; - break; - } - } + // Return the element. + return element; + } - return selector; + // If can't convert. Return nil. + return nil; } - +/////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - -#pragma mark Colors - - /////////////////////////////////////////////////////////////////////////////////////////////////// -- (NSDictionary*)colorLookupTable { - if (nil == _colorLookupTable) { - // From the W3C HTML4 spec for colors: - // http://www.w3.org/TR/css3-color/ - _colorLookupTable = [[NSDictionary alloc] initWithObjectsAndKeys: - RGBCOLOR(0x00, 0xFF, 0xFF), @"aqua", - [UIColor blackColor], @"black", - RGBCOLOR(0x00, 0x00, 0xFF), @"blue", - RGBCOLOR(0xFF, 0x00, 0xFF), @"fuschia", - RGBCOLOR(0x80, 0x80, 0x80), @"gray", - RGBCOLOR(0x00, 0x80, 0x00), @"green", - RGBCOLOR(0x00, 0xFF, 0x00), @"lime", - RGBCOLOR(0x80, 0x00, 0x00), @"maroon", - RGBCOLOR(0x00, 0x00, 0x80), @"navy", - RGBCOLOR(0x80, 0x80, 0x00), @"olive", - RGBCOLOR(0xFF, 0x00, 0x00), @"red", - RGBCOLOR(0x80, 0x00, 0x80), @"purple", - RGBCOLOR(0xC0, 0xC0, 0xC0), @"silver", - RGBCOLOR(0x00, 0x80, 0x80), @"teal", - RGBACOLOR(0xFF, 0xFF, 0xFF, 0x00), @"transparent", - [UIColor whiteColor], @"white", - RGBCOLOR(0xFF, 0xFF, 0x00), @"yellow", - - // System colors - [UIColor lightTextColor], @"lightTextColor", - [UIColor darkTextColor], @"darkTextColor", - [UIColor groupTableViewBackgroundColor], @"groupTableViewBackgroundColor", - [UIColor viewFlipsideBackgroundColor], @"viewFlipsideBackgroundColor", - nil]; - } - - return _colorLookupTable; +- (NSString*)selector:(NSString*)selector forState:(UIControlState)state { + switch (state) { + default: + case UIControlStateNormal: + break; + + case UIControlStateHighlighted: { + selector = [selector stringByAppendingString:@":hover"]; + break; + } + } + + return selector; } - /////////////////////////////////////////////////////////////////////////////////////////////////// -- (UIColor*)colorFromCssValues:(NSArray*)cssValues { - UIColor* color = nil; - - // Anything more or less is unsupported, and therefore this property is ignored - // according to the W3C guidelines. - TTDASSERT([cssValues count] == 1 - || [cssValues count] == 5 // rgb( x x x ) - || [cssValues count] == 6); // rgba( x x x x ) - - if ([cssValues count] == 1) { - NSString* cssString = [cssValues objectAtIndex:0]; +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Object Cache - if ([cssString characterAtIndex:0] == '#') { - unsigned long colorValue = 0; +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(TTCSSRuleSet*)css:(NSString*)selector { + TTCSSRuleSet *ruleSet = [_cssRulesSet objectForKey:selector]; - // #FFF - if ([cssString length] == 4) { - colorValue = strtol([cssString UTF8String] + 1, nil, 16); - colorValue = ((colorValue & 0xF00) << 12) | ((colorValue & 0xF00) << 8) - | ((colorValue & 0xF0) << 8) | ((colorValue & 0xF0) << 4) - | ((colorValue & 0xF) << 4) | (colorValue & 0xF); + //////////////////////////////////////////////////// + // Can't find? Try to create it. + if ( ruleSet == nil ) { - // #FFFFFF - } else if ([cssString length] == 7) { - colorValue = strtol([cssString UTF8String] + 1, nil, 16); - } + //////////////////////////////////////////////////// + // Retrieve from "crude" repository? + NSDictionary *crudeData = [_cssStyles objectForKey:selector]; - color = RGBCOLOR(((colorValue & 0xFF0000) >> 16), - ((colorValue & 0xFF00) >> 8), - (colorValue & 0xFF)); + // Don't exist? Warn and return nil. + if ( !crudeData ) { + TTDWARNING( @"The CSS selector '%@' don't exist.", selector ); + return nil; + } - } else if ([cssString isEqualToString:@"none"]) { - color = nil; + // Create it. + ruleSet = [TTCSSRuleSet initWithSelectorName:selector]; - } else { - color = [[self colorLookupTable] objectForKey:cssString]; - } + // Populate + ruleSet = [TTDataPopulator populateObject:ruleSet + withData:crudeData + usingMap:[self propertiesMap] + withDelegate:self]; - } else if ([cssValues count] == 5 && [[cssValues objectAtIndex:0] isEqualToString:@"rgb("]) { - // rgb( x x x ) - color = RGBCOLOR([[cssValues objectAtIndex:1] floatValue], - [[cssValues objectAtIndex:2] floatValue], - [[cssValues objectAtIndex:3] floatValue]); - - } else if ([cssValues count] == 6 && [[cssValues objectAtIndex:0] isEqualToString:@"rgba("]) { - // rgba( x x x x ) - color = RGBACOLOR([[cssValues objectAtIndex:1] floatValue], - [[cssValues objectAtIndex:2] floatValue], - [[cssValues objectAtIndex:3] floatValue], - [[cssValues objectAtIndex:4] floatValue]); - } + // Cache it. + [_cssRulesSet setValue:ruleSet forKey:selector]; + } - return color; + // Return it. + return ruleSet; } - /////////////////////////////////////////////////////////////////////////////////////////////////// -- (UIColor*)colorWithCssSelector: (NSString*)selector - propertyName: (NSString*)propertyName { - UIColor* color = [self objectForCssSelector:selector propertyName:propertyName]; - - // No cached value. - if (nil == color) { - NSDictionary* ruleSet = [_cssStyles objectForKey:selector]; - - // The given selector actually exists in the CSS. - if (nil != ruleSet) { - NSArray* values = [ruleSet objectForKey:propertyName]; - - if (nil != values) { - color = [self colorFromCssValues:values]; - - // And we can actually parse it. - if (nil != color) { - [self setObjectForCssSelector:selector propertyName:propertyName object:color]; - } - } - } - } - - return color; +-(TTCSSRuleSet*)css:(NSString*)selectorName forState:(UIControlState)state { + return [self css:[self selector:selectorName forState:state]]; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Colors /////////////////////////////////////////////////////////////////////////////////////////////////// - (UIColor*)colorWithCssSelector:(NSString*)selector forState:(UIControlState)state { - selector = [self selector:selector forState:state]; + // Try Retrieve Rule Set from Cache. + TTCSSRuleSet *ruleSet = [self css:selector forState:state]; + + // If don't have an CSS Rule Set, return nil. + if ( !ruleSet ) return nil; - return [self colorWithCssSelector:selector propertyName:kCssPropertyColor]; + // Return color from rule set. + return ruleSet.color; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (UIColor*)colorWithCssSelector:(NSString*)selector { + return [self colorWithCssSelector:selector forState:UIControlStateNormal]; +} /////////////////////////////////////////////////////////////////////////////////////////////////// - (UIColor*)backgroundColorWithCssSelector:(NSString*)selector forState:(UIControlState)state { - selector = [self selector:selector forState:state]; + // Try Retrieve Rule Set from Cache. + TTCSSRuleSet *ruleSet = [self css:selector forState:state]; + + // If don't have an CSS Rule Set, return nil. + if ( !ruleSet ) return nil; - return [self colorWithCssSelector: selector - propertyName: kCssPropertyBackgroundColor]; + // Return background color from rule set. + return ruleSet.background_color; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (UIColor*)backgroundColorWithCssSelector:(NSString*)selector { + return [self backgroundColorWithCssSelector:selector forState:UIControlStateNormal]; +} /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - #pragma mark Fonts - /////////////////////////////////////////////////////////////////////////////////////////////////// - (UIFont*)fontWithCssSelector:(NSString*)selector forState:(UIControlState)state { - selector = [self selector:selector forState:state]; - UIFont* font = [self objectForCssSelector:selector propertyName:kCssPropertyFont]; + // Try Retrieve Rule Set from Cache. + TTCSSRuleSet *ruleSet = [self css:selector forState:state]; - // No cached value. - if (nil == font) { - NSDictionary* ruleSet = [_cssStyles objectForKey:selector]; + // If don't have an CSS Rule Set, return nil. + if ( !ruleSet ) return nil; - // The given selector actually exists in the CSS. - if (nil != ruleSet) { - CGFloat fontSize = [UIFont systemFontSize]; - BOOL isBold = NO; + // Return decoded font from rule set. + return ruleSet.font; - NSArray* fontSizeValues = [ruleSet objectForKey:kCssPropertyFontSize]; - - if (nil != fontSizeValues) { - // Anything more or less is unsupported, and therefore this property is ignored - // according to the W3C guidelines. - TTDASSERT([fontSizeValues count] == 1); - if ([fontSizeValues count] == 1) { - fontSize = [[fontSizeValues objectAtIndex:0] floatValue]; - } - - NSArray* fontWeightValues = [ruleSet objectForKey:kCssPropertyFontWeight]; - // Anything more or less is unsupported, and therefore this property is ignored - // according to the W3C guidelines. - if ([fontWeightValues count] == 1) { - if ([[fontWeightValues objectAtIndex:0] isEqualToString:@"bold"]) { - isBold = YES; - } - } - - NSArray* fontFamilyValues = [ruleSet objectForKey:kCssPropertyFontFamily]; - if ([fontFamilyValues count] > 0) { - TTDINFO(@"Font families: %@", [UIFont familyNames]); - for (NSString* fontName in fontFamilyValues) { - } - if ([[fontFamilyValues objectAtIndex:0] isEqualToString:@"bold"]) { - isBold = YES; - } - } - - if (isBold) { - font = [UIFont boldSystemFontOfSize:fontSize]; - - } else { - font = [UIFont systemFontOfSize:fontSize]; - } - - if (nil != font) { - [self setObjectForCssSelector:selector propertyName:kCssPropertyFont object:font]; - } - } - } - } - - return font; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (UIFont*)fontWithCssSelector:(NSString*)selector { + return [self fontWithCssSelector:selector forState:UIControlStateNormal]; +} /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - #pragma mark Text Shadows - /////////////////////////////////////////////////////////////////////////////////////////////////// -- (NSDictionary*)textShadowWithCssSelector:(NSString*)selector forState:(UIControlState)state { - NSDictionary* textShadow = [self objectForCssSelector: selector - propertyName: kCssPropertyTextShadow]; - - // No cached value. - if (nil == textShadow) { - NSDictionary* ruleSet = [_cssStyles objectForKey:selector]; - - // The given selector actually exists in the CSS. - if (nil != ruleSet) { - NSArray* values = [ruleSet objectForKey:kCssPropertyTextShadow]; - - // Safety check - if (nil == values) return nil; - - // Anything more or less is unsupported, and therefore this property is ignored - // according to the W3C guidelines. - TTDASSERT([values count] >= 4); - if ([values count] >= 4) { - NSNumber* horizOffset = [NSNumber numberWithFloat:[[values objectAtIndex:0] floatValue]]; - NSNumber* vertOffset = [NSNumber numberWithFloat:[[values objectAtIndex:1] floatValue]]; - NSNumber* blurAmount = [NSNumber numberWithFloat:[[values objectAtIndex:2] floatValue]]; - UIColor* color = [self colorFromCssValues: - [values subarrayWithRange: - NSMakeRange(3, [values count] - 3)]]; - - textShadow = [NSDictionary dictionaryWithObjectsAndKeys: - horizOffset, kKeyTextShadowHOffset, - vertOffset, kKeyTextShadowVOffset, - blurAmount, kKeyTextShadowBlur, - color, kKeyTextShadowColor, - nil]; - } - - if (nil != textShadow) { - [self setObjectForCssSelector: selector - propertyName: kCssPropertyTextShadow - object: textShadow]; - } - } - } +- (UIColor*)textShadowColorWithCssSelector:(NSString*)selector forState:(UIControlState)state { + // Try Retrieve Rule Set from Cache. + TTCSSRuleSet *ruleSet = [self css:selector forState:state]; - return textShadow; -} + // If don't have an CSS Rule Set, return nil. + if ( !ruleSet ) return nil; + // Return Text Shadow Color. + return ruleSet.text_shadow.shadowColor; +} /////////////////////////////////////////////////////////////////////////////////////////////////// -- (UIColor*)textShadowColorWithCssSelector:(NSString*)selector forState:(UIControlState)state { - selector = [self selector:selector forState:state]; - - NSDictionary* textShadow = [self textShadowWithCssSelector: selector - forState: state]; - return nil != textShadow ? [textShadow objectForKey:kKeyTextShadowColor] : nil; +- (UIColor*)textShadowColorWithCssSelector:(NSString*)selector { + return [self textShadowColorWithCssSelector:selector forState:UIControlStateNormal]; } - /////////////////////////////////////////////////////////////////////////////////////////////////// - (CGSize)textShadowOffsetWithCssSelector:(NSString*)selector forState:(UIControlState)state { - selector = [self selector:selector forState:state]; - - NSDictionary* textShadow = [self textShadowWithCssSelector: selector - forState: state]; - return nil != textShadow ? - CGSizeMake([[textShadow objectForKey:kKeyTextShadowHOffset] floatValue], - [[textShadow objectForKey:kKeyTextShadowVOffset] floatValue]) : - CGSizeZero; + // Try Retrieve Rule Set from Cache. + TTCSSRuleSet *ruleSet = [self css:selector forState:state]; + + // If don't have an CSS Rule Set, return zero. + if ( !ruleSet ) return CGSizeZero; + + // Return Text Shadow Color. + return ruleSet.text_shadow.shadowOffset; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (CGSize)textShadowOffsetWithCssSelector:(NSString*)selector { + return [self textShadowOffsetWithCssSelector:selector forState:UIControlStateNormal]; +} /////////////////////////////////////////////////////////////////////////////////////////////////// - (CGFloat)textShadowRadiusWithCssSelector:(NSString*)selector forState:(UIControlState)state { - selector = [self selector:selector forState:state]; + // Try Retrieve Rule Set from Cache. + TTCSSRuleSet *ruleSet = [self css:selector forState:state]; + + // If don't have an CSS Rule Set, return zero. + if ( !ruleSet ) return 0.0; - NSDictionary* textShadow = [self textShadowWithCssSelector: selector - forState: state]; - return nil != textShadow ? [[textShadow objectForKey:kKeyTextShadowBlur] floatValue] : 0; + // Return Shadow Blur. + return [[ruleSet.text_shadow shadowBlur] floatValue]; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (CGFloat)textShadowRadiusWithCssSelector:(NSString*)selector { + return [self textShadowRadiusWithCssSelector:selector forState:UIControlStateNormal]; +} /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -515,9 +468,8 @@ - (CGFloat)textShadowRadiusWithCssSelector:(NSString*)selector forState:(UIContr /////////////////////////////////////////////////////////////////////////////////////////////////// - (void)freeMemory { - TT_RELEASE_SAFELY(_cachedCssStyles); - TT_RELEASE_SAFELY(_colorLookupTable); - _cachedCssStyles = [[NSMutableDictionary alloc] initWithCapacity:[_cssStyles count]]; + TT_RELEASE_SAFELY(_cssRulesSet); + _cssRulesSet = [[NSMutableDictionary alloc] initWithCapacity:[_cssStyles count]]; } diff --git a/src/extThree20CSSStyle/Sources/TTCSSTextShadowModel.m b/src/extThree20CSSStyle/Sources/TTCSSTextShadowModel.m new file mode 100644 index 0000000000..8e9350800a --- /dev/null +++ b/src/extThree20CSSStyle/Sources/TTCSSTextShadowModel.m @@ -0,0 +1,108 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 "extThree20CSSStyle/TTCSSTextShadowModel.h" +#import "extThree20CSSStyle/TTCSSFunctions.h" + +// Core +#import "Three20Core/TTCorePreprocessorMacros.h" +#import "Three20Core/TTGlobalCore.h" +#import "Three20Core/TTDebug.h" + +@implementation TTCSSTextShadowModel +@synthesize shadowOffset, shadowColor, shadowBlur; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Init Methods. + +/////////////////////////////////////////////////////////////////////////////////////////////////// ++(id)initWithShadowColor:(id)anColor andShadowOffset:(CGSize)anOffset { + TTCSSTextShadowModel *instance = [[TTCSSTextShadowModel new] autorelease]; + instance.shadowColor = anColor; + instance.shadowOffset = anOffset; + return instance; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// ++(id)initWithShadowColor:(id)anColor andShadowOffset:(CGSize)anOffset + andShadowBlur:(NSNumber*)blur { + TTCSSTextShadowModel *instance = [TTCSSTextShadowModel initWithShadowColor:anColor + andShadowOffset:anOffset]; + instance.shadowBlur = blur; + return instance; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(id)init { + self = [super init]; + if (self != nil) { + + // Default values. + self.shadowOffset = CGSizeMake(0, -1); + self.shadowColor = [UIColor clearColor]; + self.shadowBlur = [[NSNumber numberWithInt:3] retain]; + + } + return self; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)dealloc { + TT_RELEASE_SAFELY( shadowColor ); + TT_RELEASE_SAFELY( shadowBlur ); + [super dealloc]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Set Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)setShadowColor:(id)anValue { + + ///////////////////////////////// + // Release. + if ( shadowColor ) + TT_RELEASE_SAFELY( shadowColor ); + + /////////////////////////////////////// + // Array of color? + if ( [anValue isKindOfClass:[NSArray class]] ) { + + // Set. + shadowColor = [TTColorFromCssValues(anValue) retain]; + + } + + /////////////////////////////////////// + // String color? + else if ( [anValue isKindOfClass:[NSString class]] ) { + + // Set. + shadowColor = [TTColorFromCssValues([NSArray arrayWithObject:anValue]) retain]; + } + + /////////////////////////////////////// + // UIColor? + else if ( [anValue isKindOfClass:[UIColor class]] ) { + + // Set. + shadowColor = [anValue retain]; + } +} + +@end diff --git a/src/extThree20CSSStyle/Sources/TTDefaultCSSStyleSheet.m b/src/extThree20CSSStyle/Sources/TTDefaultCSSStyleSheet.m index dc78a4ad45..7c49e17ee9 100644 --- a/src/extThree20CSSStyle/Sources/TTDefaultCSSStyleSheet.m +++ b/src/extThree20CSSStyle/Sources/TTDefaultCSSStyleSheet.m @@ -15,9 +15,11 @@ // #import "extThree20CSSStyle/TTDefaultCSSStyleSheet.h" +#import "extThree20CSSStyle/TTCSSRuleSet.h" // extThree20CSSStyle #import "extThree20CSSStyle/TTCSSStyleSheet.h" +#import "extThree20CSSStyle/TTCSSApplyProtocol.h" // Core #import "Three20Core/TTCorePreprocessorMacros.h" @@ -71,6 +73,7 @@ - (void)dealloc { object: nil]; TT_RELEASE_SAFELY(_styleSheet); + TT_RELEASE_SAFELY(_cachedCssFiles); [super dealloc]; } @@ -97,13 +100,20 @@ - (void)freeMemory { /////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - #pragma mark Public /////////////////////////////////////////////////////////////////////////////////////////////////// -- (BOOL)addStyleSheetFromDisk:(NSString*)filename { +- (BOOL)addStyleSheetFromDisk:(NSString*)filename ignoreCache:(BOOL)cache { + + // Check if this file is already cached, also respect if should ignore the cache. + if (!cache && [_cachedCssFiles containsObject:filename]) { + TTDWARNING( @"'%@' is already loaded and cached. Ignoring...", filename ); + return NO; + } + TTCSSStyleSheet* styleSheet = [[TTCSSStyleSheet alloc] init]; BOOL loadedSuccessfully = [styleSheet loadFromFilename:filename]; @@ -112,9 +122,22 @@ - (BOOL)addStyleSheetFromDisk:(NSString*)filename { TT_RELEASE_SAFELY(styleSheet); + ///////////// //////// //////// //////// //////// + // Init cache, if needed. + if ( !_cachedCssFiles ) + _cachedCssFiles = [NSMutableSet new]; + + // Cache if Loaded Successfully. + if ( loadedSuccessfully ) + [_cachedCssFiles addObject:filename]; + return loadedSuccessfully; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (BOOL)addStyleSheetFromDisk:(NSString*)filename { + return [self addStyleSheetFromDisk:filename ignoreCache:NO]; +} /////////////////////////////////////////////////////////////////////////////////////////////////// + (TTDefaultCSSStyleSheet*)globalCSSStyleSheet { @@ -123,6 +146,18 @@ + (TTDefaultCSSStyleSheet*)globalCSSStyleSheet { } +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)applyCssFromSelector:(NSString*)selectorName toObject:(id)anObject { + // Assert that the conforms with the protocol. + if ( ![(id)anObject conformsToProtocol:@protocol(TTCSSApplyProtocol)] ) + [NSException raise:NSInternalInconsistencyException + format:@"'%@' must conform with the 'TTCSSApplyProtocol' protocol", + NSStringFromClass([(id)anObject class]) ]; + + // Apply retrieved rules to the object. + [anObject applyCssRules:[self css:selectorName]]; +} + /////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - @@ -347,6 +382,16 @@ - (CGSize)tableRefreshHeaderTextShadowOffset { forState: UIControlStateNormal]; } +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(TTCSSRuleSet*)css:(NSString*)selector { + return [_styleSheet css:selector]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(TTCSSRuleSet*)css:(NSString*)selectorName forState:(UIControlState)state { + return [_styleSheet css:selectorName forState:state]; +} + @end diff --git a/src/extThree20CSSStyle/Sources/UILabel+CSSAdditions.m b/src/extThree20CSSStyle/Sources/UILabel+CSSAdditions.m new file mode 100644 index 0000000000..c964517957 --- /dev/null +++ b/src/extThree20CSSStyle/Sources/UILabel+CSSAdditions.m @@ -0,0 +1,83 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 "extThree20CSSStyle/UILabel+CSSAdditions.h" + +// Core +#import "Three20Core/TTCorePreprocessorMacros.h" + +#ifdef __IPHONE_3_2 +#import +#endif + +/** + * Additions. + */ +TT_FIX_CATEGORY_BUG(TTCSSLabelAdditions) + +@implementation UILabel (TTCSSAdditions) + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Receive an Set of Rules from some CSS selector to apply. This method +// receive an TTCSSRuleSet with all properties ready to be set. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)applyCssRules:(TTCSSRuleSet*)anRuleSet { + // Super. + [super applyCssRules:anRuleSet]; + + // Set properties from CSS, if defined. + if (anRuleSet.font) self.font = anRuleSet.font; + if (anRuleSet.color) self.textColor = anRuleSet.color; + + // Alignment. + if (anRuleSet.text_align) self.textAlignment = [anRuleSet textAlign]; + + // Set Shadow, if needed. + if (anRuleSet.text_shadow.shadowColor) { + + // iPhone 3.2 accept blur on shadows, so do it. + #ifdef __IPHONE_3_2 + // If blur defined. + if (anRuleSet.text_shadow.shadowBlur) { + self.layer.shadowOpacity = [anRuleSet.text_shadow_opacity floatValue]; + self.layer.shadowColor = [anRuleSet.text_shadow.shadowColor CGColor]; + self.layer.shadowOffset = anRuleSet.text_shadow.shadowOffset; + self.layer.shadowRadius = [anRuleSet.text_shadow.shadowBlur floatValue]; + self.layer.masksToBounds = NO; + } + //////////// ///// ///// ///// ///// ///// ///// ///// ///// + // If not. + else { + self.shadowColor = anRuleSet.text_shadow.shadowColor; + self.shadowOffset = anRuleSet.text_shadow.shadowOffset; + } + //////////// ///// ///// ///// ///// ///// ///// ///// ///// + // If not, just color and offset. + #else + self.shadowColor = anRuleSet.text_shadow.shadowColor; + self.shadowOffset = anRuleSet.text_shadow.shadowOffset; + #endif + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Receive an Set of Rules from some CSS selector to apply. This method +// receive an TTCSSRuleSet with all properties ready to be set. +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +@end + + diff --git a/src/extThree20CSSStyle/Sources/UILabelAdditions.m b/src/extThree20CSSStyle/Sources/UILabelAdditions.m deleted file mode 100644 index 2f57da426d..0000000000 --- a/src/extThree20CSSStyle/Sources/UILabelAdditions.m +++ /dev/null @@ -1,73 +0,0 @@ -// -// Copyright 2009-2011 Facebook -// -// 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 "extThree20CSSStyle/UILabelAdditions.h" - -#import "extThree20CSSStyle/TTCSSGlobalStyle.h" -#import "extThree20CSSStyle/TTCSSStyleSheet.h" -#import "extThree20CSSStyle/TTDefaultCSSStyleSheet.h" - -// Core -#import "Three20Core/TTCorePreprocessorMacros.h" - -#ifdef __IPHONE_3_2 -#import -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/** - * Additions. - */ -TT_FIX_CATEGORY_BUG(TTCSSLabelAdditions) - -@implementation UILabel (TTCSSCategory) - -/////////////////////////////////////////////////////////////////////////////////////////////////// -- (void)applyCssSelector:(NSString *)selector { - UIFont *font = TTCSS(selector, font); - UIColor *color = TTCSS(selector, color); - UIColor *backgroundColor = TTCSS(selector, backgroundColor); - - if (font) self.font = font; - if (color) self.textColor = color; - if (backgroundColor) self.backgroundColor = backgroundColor; - - UIColor *shadowColor = TTCSS(selector, shadowColor); - CGSize shadowOffset = TTCSS(selector, shadowOffset); - if (shadowColor) { -#ifdef __IPHONE_3_2 - CGFloat shadowRadius = TTCSS(selector, shadowRadius); - if (shadowRadius) { - self.layer.shadowOpacity = 1.0; - self.layer.shadowColor = shadowColor.CGColor; - self.layer.shadowOffset = shadowOffset; - self.layer.shadowRadius = shadowRadius; - self.layer.masksToBounds = NO; - } - else { - self.shadowColor = shadowColor; - self.shadowOffset = shadowOffset; - } -#else - self.shadowColor = shadowColor; - self.shadowOffset = shadowOffset; -#endif - } -} - -@end diff --git a/src/extThree20CSSStyle/Sources/UIView+CSSAdditions.m b/src/extThree20CSSStyle/Sources/UIView+CSSAdditions.m new file mode 100644 index 0000000000..1a3f9e669b --- /dev/null +++ b/src/extThree20CSSStyle/Sources/UIView+CSSAdditions.m @@ -0,0 +1,103 @@ +// +// Copyright 2009-2011 Facebook +// +// 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 "extThree20CSSStyle/UIView+CSSAdditions.h" +#import "extThree20CSSStyle/TTDefaultCSSStyleSheet.h" +#import "extThree20CSSStyle/TTCSSGlobalStyle.h" + +// Core +#import "Three20Core/TTCorePreprocessorMacros.h" +#import "Three20Core/TTGlobalCorePaths.h" + +/** + * Additions. + */ +TT_FIX_CATEGORY_BUG(TTCSSViewAdditions) + +@implementation UIView (TTCSSAdditions) + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Convenient Init method to create an UIView and apply an CSS Rule Set on one pass. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(id)initWithFrame:(CGRect)anFrame andApplyCssFromSelector:(NSString*)anSelector { + self = [self initWithFrame:anFrame]; + if (self != nil) { + // Apply CSS. + TTApplyCSS( anSelector, self ); + } + return self; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Receive an Set of Rules from some CSS selector to apply. This method +// receive an TTCSSRuleSet with all properties ready to be set. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(void)applyCssRules:(TTCSSRuleSet*)anRuleSet { + // Set properties from CSS. + self.backgroundColor = anRuleSet.background_color; + + ////////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// //// + // Set image background. + if ( anRuleSet.background_image ) { + + ////////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// //// + // Assert that this file exist on the bundle + BOOL exist = [[NSFileManager defaultManager] fileExistsAtPath: + TTPathForBundleResource( anRuleSet.background_image )]; + if ( !exist ) { + NSString *m = [NSString stringWithFormat:@"The file '%@' on the property %@", + anRuleSet.background_image, + @"'background_image' don't exist on your application bundle."]; + [NSException raise:@"NSFileNotFoundException" format:@"%@", m]; + } + + ////////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// //// + // If ok add as subview. + [self addSubview:[[UIImageView alloc] initWithImage: + [UIImage imageNamed:anRuleSet.background_image]]]; + } + + ////////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// //// + // Hidden? + self.hidden = anRuleSet.hidden; + + ////////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// //// + // Original frame. + CGRect newFrame = self.frame; + + ////////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// ////// //// + // Change Frame from CSS values if needed. + newFrame.origin.x = ( anRuleSet.left ? anRuleSet.origin.x : newFrame.origin.x ); + newFrame.origin.y = ( anRuleSet.top ? anRuleSet.origin.y : newFrame.origin.y ); + /// + newFrame.size.width = ( anRuleSet.width ? anRuleSet.size.width : newFrame.size.width ); + newFrame.size.height = ( anRuleSet.height ? anRuleSet.size.height : newFrame.size.height ); + + // Apply. + self.frame = newFrame; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Set a CSS stylesheet selector. +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)applyCssSelector:(NSString *)anSelector { + // Apply CSS. + TTApplyCSS( anSelector, self ); +} + +@end diff --git a/src/extThree20CSSStyle/ThirdPart/TTDataConverter.m b/src/extThree20CSSStyle/ThirdPart/TTDataConverter.m new file mode 100644 index 0000000000..04c6ad2a39 --- /dev/null +++ b/src/extThree20CSSStyle/ThirdPart/TTDataConverter.m @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011 - SEQOY.org and Paulo Oliveira ( http://www.seqoy.org ) + * JUMP GIT Repository: https://github.com/seqoy/jump + * + * 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 "extThree20CSSStyle/TTDataConverter.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +@implementation TTDataConverter + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Convert Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Take an NSString Object and try to convert to NSNumber. +/////////////////////////////////////////////////////////////////////////////////////////////////// ++(NSNumber*)convertToNSNumberThisObject:(id)anObject { + + // Convert from NSString to NSNumber. + if ( [anObject isKindOfClass:[NSString class]] ) { + + // Create an Scanner, the scaner will scan the string looking for specific type number. + NSScanner *stringScanner = [NSScanner scannerWithString:anObject]; + + // NOTE: The order is very important ->-- 'float' after 'double' and then 'int'. + + // Scan string looking for FLOAT. + float aFloat; + if ( [stringScanner scanFloat:&aFloat] ) + return [NSNumber numberWithFloat:[anObject floatValue]]; + + // Scan string looking for DOUBLE. + double aDouble; + if ( [stringScanner scanDouble:&aDouble] ) + return [NSNumber numberWithDouble:[anObject doubleValue]]; + + // Scan string looking for INT. + int aInt; + if ( [stringScanner scanInt:&aInt] ) + return [NSNumber numberWithInt:[anObject intValue]]; + } + + // Can't convert, return NIL. + return nil; +} +@end diff --git a/src/extThree20CSSStyle/ThirdPart/TTDataPopulator.m b/src/extThree20CSSStyle/ThirdPart/TTDataPopulator.m new file mode 100644 index 0000000000..15359dacd8 --- /dev/null +++ b/src/extThree20CSSStyle/ThirdPart/TTDataPopulator.m @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2011 - SEQOY.org and Paulo Oliveira ( http://www.seqoy.org ) + * JUMP GIT Repository: https://github.com/seqoy/jump + * + * 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 "extThree20CSSStyle/TTDataPopulator.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +@implementation TTDataPopulator +@synthesize delegate; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Private Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(NSString*)capitalizeFirstLetter:(NSString*)anString { + + NSString *firstLetter = [ [anString substringWithRange:NSMakeRange(0, 1)] uppercaseString]; + NSString *rest = [anString substringFromIndex:1]; + + // Return formatted String. + return [NSString stringWithFormat:@"%@%@", firstLetter, rest]; + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(id)tryToGrabDataKey:(NSString*)anKey fromMap:(NSDictionary*)anMap { + + // Try To Grab a Data Key + return [anMap objectForKey:anKey]; + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(Class)grabTheClassOfProperty:(NSString*)firstKey onObject:(id)firstObject { + + // ///////////// ///////////// ///////////// ///////////// ///////////// + /* + * To correct compile, you need to ADD the libobjc.A.dylib framework to + * your target. And also #import the + */ + + // Get the property (Method) attributes. + objc_property_t property = class_getProperty([firstObject class], [firstKey UTF8String]); + + // Test if some data was returned, first. + if ( property != NULL ) { + + // Attribute description: + NSString *attributeDescripion = [NSString stringWithCString:property_getAttributes(property) + encoding:[NSString defaultCStringEncoding]]; + + // Isolate the Class of this property. + NSArray *elements = [attributeDescripion componentsSeparatedByString:@"\""]; + + // Should have 3 elements, if don't we can't process. + if ( [elements count] != 3 ) return nil; + + // The second element is what we want... So transform him on a class. + Class firstKeyClass = NSClassFromString([elements objectAtIndex:1]); + + // And return. + return firstKeyClass; + } + + ///////////// ///////////// /////// + // If can't decode, return nil. + return nil; + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Check if the *firstKey* (Method) type of the Object **anObject** (Class) +// is the same that the secondKey (Method) secondObject (Class). +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(BOOL)checkIfObject:(id)firstObject ofKey:(NSString*)firstKey + hasSameTypeOf:(id)secondObject ofKey:(NSString*)secondKey { + + // Class of the First Key. + Class firstKeyClass = [self grabTheClassOfProperty:firstKey onObject:firstObject]; + + // Return if matches. + return [secondObject isKindOfClass:firstKeyClass]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Try to convert the **fistObject** to the same type of the **secondObject**. +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(id)tryToConvert:(id)firstObject ofKey:(NSString*)firstKey + toTheSameClassOf:(id)secondObject ofKey:(NSString*)secondKey { + + // Class of the Second Key. + Class secondKeyClass = [self grabTheClassOfProperty:secondKey onObject:secondObject]; + + // Converted value. + id converted = nil; + + ///////////// ///////////// //////// + // If desired value are an NSNumber. + if ( secondKeyClass == [NSNumber class] ) + converted = [TTDataConverter convertToNSNumberThisObject:firstObject]; + + // Maybe the delegate can convert it... + if ( delegate ) + if ( [(id)delegate respondsToSelector:@selector(tryToConvert:ofClass:toClass:) ] ) + converted = [delegate tryToConvert:firstObject ofClass:[firstObject class] + toClass:secondKeyClass]; + + // Return converted. + return converted; + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +-(id)populateObject:(id)anObject withData:(NSDictionary*)anDictionary + usingMap:(NSDictionary*)anMap { + + //// //// //// //// //// //// //// //// //// //// //// //// + // Loop every property. + for ( id property in anDictionary ) { + + // Try to find corresponding data key. + NSString *dataKey = [self tryToGrabDataKey:property fromMap:anMap]; + + // Only process if found. + if ( dataKey ) { + + // Method Name for corresponding server key. + NSString *convertedMethodName = [NSString stringWithFormat:@"set%@:", + [self capitalizeFirstLetter:dataKey]]; + + // Selector for this element. + SEL anSelector = NSSelectorFromString( convertedMethodName ); + + ///////////////////////////////////////////////////////////////////// + // Check if object responds to this SET selector. + if ( [anObject respondsToSelector:anSelector] + && + ! [[anDictionary objectForKey:property] isKindOfClass:[NSNull class]] ) + { + // Retrieve the data. + id serverData = [anDictionary objectForKey:property]; + + //// //// //// //// //// //// //// //// //// //// //// //// //// + // Check if Server Data has the same type of Core Data Object. + //// //// //// //// //// //// ///// //// // //// //// //// ///// + if ( ! [self checkIfObject:anObject ofKey:dataKey + hasSameTypeOf:serverData ofKey:property] ) + { + // if DONT → Try to convert. ➘ (Oh yeah!) + serverData = [self tryToConvert:serverData ofKey:property + toTheSameClassOf:anObject ofKey:dataKey]; + } + //// //// //// //// //// //// //// //// //// //////// //// //////// //// ///// + // Set Value if isn't NIL. + if ( serverData != nil ) { + + // Validate first. + NSError *anError; + if ( ![anObject validateValue:&serverData forKey:dataKey error:&anError] ) { + [NSException raise:anError.domain format:@"%@", [anError localizedDescription]]; + return nil; + } + + // Set the value. + [anObject setValue:serverData forKey:dataKey]; + } + } + } + } + + // Return populated object. + return anObject; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark Populate Methods. +/////////////////////////////////////////////////////////////////////////////////////////////////// ++(id)populateObject:(id)anObject withData:(NSDictionary*)anDictionary + usingMap:(NSDictionary*)anMap withDelegate:(id)anDelegate { + // Create an instance. + TTDataPopulator *anInstance = [[[self alloc] init] autorelease]; + // Set delegate. + anInstance.delegate = anDelegate; + + ///////////// + return [anInstance populateObject:anObject + withData:anDictionary + usingMap:anMap]; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Populate the informed object with data. +/////////////////////////////////////////////////////////////////////////////////////////////////// ++(id)populateObject:(id)anObject withData:(NSDictionary*)anDictionary + usingMap:(NSDictionary*)anMap { + return [self populateObject:anObject withData:anDictionary usingMap:anMap withDelegate:nil]; +} +///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// ///// //// +@end diff --git a/src/extThree20CSSStyle/UnitTests/CssRuleSetTests.m b/src/extThree20CSSStyle/UnitTests/CssRuleSetTests.m new file mode 100644 index 0000000000..1f2cbc4971 --- /dev/null +++ b/src/extThree20CSSStyle/UnitTests/CssRuleSetTests.m @@ -0,0 +1,100 @@ +// +// Copyright 2009-2011 Facebook +// +// 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. +// + +// See: http://bit.ly/hS5nNh for unit test macros. +// See Also: http://bit.ly/hgpqd2 + +#import + +#import "TTCSSRuleSet.h" + +// Core +#import "Three20Core/TTCorePreprocessorMacros.h" + +@interface CssRuleSetTests : SenTestCase { + TTCSSRuleSet *_ruleSet; +} + +@end + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////////// +@implementation CssRuleSetTests + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)setUp { + _ruleSet = [[TTCSSRuleSet initWithSelectorName:@"testSelector"] retain]; + STAssertNotNil( _ruleSet, @"CSS Rule Set Object wasn't initiated correctly"); + STAssertTrue( [_ruleSet.selector isEqualToString:@"testSelector"], + @"Selector name wasn't setted correctly." ); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)tearDown { + TT_RELEASE_SAFELY(_ruleSet); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +//- (void)testLoadColorData { +// // Test UI Color. +// UIColor *anColor = [UIColor redColor]; +// _ruleSet.color = anColor; +// _ruleSet.background_color = anColor; +// /////////////////////// //////////////// /////////////////////// //////////////// +// STAssertTrue( anColor == _ruleSet.color, +// @"'color' property with UIColor value wasn't setted correctly" ); +// /////////////////////// //////////////// /////////////////////// //////////////// +// STAssertTrue( anColor == _ruleSet.background_color, +// @"'background_color' property with UIColor value wasn't setted correctly" ); +// +// /////////////////////// //////////////// /////////////////////// //////////////// +// // Test String Color. +// _ruleSet.color = @"red"; +// _ruleSet.background_color = @"red"; +// /////////////////////// //////////////// /////////////////////// //////////////// +// STAssertTrue( anColor == _ruleSet.color, +// @"'color' property with String value wasn't setted correctly" ); +// /////////////////////// //////////////// /////////////////////// //////////////// +// STAssertTrue( anColor == _ruleSet.background_color, +// @"'background_color' property with String value wasn't setted correctly" ); +//} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +- (void)testFont { + // Set font values. + _ruleSet.font_family = @"Helvetica"; + _ruleSet.font_weight = @"BoldOblique"; + _ruleSet.font_size = [NSNumber numberWithInt:10]; + /////////////////////// //////////////// /////////////////////// //////////////// + STAssertTrue( [_ruleSet.font_family isEqualToString:@"Helvetica"], + @"'font_family' property wasn't setted correctly" ); + /////////////////////// //////////////// /////////////////////// //////////////// + STAssertTrue( [_ruleSet.font_weight isEqualToString:@"BoldOblique"], + @"'font_weight' property wasn't setted correctly" ); + /////////////////////// //////////////// /////////////////////// //////////////// + STAssertTrue( [_ruleSet.font_size intValue] == 10, + @"'font_size' property wasn't setted correctly" ); + /////////////////////// //////////////// /////////////////////// //////////////// + //UIFont *createdFont = _ruleSet.font; + //STAssertNotNil( createdFont, @"Font must be created at this time"); +} + + +@end diff --git a/src/extThree20CSSStyle/extThree20CSSStyle.xcodeproj/project.pbxproj b/src/extThree20CSSStyle/extThree20CSSStyle.xcodeproj/project.pbxproj index 1439d4208c..f9c0e99b6f 100755 --- a/src/extThree20CSSStyle/extThree20CSSStyle.xcodeproj/project.pbxproj +++ b/src/extThree20CSSStyle/extThree20CSSStyle.xcodeproj/project.pbxproj @@ -21,6 +21,33 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 1831D1AF13AA9FAC00AB4D55 /* TTDataConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1831D1AD13AA9FAC00AB4D55 /* TTDataConverter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1831D1B013AA9FAC00AB4D55 /* TTDataPopulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1831D1AE13AA9FAC00AB4D55 /* TTDataPopulator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1831D1B313AA9FB500AB4D55 /* TTDataConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1831D1B113AA9FB500AB4D55 /* TTDataConverter.m */; }; + 1831D1B413AA9FB500AB4D55 /* TTDataPopulator.m in Sources */ = {isa = PBXBuildFile; fileRef = 1831D1B213AA9FB500AB4D55 /* TTDataPopulator.m */; }; + 1831D1DA13AAA24400AB4D55 /* TTDataPopulatorDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1831D1D913AAA24400AB4D55 /* TTDataPopulatorDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1832BD9713B243FD00C50CFE /* TTDefaultCSSStyleSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = 1832BD9613B243FD00C50CFE /* TTDefaultCSSStyleSheet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 183F67B313B0F5BE0032CFF5 /* TTCSSFunctions.m in Sources */ = {isa = PBXBuildFile; fileRef = 183F67B213B0F5BE0032CFF5 /* TTCSSFunctions.m */; }; + 183F67EA13B0F8B40032CFF5 /* TTCSSFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = 183F67AD13B0F5AE0032CFF5 /* TTCSSFunctions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 186AE75913AA4C35004D43FA /* TTCSSRuleSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 186AE6F213AA3FF1004D43FA /* TTCSSRuleSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 186AE75A13AA4C3A004D43FA /* TTCSSRuleSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 186AE75613AA4C1C004D43FA /* TTCSSRuleSet.m */; }; + 186AE80913AA512C004D43FA /* TTCSSTextShadowModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 186AE80813AA512C004D43FA /* TTCSSTextShadowModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 186AE80B13AA5379004D43FA /* TTCSSTextShadowModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 186AE80A13AA5379004D43FA /* TTCSSTextShadowModel.m */; }; + 186AE92013AA7C7E004D43FA /* CssRuleSetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 186AE91F13AA7C7E004D43FA /* CssRuleSetTests.m */; }; + 1892DC1C13D61D5B008DFAC5 /* UILabelAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1892DC1B13D61D5B008DFAC5 /* UILabelAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1892DC1F13D61D6A008DFAC5 /* TTShadowStyleAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1892DC1D13D61D6A008DFAC5 /* TTShadowStyleAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1892DC2013D61D6A008DFAC5 /* TTTextStyleAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1892DC1E13D61D6A008DFAC5 /* TTTextStyleAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1892DC2213D61D77008DFAC5 /* TTCSSGlobalStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 1892DC2113D61D77008DFAC5 /* TTCSSGlobalStyle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1892DC2513D61D81008DFAC5 /* TTShadowStyleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1892DC2313D61D81008DFAC5 /* TTShadowStyleAdditions.m */; }; + 1892DC2613D61D81008DFAC5 /* TTTextStyleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1892DC2413D61D81008DFAC5 /* TTTextStyleAdditions.m */; }; + 1892DC2713D61D81008DFAC5 /* TTShadowStyleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1892DC2313D61D81008DFAC5 /* TTShadowStyleAdditions.m */; }; + 1892DC2813D61D81008DFAC5 /* TTTextStyleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1892DC2413D61D81008DFAC5 /* TTTextStyleAdditions.m */; }; + 1892DC2E13D61D90008DFAC5 /* extThree20CSSStyle+Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 1892DC2D13D61D90008DFAC5 /* extThree20CSSStyle+Additions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18F5A81713B2927500B3EF43 /* TTCSSApplyProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F5A81613B2927500B3EF43 /* TTCSSApplyProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18F5A86F13B2973F00B3EF43 /* UIView+CSSAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F5A86E13B2973F00B3EF43 /* UIView+CSSAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18F5A87813B2979E00B3EF43 /* UIView+CSSAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F5A87713B2979E00B3EF43 /* UIView+CSSAdditions.m */; }; + 18F5A88813B298BE00B3EF43 /* UILabel+CSSAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 18F5A88713B298BE00B3EF43 /* UILabel+CSSAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 18F5A88A13B298D100B3EF43 /* UILabel+CSSAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 18F5A88913B298D100B3EF43 /* UILabel+CSSAdditions.m */; }; 663DB00812661D6F00CF8CEA /* Xcode324iOS41TestSuiteWorkaround.m in Sources */ = {isa = PBXBuildFile; fileRef = 663DB00712661D6F00CF8CEA /* Xcode324iOS41TestSuiteWorkaround.m */; }; 66E722D0129392DD007134B0 /* TTExtensionLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 66E722CC129392DD007134B0 /* TTExtensionLoader.m */; }; 66E722D3129392EB007134B0 /* TTExtensionLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 66E722D1129392EB007134B0 /* TTExtensionLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -30,7 +57,6 @@ 6E036A3211B364DF0025E8EE /* TTCSSStyleSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E036A3111B364DF0025E8EE /* TTCSSStyleSheet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E036A7D11B371790025E8EE /* CssStyleSheetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E036A7711B371150025E8EE /* CssStyleSheetTests.m */; }; 6E036B6911B38DA30025E8EE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E85155511B2E94E0071A4FD /* CoreGraphics.framework */; }; - 6E036D1911B487CF0025E8EE /* TTDefaultCSSStyleSheet.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E036D1711B487CF0025E8EE /* TTDefaultCSSStyleSheet.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E036D1A11B487CF0025E8EE /* TTDefaultCSSStyleSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E036D1811B487CF0025E8EE /* TTDefaultCSSStyleSheet.m */; }; 6E3C3470118806590079637E /* extThree20CSSStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E646518118805EB00F08CB1 /* extThree20CSSStyle.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6E645AA111876E2B00F08CB1 /* libThree20Core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6E645A7011876D3F00F08CB1 /* libThree20Core.a */; }; @@ -42,17 +68,23 @@ 6E85154011B2E8660071A4FD /* TTCSSParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E85145111B1B5200071A4FD /* TTCSSParser.m */; }; 6EAE4E5611B2F0A7001073B4 /* testcase.css in Resources */ = {isa = PBXBuildFile; fileRef = 6EAE4E5511B2F0A7001073B4 /* testcase.css */; }; 6EB460DA1183D8CB00685649 /* libextThree20CSSStyle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BEF31F3A0F352DF5000DE5D2 /* libextThree20CSSStyle.a */; }; - 90C3A115132B9BE100AC06A2 /* TTCSSGlobalStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = 90C3A114132B9BE100AC06A2 /* TTCSSGlobalStyle.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 90C3A1B5132BE3EB00AC06A2 /* UILabelAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 90C3A1B3132BE3EB00AC06A2 /* UILabelAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 90C3A1B6132BE3EB00AC06A2 /* UILabelAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 90C3A1B4132BE3EB00AC06A2 /* UILabelAdditions.m */; }; - 90C3A1B8132BE40100AC06A2 /* extThree20CSSStyle+Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 90C3A1B7132BE40100AC06A2 /* extThree20CSSStyle+Additions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 90C3A1BD132BF2D100AC06A2 /* TTTextStyleAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 90C3A1BB132BF2D100AC06A2 /* TTTextStyleAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 90C3A1BE132BF2D100AC06A2 /* TTTextStyleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 90C3A1BC132BF2D100AC06A2 /* TTTextStyleAdditions.m */; }; - 90C3A1C4132BFDFF00AC06A2 /* TTShadowStyleAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 90C3A1C2132BFDFE00AC06A2 /* TTShadowStyleAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 90C3A1C5132BFDFF00AC06A2 /* TTShadowStyleAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 90C3A1C3132BFDFF00AC06A2 /* TTShadowStyleAdditions.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 1892DC1613D61D4E008DFAC5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6E036A0E11B364530025E8EE /* Three20Network.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 662D81EF12630516005851C2; + remoteInfo = "Three20Network-Xcode3.2.5"; + }; + 1892DC1813D61D4E008DFAC5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6E036A0E11B364530025E8EE /* Three20Network.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 662D81B2126304EB005851C2; + remoteInfo = "Three20NetworkUnitTests-Xcode3.2.5"; + }; 6E036A1311B364530025E8EE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6E036A0E11B364530025E8EE /* Three20Network.xcodeproj */; @@ -133,6 +165,31 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1831D1AD13AA9FAC00AB4D55 /* TTDataConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTDataConverter.h; path = Headers/TTDataConverter.h; sourceTree = ""; }; + 1831D1AE13AA9FAC00AB4D55 /* TTDataPopulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTDataPopulator.h; path = Headers/TTDataPopulator.h; sourceTree = ""; }; + 1831D1B113AA9FB500AB4D55 /* TTDataConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTDataConverter.m; path = ThirdPart/TTDataConverter.m; sourceTree = ""; }; + 1831D1B213AA9FB500AB4D55 /* TTDataPopulator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTDataPopulator.m; path = ThirdPart/TTDataPopulator.m; sourceTree = ""; }; + 1831D1D913AAA24400AB4D55 /* TTDataPopulatorDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTDataPopulatorDelegate.h; path = Headers/TTDataPopulatorDelegate.h; sourceTree = ""; }; + 1832BD9613B243FD00C50CFE /* TTDefaultCSSStyleSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTDefaultCSSStyleSheet.h; path = Headers/TTDefaultCSSStyleSheet.h; sourceTree = ""; }; + 183F67AD13B0F5AE0032CFF5 /* TTCSSFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTCSSFunctions.h; path = Headers/TTCSSFunctions.h; sourceTree = ""; }; + 183F67B213B0F5BE0032CFF5 /* TTCSSFunctions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTCSSFunctions.m; path = Sources/TTCSSFunctions.m; sourceTree = ""; }; + 186AE6F213AA3FF1004D43FA /* TTCSSRuleSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTCSSRuleSet.h; path = Headers/TTCSSRuleSet.h; sourceTree = ""; }; + 186AE75613AA4C1C004D43FA /* TTCSSRuleSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTCSSRuleSet.m; path = Sources/TTCSSRuleSet.m; sourceTree = ""; }; + 186AE80813AA512C004D43FA /* TTCSSTextShadowModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTCSSTextShadowModel.h; path = Headers/TTCSSTextShadowModel.h; sourceTree = ""; }; + 186AE80A13AA5379004D43FA /* TTCSSTextShadowModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTCSSTextShadowModel.m; path = Sources/TTCSSTextShadowModel.m; sourceTree = ""; }; + 186AE91F13AA7C7E004D43FA /* CssRuleSetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CssRuleSetTests.m; path = UnitTests/CssRuleSetTests.m; sourceTree = ""; }; + 1892DC1B13D61D5B008DFAC5 /* UILabelAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UILabelAdditions.h; path = Headers/UILabelAdditions.h; sourceTree = ""; }; + 1892DC1D13D61D6A008DFAC5 /* TTShadowStyleAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTShadowStyleAdditions.h; path = Headers/TTShadowStyleAdditions.h; sourceTree = ""; }; + 1892DC1E13D61D6A008DFAC5 /* TTTextStyleAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTTextStyleAdditions.h; path = Headers/TTTextStyleAdditions.h; sourceTree = ""; }; + 1892DC2113D61D77008DFAC5 /* TTCSSGlobalStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTCSSGlobalStyle.h; path = Headers/TTCSSGlobalStyle.h; sourceTree = ""; }; + 1892DC2313D61D81008DFAC5 /* TTShadowStyleAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTShadowStyleAdditions.m; path = Sources/TTShadowStyleAdditions.m; sourceTree = ""; }; + 1892DC2413D61D81008DFAC5 /* TTTextStyleAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTTextStyleAdditions.m; path = Sources/TTTextStyleAdditions.m; sourceTree = ""; }; + 1892DC2D13D61D90008DFAC5 /* extThree20CSSStyle+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "extThree20CSSStyle+Additions.h"; path = "Headers/extThree20CSSStyle+Additions.h"; sourceTree = ""; }; + 18F5A81613B2927500B3EF43 /* TTCSSApplyProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTCSSApplyProtocol.h; path = Headers/TTCSSApplyProtocol.h; sourceTree = ""; }; + 18F5A86E13B2973F00B3EF43 /* UIView+CSSAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIView+CSSAdditions.h"; path = "Headers/UIView+CSSAdditions.h"; sourceTree = ""; }; + 18F5A87713B2979E00B3EF43 /* UIView+CSSAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIView+CSSAdditions.m"; path = "Sources/UIView+CSSAdditions.m"; sourceTree = ""; }; + 18F5A88713B298BE00B3EF43 /* UILabel+CSSAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UILabel+CSSAdditions.h"; path = "Headers/UILabel+CSSAdditions.h"; sourceTree = ""; }; + 18F5A88913B298D100B3EF43 /* UILabel+CSSAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UILabel+CSSAdditions.m"; path = "Sources/UILabel+CSSAdditions.m"; sourceTree = ""; }; 66313D671267BFCF00C09C9F /* extThree20CSSStyle_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = extThree20CSSStyle_Prefix.pch; path = Headers/extThree20CSSStyle_Prefix.pch; sourceTree = ""; }; 663DB00712661D6F00CF8CEA /* Xcode324iOS41TestSuiteWorkaround.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Xcode324iOS41TestSuiteWorkaround.m; path = ../UnitTests/Xcode324iOS41TestSuiteWorkaround.m; sourceTree = SOURCE_ROOT; }; 66E722CC129392DD007134B0 /* TTExtensionLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTExtensionLoader.m; path = Sources/TTExtensionLoader.m; sourceTree = ""; }; @@ -144,7 +201,6 @@ 6E036A7711B371150025E8EE /* CssStyleSheetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CssStyleSheetTests.m; path = UnitTests/CssStyleSheetTests.m; sourceTree = ""; }; 6E036B3611B38A420025E8EE /* README.mdown */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.mdown; sourceTree = ""; }; 6E036B6111B38D1B0025E8EE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 6E036D1711B487CF0025E8EE /* TTDefaultCSSStyleSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTDefaultCSSStyleSheet.h; path = Sources/TTDefaultCSSStyleSheet.h; sourceTree = ""; }; 6E036D1811B487CF0025E8EE /* TTDefaultCSSStyleSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTDefaultCSSStyleSheet.m; path = Sources/TTDefaultCSSStyleSheet.m; sourceTree = ""; }; 6E0835AB11B4C3A200B99C32 /* extThree20CSSStyle.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = extThree20CSSStyle.bundle; path = Resources/extThree20CSSStyle.bundle; sourceTree = ""; }; 6E083B5311B6122800B99C32 /* Build.Command */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Build.Command; path = Grammars/Build.Command; sourceTree = ""; }; @@ -164,15 +220,6 @@ 6EAE4E5511B2F0A7001073B4 /* testcase.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; name = testcase.css; path = UnitTests/Resources/CSS/testcase.css; sourceTree = ""; }; 6EB460921183D16000685649 /* UnitTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "UnitTests-Info.plist"; path = "UnitTests/Resources/PropertyLists/UnitTests-Info.plist"; sourceTree = ""; }; 6EB460A61183D2AC00685649 /* UnitTests.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = UnitTests.xcconfig; path = Configurations/UnitTests.xcconfig; sourceTree = ""; }; - 90C3A114132B9BE100AC06A2 /* TTCSSGlobalStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTCSSGlobalStyle.h; path = Headers/TTCSSGlobalStyle.h; sourceTree = ""; }; - 90C3A1B3132BE3EB00AC06A2 /* UILabelAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UILabelAdditions.h; path = Headers/UILabelAdditions.h; sourceTree = ""; }; - 90C3A1B4132BE3EB00AC06A2 /* UILabelAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UILabelAdditions.m; path = Sources/UILabelAdditions.m; sourceTree = ""; }; - 90C3A1B7132BE40100AC06A2 /* extThree20CSSStyle+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "extThree20CSSStyle+Additions.h"; path = "Headers/extThree20CSSStyle+Additions.h"; sourceTree = ""; }; - 90C3A1B9132BEB7100AC06A2 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - 90C3A1BB132BF2D100AC06A2 /* TTTextStyleAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTTextStyleAdditions.h; path = Headers/TTTextStyleAdditions.h; sourceTree = ""; }; - 90C3A1BC132BF2D100AC06A2 /* TTTextStyleAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTTextStyleAdditions.m; path = Sources/TTTextStyleAdditions.m; sourceTree = ""; }; - 90C3A1C2132BFDFE00AC06A2 /* TTShadowStyleAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TTShadowStyleAdditions.h; path = Headers/TTShadowStyleAdditions.h; sourceTree = ""; }; - 90C3A1C3132BFDFF00AC06A2 /* TTShadowStyleAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TTShadowStyleAdditions.m; path = Sources/TTShadowStyleAdditions.m; sourceTree = ""; }; BEF31F3A0F352DF5000DE5D2 /* libextThree20CSSStyle.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libextThree20CSSStyle.a; sourceTree = BUILT_PRODUCTS_DIR; }; EB9E6C6210B6A8F800DE563C /* extCSSStyleUnitTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = extCSSStyleUnitTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -200,6 +247,56 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1831D1A913AA9F4800AB4D55 /* Data Processing */ = { + isa = PBXGroup; + children = ( + 1831D1AD13AA9FAC00AB4D55 /* TTDataConverter.h */, + 1831D1B113AA9FB500AB4D55 /* TTDataConverter.m */, + 1831D1D913AAA24400AB4D55 /* TTDataPopulatorDelegate.h */, + 1831D1AE13AA9FAC00AB4D55 /* TTDataPopulator.h */, + 1831D1B213AA9FB500AB4D55 /* TTDataPopulator.m */, + ); + name = "Data Processing"; + sourceTree = ""; + }; + 183F67AF13B0F5B10032CFF5 /* Common */ = { + isa = PBXGroup; + children = ( + 18F5A81613B2927500B3EF43 /* TTCSSApplyProtocol.h */, + 183F67AD13B0F5AE0032CFF5 /* TTCSSFunctions.h */, + 183F67B213B0F5BE0032CFF5 /* TTCSSFunctions.m */, + ); + name = Common; + sourceTree = ""; + }; + 186AE6E013AA3F97004D43FA /* CSS Model Objects */ = { + isa = PBXGroup; + children = ( + 1831D1A913AA9F4800AB4D55 /* Data Processing */, + 186AE80813AA512C004D43FA /* TTCSSTextShadowModel.h */, + 186AE80A13AA5379004D43FA /* TTCSSTextShadowModel.m */, + 186AE6F213AA3FF1004D43FA /* TTCSSRuleSet.h */, + 186AE75613AA4C1C004D43FA /* TTCSSRuleSet.m */, + 1892DC1D13D61D6A008DFAC5 /* TTShadowStyleAdditions.h */, + 1892DC2313D61D81008DFAC5 /* TTShadowStyleAdditions.m */, + 1892DC1E13D61D6A008DFAC5 /* TTTextStyleAdditions.h */, + 1892DC2413D61D81008DFAC5 /* TTTextStyleAdditions.m */, + ); + name = "CSS Model Objects"; + sourceTree = ""; + }; + 18F5A86613B2971900B3EF43 /* UIKit Additions */ = { + isa = PBXGroup; + children = ( + 18F5A86E13B2973F00B3EF43 /* UIView+CSSAdditions.h */, + 18F5A87713B2979E00B3EF43 /* UIView+CSSAdditions.m */, + 1892DC1B13D61D5B008DFAC5 /* UILabelAdditions.h */, + 18F5A88713B298BE00B3EF43 /* UILabel+CSSAdditions.h */, + 18F5A88913B298D100B3EF43 /* UILabel+CSSAdditions.m */, + ); + name = "UIKit Additions"; + sourceTree = ""; + }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( @@ -214,7 +311,7 @@ children = ( 6E036B3611B38A420025E8EE /* README.mdown */, 6E646518118805EB00F08CB1 /* extThree20CSSStyle.h */, - 90C3A1B7132BE40100AC06A2 /* extThree20CSSStyle+Additions.h */, + 1892DC2D13D61D90008DFAC5 /* extThree20CSSStyle+Additions.h */, 66313D671267BFCF00C09C9F /* extThree20CSSStyle_Prefix.pch */, 66E722D1129392EB007134B0 /* TTExtensionLoader.h */, 66E722CC129392DD007134B0 /* TTExtensionLoader.m */, @@ -241,7 +338,9 @@ isa = PBXGroup; children = ( 6E036A1411B364530025E8EE /* libThree20Network.a */, + 1892DC1713D61D4E008DFAC5 /* libThree20Network-Xcode3.2.5.a */, 6E036A1611B364530025E8EE /* NetworkUnitTests.octest */, + 1892DC1913D61D4E008DFAC5 /* NetworkUnitTests-Xcode3.2.5.octest */, ); name = Products; sourceTree = ""; @@ -268,9 +367,10 @@ 6E036A2B11B364B60025E8EE /* CSS Stylesheet */ = { isa = PBXGroup; children = ( + 1892DC2113D61D77008DFAC5 /* TTCSSGlobalStyle.h */, 6E036A3111B364DF0025E8EE /* TTCSSStyleSheet.h */, 6E036A2E11B364CC0025E8EE /* TTCSSStyleSheet.m */, - 6E036D1711B487CF0025E8EE /* TTDefaultCSSStyleSheet.h */, + 1832BD9613B243FD00C50CFE /* TTDefaultCSSStyleSheet.h */, 6E036D1811B487CF0025E8EE /* TTDefaultCSSStyleSheet.m */, ); name = "CSS Stylesheet"; @@ -290,7 +390,6 @@ 6E85154F11B2E93E0071A4FD /* Foundation.framework */, 6E85155511B2E94E0071A4FD /* CoreGraphics.framework */, 6E036B6111B38D1B0025E8EE /* UIKit.framework */, - 90C3A1B9132BEB7100AC06A2 /* QuartzCore.framework */, ); name = Frameworks; sourceTree = ""; @@ -337,8 +436,9 @@ 6EB4609C1183D1E000685649 /* Source */ = { isa = PBXGroup; children = ( - 90C3A10F132B9B5000AC06A2 /* Global */, - 90C3A1AF132BE3C800AC06A2 /* Additions */, + 18F5A86613B2971900B3EF43 /* UIKit Additions */, + 183F67AF13B0F5B10032CFF5 /* Common */, + 186AE6E013AA3F97004D43FA /* CSS Model Objects */, 6E036A2A11B364AF0025E8EE /* CSS Parser */, 6E036A2B11B364B60025E8EE /* CSS Stylesheet */, ); @@ -361,6 +461,7 @@ 663DB00612661D6F00CF8CEA /* Xcode 3.2.4 Workaround */, 6E85152511B2E7B80071A4FD /* CssParserTests.m */, 6E036A7711B371150025E8EE /* CssStyleSheetTests.m */, + 186AE91F13AA7C7E004D43FA /* CssRuleSetTests.m */, ); name = Tests; sourceTree = ""; @@ -375,27 +476,6 @@ name = Configurations; sourceTree = ""; }; - 90C3A10F132B9B5000AC06A2 /* Global */ = { - isa = PBXGroup; - children = ( - 90C3A114132B9BE100AC06A2 /* TTCSSGlobalStyle.h */, - ); - name = Global; - sourceTree = ""; - }; - 90C3A1AF132BE3C800AC06A2 /* Additions */ = { - isa = PBXGroup; - children = ( - 90C3A1B3132BE3EB00AC06A2 /* UILabelAdditions.h */, - 90C3A1B4132BE3EB00AC06A2 /* UILabelAdditions.m */, - 90C3A1BB132BF2D100AC06A2 /* TTTextStyleAdditions.h */, - 90C3A1BC132BF2D100AC06A2 /* TTTextStyleAdditions.m */, - 90C3A1C2132BFDFE00AC06A2 /* TTShadowStyleAdditions.h */, - 90C3A1C3132BFDFF00AC06A2 /* TTShadowStyleAdditions.m */, - ); - name = Additions; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -403,17 +483,26 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 1892DC2213D61D77008DFAC5 /* TTCSSGlobalStyle.h in Headers */, + 18F5A88813B298BE00B3EF43 /* UILabel+CSSAdditions.h in Headers */, + 18F5A86F13B2973F00B3EF43 /* UIView+CSSAdditions.h in Headers */, + 18F5A81713B2927500B3EF43 /* TTCSSApplyProtocol.h in Headers */, + 183F67EA13B0F8B40032CFF5 /* TTCSSFunctions.h in Headers */, + 1831D1AF13AA9FAC00AB4D55 /* TTDataConverter.h in Headers */, + 1831D1DA13AAA24400AB4D55 /* TTDataPopulatorDelegate.h in Headers */, + 1831D1B013AA9FAC00AB4D55 /* TTDataPopulator.h in Headers */, + 186AE80913AA512C004D43FA /* TTCSSTextShadowModel.h in Headers */, + 186AE75913AA4C35004D43FA /* TTCSSRuleSet.h in Headers */, + 6E036A3211B364DF0025E8EE /* TTCSSStyleSheet.h in Headers */, 6E3C3470118806590079637E /* extThree20CSSStyle.h in Headers */, - 90C3A1B8132BE40100AC06A2 /* extThree20CSSStyle+Additions.h in Headers */, - 90C3A115132B9BE100AC06A2 /* TTCSSGlobalStyle.h in Headers */, 6E85145411B1B5390071A4FD /* TTCSSParser.h in Headers */, 6E8514ED11B2E3F30071A4FD /* CssTokens.h in Headers */, - 6E036A3211B364DF0025E8EE /* TTCSSStyleSheet.h in Headers */, - 6E036D1911B487CF0025E8EE /* TTDefaultCSSStyleSheet.h in Headers */, 66E722D3129392EB007134B0 /* TTExtensionLoader.h in Headers */, - 90C3A1B5132BE3EB00AC06A2 /* UILabelAdditions.h in Headers */, - 90C3A1BD132BF2D100AC06A2 /* TTTextStyleAdditions.h in Headers */, - 90C3A1C4132BFDFF00AC06A2 /* TTShadowStyleAdditions.h in Headers */, + 1832BD9713B243FD00C50CFE /* TTDefaultCSSStyleSheet.h in Headers */, + 1892DC1C13D61D5B008DFAC5 /* UILabelAdditions.h in Headers */, + 1892DC1F13D61D6A008DFAC5 /* TTShadowStyleAdditions.h in Headers */, + 1892DC2013D61D6A008DFAC5 /* TTTextStyleAdditions.h in Headers */, + 1892DC2E13D61D90008DFAC5 /* extThree20CSSStyle+Additions.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -506,6 +595,20 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ + 1892DC1713D61D4E008DFAC5 /* libThree20Network-Xcode3.2.5.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libThree20Network-Xcode3.2.5.a"; + remoteRef = 1892DC1613D61D4E008DFAC5 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1892DC1913D61D4E008DFAC5 /* NetworkUnitTests-Xcode3.2.5.octest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "NetworkUnitTests-Xcode3.2.5.octest"; + remoteRef = 1892DC1813D61D4E008DFAC5 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 6E036A1411B364530025E8EE /* libThree20Network.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -624,15 +727,21 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 186AE75A13AA4C3A004D43FA /* TTCSSRuleSet.m in Sources */, 6E85154011B2E8660071A4FD /* TTCSSParser.m in Sources */, 6E8514DA11B2E31E0071A4FD /* CssTokenizer.m in Sources */, 6E8514DB11B2E31E0071A4FD /* CssTokens.m in Sources */, 6E036A3011B364CC0025E8EE /* TTCSSStyleSheet.m in Sources */, 6E036D1A11B487CF0025E8EE /* TTDefaultCSSStyleSheet.m in Sources */, 66E722D0129392DD007134B0 /* TTExtensionLoader.m in Sources */, - 90C3A1B6132BE3EB00AC06A2 /* UILabelAdditions.m in Sources */, - 90C3A1BE132BF2D100AC06A2 /* TTTextStyleAdditions.m in Sources */, - 90C3A1C5132BFDFF00AC06A2 /* TTShadowStyleAdditions.m in Sources */, + 186AE80B13AA5379004D43FA /* TTCSSTextShadowModel.m in Sources */, + 1831D1B313AA9FB500AB4D55 /* TTDataConverter.m in Sources */, + 1831D1B413AA9FB500AB4D55 /* TTDataPopulator.m in Sources */, + 183F67B313B0F5BE0032CFF5 /* TTCSSFunctions.m in Sources */, + 18F5A87813B2979E00B3EF43 /* UIView+CSSAdditions.m in Sources */, + 18F5A88A13B298D100B3EF43 /* UILabel+CSSAdditions.m in Sources */, + 1892DC2513D61D81008DFAC5 /* TTShadowStyleAdditions.m in Sources */, + 1892DC2613D61D81008DFAC5 /* TTTextStyleAdditions.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -643,6 +752,9 @@ 6E036A7D11B371790025E8EE /* CssStyleSheetTests.m in Sources */, 6E85152611B2E7B80071A4FD /* CssParserTests.m in Sources */, 663DB00812661D6F00CF8CEA /* Xcode324iOS41TestSuiteWorkaround.m in Sources */, + 186AE92013AA7C7E004D43FA /* CssRuleSetTests.m in Sources */, + 1892DC2713D61D81008DFAC5 /* TTShadowStyleAdditions.m in Sources */, + 1892DC2813D61D81008DFAC5 /* TTTextStyleAdditions.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/scripts/ttmodule.py b/src/scripts/ttmodule.py old mode 100644 new mode 100755