Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add source code for CoconutKit 2.0

  • Loading branch information...
commit 08436d2218fd7b89bb45af6efe375482d92e04de 1 parent 031b1be
@defagos authored
Showing with 25,881 additions and 3 deletions.
  1. +8 −0 CoconutKit-Prefix.pch
  2. BIN  CoconutKit-resources.bundle/ButtonBarArrowLeft.png
  3. BIN  CoconutKit-resources.bundle/ButtonBarArrowLeft@2x.png
  4. BIN  CoconutKit-resources.bundle/ButtonBarArrowRight.png
  5. BIN  CoconutKit-resources.bundle/ButtonBarArrowRight@2x.png
  6. BIN  CoconutKit-resources.bundle/ButtonBarRefresh.png
  7. BIN  CoconutKit-resources.bundle/ButtonBarRefresh@2x.png
  8. BIN  CoconutKit-resources.bundle/CursorDefaultPointer.png
  9. BIN  CoconutKit-resources.bundle/HLSWebViewController.nib
  10. BIN  CoconutKit-resources.bundle/Info.plist
  11. BIN  CoconutKit-resources.bundle/SearchFieldIcon.png
  12. BIN  CoconutKit-resources.bundle/SearchFieldIcon@2x.png
  13. BIN  CoconutKit-resources.bundle/de.lproj/Localizable.strings
  14. BIN  CoconutKit-resources.bundle/en.lproj/Localizable.strings
  15. BIN  CoconutKit-resources.bundle/es.lproj/Localizable.strings
  16. BIN  CoconutKit-resources.bundle/fr.lproj/Localizable.strings
  17. BIN  CoconutKit-resources.bundle/it.lproj/Localizable.strings
  18. BIN  CoconutKit-resources.bundle/ja.lproj/Localizable.strings
  19. BIN  CoconutKit-resources.bundle/ko.lproj/Localizable.strings
  20. +7 −0 LICENSE
  21. +37 −0 PublicHeaders/CALayer+HLSExtensions.h
  22. +21 −0 PublicHeaders/CAMediaTimingFunction+HLSExtensions.h
  23. +90 −0 PublicHeaders/CoconutKit.h
  24. +106 −0 PublicHeaders/HLSActionSheet.h
  25. +288 −0 PublicHeaders/HLSAnimation.h
  26. +51 −0 PublicHeaders/HLSAnimationStep.h
  27. +25 −0 PublicHeaders/HLSApplicationPreloader.h
  28. +116 −0 PublicHeaders/HLSAssert.h
  29. +46 −0 PublicHeaders/HLSAutorotation.h
  30. +464 −0 PublicHeaders/HLSContainerStack.h
  31. +50 −0 PublicHeaders/HLSConverters.h
  32. +147 −0 PublicHeaders/HLSCursor.h
  33. +64 −0 PublicHeaders/HLSError.h
  34. +98 −0 PublicHeaders/HLSExpandingSearchBar.h
  35. +57 −0 PublicHeaders/HLSFloat.h
  36. +53 −0 PublicHeaders/HLSKeyboardInformation.h
  37. +43 −0 PublicHeaders/HLSLabel.h
  38. +119 −0 PublicHeaders/HLSLayerAnimation.h
  39. +55 −0 PublicHeaders/HLSLayerAnimationStep.h
  40. +97 −0 PublicHeaders/HLSLogger.h
  41. +25 −0 PublicHeaders/HLSManagedObjectCopying.h
  42. +158 −0 PublicHeaders/HLSModelManager.h
  43. +54 −0 PublicHeaders/HLSNibView.h
  44. +128 −0 PublicHeaders/HLSNotifications.h
  45. +19 −0 PublicHeaders/HLSObjectAnimation.h
  46. +80 −0 PublicHeaders/HLSOptionalFeatures.h
  47. +55 −0 PublicHeaders/HLSPlaceholderInsetSegue.h
  48. +229 −0 PublicHeaders/HLSPlaceholderViewController.h
  49. +31 −0 PublicHeaders/HLSRuntime.h
  50. +146 −0 PublicHeaders/HLSSlideshow.h
  51. +330 −0 PublicHeaders/HLSStackController.h
  52. +50 −0 PublicHeaders/HLSStackPushSegue.h
  53. +19 −0 PublicHeaders/HLSSubtitleTableViewCell.h
  54. +84 −0 PublicHeaders/HLSTableSearchDisplayViewController.h
  55. +107 −0 PublicHeaders/HLSTableViewCell.h
  56. +140 −0 PublicHeaders/HLSTask.h
  57. +149 −0 PublicHeaders/HLSTaskGroup.h
  58. +138 −0 PublicHeaders/HLSTaskManager.h
  59. +42 −0 PublicHeaders/HLSTaskOperation+Protected.h
  60. +41 −0 PublicHeaders/HLSTaskOperation.h
  61. +69 −0 PublicHeaders/HLSTextField.h
  62. +460 −0 PublicHeaders/HLSTransition.h
  63. +28 −0 PublicHeaders/HLSUserInterfaceLock.h
  64. +20 −0 PublicHeaders/HLSValidable.h
  65. +22 −0 PublicHeaders/HLSValidators.h
  66. +19 −0 PublicHeaders/HLSValue1TableViewCell.h
  67. +19 −0 PublicHeaders/HLSValue2TableViewCell.h
  68. +38 −0 PublicHeaders/HLSVector.h
  69. +60 −0 PublicHeaders/HLSViewAnimation.h
  70. +44 −0 PublicHeaders/HLSViewAnimationStep.h
  71. +103 −0 PublicHeaders/HLSViewController.h
  72. +59 −0 PublicHeaders/HLSWebViewController.h
  73. +83 −0 PublicHeaders/HLSWizardViewController.h
  74. +29 −0 PublicHeaders/NSArray+HLSExtensions.h
  75. +70 −0 PublicHeaders/NSBundle+HLSDynamicLocalization.h
  76. +23 −0 PublicHeaders/NSBundle+HLSExtensions.h
  77. +184 −0 PublicHeaders/NSCalendar+HLSExtensions.h
  78. +51 −0 PublicHeaders/NSData+HLSExtensions.h
  79. +19 −0 PublicHeaders/NSDate+HLSExtensions.h
  80. +18 −0 PublicHeaders/NSDateFormatter+HLSExtensions.h
  81. +35 −0 PublicHeaders/NSDictionary+HLSExtensions.h
  82. +38 −0 PublicHeaders/NSError+HLSExtensions.h
  83. +87 −0 PublicHeaders/NSManagedObject+HLSExtensions.h
  84. +131 −0 PublicHeaders/NSManagedObject+HLSValidation.h
  85. +27 −0 PublicHeaders/NSObject+HLSExtensions.h
  86. +118 −0 PublicHeaders/NSString+HLSExtensions.h
  87. +77 −0 PublicHeaders/NSTimeZone+HLSExtensions.h
  88. +18 −0 PublicHeaders/UIActionSheet+HLSExtensions.h
  89. +35 −0 PublicHeaders/UIColor+HLSExtensions.h
  90. +20 −0 PublicHeaders/UIControl+HLSExclusiveTouch.h
  91. +27 −0 PublicHeaders/UIImage+HLSExtensions.h
  92. +75 −0 PublicHeaders/UILabel+HLSDynamicLocalization.h
  93. +16 −0 PublicHeaders/UINavigationBar+HLSExtensions.h
  94. +29 −0 PublicHeaders/UINavigationController+HLSExtensions.h
  95. +16 −0 PublicHeaders/UIPopoverController+HLSExtensions.h
  96. +39 −0 PublicHeaders/UIScrollView+HLSExtensions.h
  97. +28 −0 PublicHeaders/UISplitViewController+HLSExtensions.h
  98. +28 −0 PublicHeaders/UITabBarController+HLSExtensions.h
  99. +16 −0 PublicHeaders/UITextField+HLSExtensions.h
  100. +107 −0 PublicHeaders/UITextField+HLSValidation.h
  101. +16 −0 PublicHeaders/UITextView+HLSExtensions.h
  102. +16 −0 PublicHeaders/UIToolbar+HLSExtensions.h
  103. +30 −0 PublicHeaders/UIView+HLSExtensions.h
  104. +120 −0 PublicHeaders/UIViewController+HLSExtensions.h
  105. +29 −0 PublicHeaders/UIWebView+HLSExtensions.h
  106. +2 −3 README.md
  107. +623 −0 Sources/Animation/HLSAnimation.m
  108. +66 −0 Sources/Animation/HLSAnimationStep+Friend.h
  109. +112 −0 Sources/Animation/HLSAnimationStep+Protected.h
  110. +305 −0 Sources/Animation/HLSAnimationStep.m
  111. +45 −0 Sources/Animation/HLSLayerAnimation+Friend.h
  112. +352 −0 Sources/Animation/HLSLayerAnimation.m
  113. +397 −0 Sources/Animation/HLSLayerAnimationStep.m
  114. +20 −0 Sources/Animation/HLSObjectAnimation+Friend.h
  115. +36 −0 Sources/Animation/HLSObjectAnimation.m
  116. +25 −0 Sources/Animation/HLSViewAnimation+Friend.h
  117. +141 −0 Sources/Animation/HLSViewAnimation.m
  118. +203 −0 Sources/Animation/HLSViewAnimationStep.m
  119. +135 −0 Sources/Core/CALayer+HLSExtensions.m
  120. +47 −0 Sources/Core/CAMediaTimingFunction+HLSExtensions.m
  121. +172 −0 Sources/Core/HLSApplicationPreloader.m
  122. +85 −0 Sources/Core/HLSAssert.m
  123. +170 −0 Sources/Core/HLSConverters.m
  124. +129 −0 Sources/Core/HLSError.m
  125. +73 −0 Sources/Core/HLSFloat.m
  126. +107 −0 Sources/Core/HLSKeyboardInformation.m
  127. +354 −0 Sources/Core/HLSNotifications.m
  128. +36 −0 Sources/Core/HLSRuntime.m
  129. +65 −0 Sources/Core/HLSUserInterfaceLock.m
  130. +35 −0 Sources/Core/HLSValidators.m
  131. +54 −0 Sources/Core/HLSVector.m
  132. +58 −0 Sources/Core/HLSZeroingWeakRef.h
  133. +161 −0 Sources/Core/HLSZeroingWeakRef.m
  134. +60 −0 Sources/Core/NSArray+HLSExtensions.m
  135. +242 −0 Sources/Core/NSBundle+HLSDynamicLocalization.m
  136. +35 −0 Sources/Core/NSBundle+HLSExtensions.m
  137. +470 −0 Sources/Core/NSCalendar+HLSExtensions.m
  138. +72 −0 Sources/Core/NSData+HLSExtensions.m
  139. +74 −0 Sources/Core/NSDate+HLSExtensions.m
  140. +41 −0 Sources/Core/NSDateFormatter+HLSExtensions.m
  141. +46 −0 Sources/Core/NSDictionary+HLSExtensions.m
  142. +64 −0 Sources/Core/NSError+HLSExtensions.m
  143. +21 −0 Sources/Core/NSMutableArray+HLSExtensions.h
  144. +27 −0 Sources/Core/NSMutableArray+HLSExtensions.m
  145. +47 −0 Sources/Core/NSObject+HLSExtensions.m
  146. +16 −0 Sources/Core/NSSet+HLSExtensions.h
  147. +19 −0 Sources/Core/NSSet+HLSExtensions.m
  148. +165 −0 Sources/Core/NSString+HLSExtensions.m
  149. +83 −0 Sources/Core/NSTimeZone+HLSExtensions.m
  150. +13 −0 Sources/Core/NSURLRequest+HLSExtensions.h
  151. +41 −0 Sources/Core/NSURLRequest+HLSExtensions.m
  152. +68 −0 Sources/Core/UIColor+HLSExtensions.m
  153. +63 −0 Sources/Core/UIControl+HLSExclusiveTouch.m
  154. +58 −0 Sources/Core/UIImage+HLSExtensions.m
  155. +58 −0 Sources/CoreData/HLSManagedTextFieldValidator.h
  156. +255 −0 Sources/CoreData/HLSManagedTextFieldValidator.m
  157. +358 −0 Sources/CoreData/HLSModelManager.m
  158. +214 −0 Sources/CoreData/NSManagedObject+HLSExtensions.m
  159. +519 −0 Sources/CoreData/NSManagedObject+HLSValidation.m
  160. +171 −0 Sources/Logging/HLSLogger.m
  161. +40 −0 Sources/Task/HLSTask+Friend.h
  162. +190 −0 Sources/Task/HLSTask.m
  163. +45 −0 Sources/Task/HLSTaskGroup+Friend.h
  164. +370 −0 Sources/Task/HLSTaskGroup.m
  165. +28 −0 Sources/Task/HLSTaskManager+Friend.h
  166. +559 −0 Sources/Task/HLSTaskManager.m
  167. +293 −0 Sources/Task/HLSTaskOperation.m
  168. +27 −0 Sources/View/HLSActionSheet+Friend.h
  169. +246 −0 Sources/View/HLSActionSheet.m
  170. +598 −0 Sources/View/HLSCursor.m
  171. +481 −0 Sources/View/HLSExpandingSearchBar.m
  172. +93 −0 Sources/View/HLSLabel.m
  173. +62 −0 Sources/View/HLSLabelLocalizationInfo.h
  174. +276 −0 Sources/View/HLSLabelLocalizationInfo.m
  175. +91 −0 Sources/View/HLSNibView.m
  176. +857 −0 Sources/View/HLSSlideshow.m
  177. +20 −0 Sources/View/HLSSubtitleTableViewCell.m
  178. +17 −0 Sources/View/HLSTableViewCell+Protected.h
  179. +165 −0 Sources/View/HLSTableViewCell.m
  180. +390 −0 Sources/View/HLSTextField.m
  181. +37 −0 Sources/View/HLSTextFieldInternalDelegate.h
  182. +137 −0 Sources/View/HLSTextFieldInternalDelegate.m
  183. +31 −0 Sources/View/HLSTextFieldTouchDetector.h
  184. +75 −0 Sources/View/HLSTextFieldTouchDetector.m
  185. +20 −0 Sources/View/HLSValue1TableViewCell.m
  186. +20 −0 Sources/View/HLSValue2TableViewCell.m
  187. +105 −0 Sources/View/UIActionSheet+HLSExtensions.m
  188. +20 −0 Sources/View/UIBarButtonItem+HLSActionSheet.h
  189. +84 −0 Sources/View/UIBarButtonItem+HLSActionSheet.m
  190. +263 −0 Sources/View/UILabel+HLSDynamicLocalization.m
  191. +132 −0 Sources/View/UINavigationBar+HLSExtensions.m
  192. +16 −0 Sources/View/UINavigationController+HLSActionSheet.h
  193. +41 −0 Sources/View/UINavigationController+HLSActionSheet.m
  194. +145 −0 Sources/View/UIScrollView+HLSExtensions.m
  195. +58 −0 Sources/View/UITextField+HLSExtensions.m
  196. +219 −0 Sources/View/UITextField+HLSValidation.m
  197. +65 −0 Sources/View/UITextView+HLSExtensions.m
  198. +62 −0 Sources/View/UIToolbar+HLSExtensions.m
  199. +47 −0 Sources/View/UIView+HLSExtensions.m
  200. +98 −0 Sources/View/UIWebView+HLSExtensions.m
  201. +28 −0 Sources/ViewControllers/HLSAutorotationCompatibility.h
  202. +179 −0 Sources/ViewControllers/HLSContainerContent.h
  203. +592 −0 Sources/ViewControllers/HLSContainerContent.m
  204. +58 −0 Sources/ViewControllers/HLSContainerGroupView.h
  205. +122 −0 Sources/ViewControllers/HLSContainerGroupView.m
  206. +1,213 −0 Sources/ViewControllers/HLSContainerStack.m
  207. +146 −0 Sources/ViewControllers/HLSContainerStackView.h
  208. +149 −0 Sources/ViewControllers/HLSContainerStackView.m
  209. +81 −0 Sources/ViewControllers/HLSPlaceholderInsetSegue.m
  210. +437 −0 Sources/ViewControllers/HLSPlaceholderViewController.m
  211. +449 −0 Sources/ViewControllers/HLSStackController.m
  212. +76 −0 Sources/ViewControllers/HLSStackPushSegue.m
  213. +208 −0 Sources/ViewControllers/HLSTableSearchDisplayViewController.m
  214. +1,425 −0 Sources/ViewControllers/HLSTransition.m
  215. +224 −0 Sources/ViewControllers/HLSViewController.m
Sorry, we could not display the entire diff because it was too big.
View
8 CoconutKit-Prefix.pch
@@ -0,0 +1,8 @@
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+ #import <CoreData/CoreData.h>
+ #import <CoreGraphics/CoreGraphics.h>
+ #import <QuartzCore/QuartzCore.h>
+ #import <UIKit/UIKit.h>
+ #import <MessageUI/MessageUI.h>
+#endif
View
BIN  CoconutKit-resources.bundle/ButtonBarArrowLeft.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/ButtonBarArrowLeft@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/ButtonBarArrowRight.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/ButtonBarArrowRight@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/ButtonBarRefresh.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/ButtonBarRefresh@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/CursorDefaultPointer.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/HLSWebViewController.nib
Binary file not shown
View
BIN  CoconutKit-resources.bundle/Info.plist
Binary file not shown
View
BIN  CoconutKit-resources.bundle/SearchFieldIcon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/SearchFieldIcon@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  CoconutKit-resources.bundle/de.lproj/Localizable.strings
Binary file not shown
View
BIN  CoconutKit-resources.bundle/en.lproj/Localizable.strings
Binary file not shown
View
BIN  CoconutKit-resources.bundle/es.lproj/Localizable.strings
Binary file not shown
View
BIN  CoconutKit-resources.bundle/fr.lproj/Localizable.strings
Binary file not shown
View
BIN  CoconutKit-resources.bundle/it.lproj/Localizable.strings
Binary file not shown
View
BIN  CoconutKit-resources.bundle/ja.lproj/Localizable.strings
Binary file not shown
View
BIN  CoconutKit-resources.bundle/ko.lproj/Localizable.strings
Binary file not shown
View
7 LICENSE
@@ -0,0 +1,7 @@
+Copyright (c) 2011-2012 hortis le studio, Samuel Défago
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
37 PublicHeaders/CALayer+HLSExtensions.h
@@ -0,0 +1,37 @@
+//
+// CALayer+HLSExtensions.h
+// CoconutKit
+//
+// Created by Samuel Défago on 8/23/12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+@interface CALayer (HLSExtensions)
+
+/**
+ * This method removes all animations added to a CALayer and to all layers in its sublayer hierarchy
+ * (the usual -removeAllAnimations only removes the animations attached to a layer, not to its sublayers)
+ */
+- (void)removeAllAnimationsRecursively;
+
+/**
+ * Pause all animations attached to a layer. Does nothing if the layer was already paused
+ */
+- (void)pauseAllAnimations;
+
+/**
+ * Resume animations attached to a layer. Does nothing if the layer was not paused
+ */
+- (void)resumeAllAnimations;
+
+/**
+ * Return YES iff layer animations have been paused
+ */
+- (BOOL)isPaused;
+
+/**
+ * Return the layer and all its sublayers flattened as a UIImage
+ */
+- (UIImage *)flattenedImage;
+
+@end
View
21 PublicHeaders/CAMediaTimingFunction+HLSExtensions.h
@@ -0,0 +1,21 @@
+//
+// CAMediaTimingFunction+HLSExtensions.h
+// CoconutKit
+//
+// Created by Samuel Défago on 8/23/12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+@interface CAMediaTimingFunction (HLSExtensions)
+
+/**
+ * Return the inverse function, i.e. the one which must be played when playing an animation backwards
+ */
+- (CAMediaTimingFunction *)inverseFunction;
+
+/**
+ * Return the control points as a human-readable string
+ */
+- (NSString *)controlPointsString;
+
+@end
View
90 PublicHeaders/CoconutKit.h
@@ -0,0 +1,90 @@
+ #import <Foundation/Foundation.h>
+ #import <CoreData/CoreData.h>
+ #import <CoreGraphics/CoreGraphics.h>
+ #import <QuartzCore/QuartzCore.h>
+ #import <UIKit/UIKit.h>
+ #import <MessageUI/MessageUI.h>
+#import "CALayer+HLSExtensions.h"
+#import "CAMediaTimingFunction+HLSExtensions.h"
+#import "HLSActionSheet.h"
+#import "HLSAnimation.h"
+#import "HLSAnimationStep.h"
+#import "HLSApplicationPreloader.h"
+#import "HLSAssert.h"
+#import "HLSAutorotation.h"
+#import "HLSContainerStack.h"
+#import "HLSConverters.h"
+#import "HLSCursor.h"
+#import "HLSError.h"
+#import "HLSExpandingSearchBar.h"
+#import "HLSFloat.h"
+#import "HLSKeyboardInformation.h"
+#import "HLSLabel.h"
+#import "HLSLayerAnimation.h"
+#import "HLSLayerAnimationStep.h"
+#import "HLSLogger.h"
+#import "HLSManagedObjectCopying.h"
+#import "HLSModelManager.h"
+#import "HLSNibView.h"
+#import "HLSNotifications.h"
+#import "HLSObjectAnimation.h"
+#import "HLSOptionalFeatures.h"
+#import "HLSPlaceholderInsetSegue.h"
+#import "HLSPlaceholderViewController.h"
+#import "HLSRuntime.h"
+#import "HLSSlideshow.h"
+#import "HLSStackController.h"
+#import "HLSStackPushSegue.h"
+#import "HLSSubtitleTableViewCell.h"
+#import "HLSTableSearchDisplayViewController.h"
+#import "HLSTableViewCell.h"
+#import "HLSTask.h"
+#import "HLSTaskGroup.h"
+#import "HLSTaskManager.h"
+#import "HLSTaskOperation.h"
+#import "HLSTaskOperation+Protected.h"
+#import "HLSTextField.h"
+#import "HLSTransition.h"
+#import "HLSUserInterfaceLock.h"
+#import "HLSValidable.h"
+#import "HLSValidators.h"
+#import "HLSValue1TableViewCell.h"
+#import "HLSValue2TableViewCell.h"
+#import "HLSVector.h"
+#import "HLSViewAnimation.h"
+#import "HLSViewAnimationStep.h"
+#import "HLSViewController.h"
+#import "HLSWebViewController.h"
+#import "HLSWizardViewController.h"
+#import "NSArray+HLSExtensions.h"
+#import "NSBundle+HLSExtensions.h"
+#import "NSBundle+HLSDynamicLocalization.h"
+#import "NSCalendar+HLSExtensions.h"
+#import "NSData+HLSExtensions.h"
+#import "NSDate+HLSExtensions.h"
+#import "NSDateFormatter+HLSExtensions.h"
+#import "NSDictionary+HLSExtensions.h"
+#import "NSError+HLSExtensions.h"
+#import "NSManagedObject+HLSExtensions.h"
+#import "NSManagedObject+HLSValidation.h"
+#import "NSObject+HLSExtensions.h"
+#import "NSString+HLSExtensions.h"
+#import "NSTimeZone+HLSExtensions.h"
+#import "UIActionSheet+HLSExtensions.h"
+#import "UIColor+HLSExtensions.h"
+#import "UIControl+HLSExclusiveTouch.h"
+#import "UIImage+HLSExtensions.h"
+#import "UILabel+HLSDynamicLocalization.h"
+#import "UINavigationBar+HLSExtensions.h"
+#import "UINavigationController+HLSExtensions.h"
+#import "UIPopoverController+HLSExtensions.h"
+#import "UIScrollView+HLSExtensions.h"
+#import "UISplitViewController+HLSExtensions.h"
+#import "UITabBarController+HLSExtensions.h"
+#import "UITextField+HLSExtensions.h"
+#import "UITextField+HLSValidation.h"
+#import "UITextView+HLSExtensions.h"
+#import "UIToolbar+HLSExtensions.h"
+#import "UIView+HLSExtensions.h"
+#import "UIViewController+HLSExtensions.h"
+#import "UIWebView+HLSExtensions.h"
View
106 PublicHeaders/HLSActionSheet.h
@@ -0,0 +1,106 @@
+//
+// HLSActionSheet.h
+// CoconutKit
+//
+// Created by Samuel Défago on 24.08.11.
+// Copyright 2011 Hortis. All rights reserved.
+//
+
+/**
+ * The built-in UIActionSheet is rather inconvenient when action buttons are enabled or not depending on
+ * some context. Imagine for example a menu letting you take a picture using the camera, or choose one
+ * from your library. If either one is unavailable for some reason, the corresponding option should not
+ * be displayed in the menu. In such cases it is rather inconvenient for the delegate to implement the
+ * -actionSheet:clickedButtonAtIndex: protocol method, since the index it receives does not always correspond
+ * to the same action depending on which actions buttons were actually available.
+ *
+ * Moreover, UIActionSheet has a strange behavior on the iPad: When an action sheet is shown, it usually
+ * can be dismissed when the user taps outside it. The only exception is when the action sheet is shown
+ * from a bar button item: In such cases, all toolbar buttons (in the same toolbar) remain active, including
+ * of course the one which shows the action sheet. Tapping outside an action sheet therefore does not
+ * dismiss it if the tap occurs in the same toolbar which the button showing it belongs to. In such cases,
+ * additional code has to be written by clients so that the behavior stays correct, which means:
+ * - avoiding the user to be able to stack up action sheets by repeatedly tapping the same bar button item
+ * - tapping a bar button while another one is displaying an action sheet must dismiss the action sheet
+ * - dismissing the action sheet when navigating back in a navigation controller
+ *
+ * The HLSActionSheet class solves all the above issues. When creating an action sheet, you add buttons to
+ * it, attaching targets and actions as you would for a button. This makes it easy to keep your code well
+ * organized. Moreover, correct behavior with bar buttons is ensured.
+ *
+ * To create and display an HLSActionSheet object, proceed as follows:
+ * - initialize the object using the -init method (the designated intializer inherited from
+ * UIActionSheet cannot be used anymore)
+ * - further customize the action sheet using the properties inherited from UIActionSheet (if
+ * needed). The destructiveButtonIndex and cancelButtonIndex properties have been overridden
+ * and do nothing anymore
+ * - add the buttons in the order you want them displayed on screen, using the add... methods
+ * Then display the HLSActionSheet using the -show... methods inherited from UIActionSheet.
+ *
+ * Wherever you used a UIActionSheet, you can replace it with an HLSActionSheet with little effort.
+ * HLSActionSheet is not strictly a drop-in replacement for UIActionSheet, but almost. In general,
+ * all you have to do is replacing the
+ * -initWithTitle:delegate:cancelButtonTitle:destructiveButtonTitle:otherButtonTitles:
+ * call used to initialize a UIActionSheet with a call to init, followed by calls to the three
+ * add methods of HLSActionSheet.
+ *
+ * Remarks:
+ * - You can still have a delegate if you want. It will catch the exact same events as if you had used
+ * a built-in UIActionSheet. This is useful for menus letting you choose a value from a set of elements
+ * (e.g. a set of languages given by the system)
+ * - iPad: If you tap outside the pop-up, the protocol methods
+ * -actionSheet:clickedButtonAtIndex:
+ * -actionSheet:willDismissWithButtonIndex:
+ * -actionSheet:didDismissWithButtonIndex:
+ * are called, each one receiving -1 as button index. This is the same as for UIActionSheet, but I
+ * found it useful to have it documented somewhere.
+ *
+ * Designated initializer: -init
+ */
+@interface HLSActionSheet : UIActionSheet {
+@private
+ NSArray *m_targets;
+ NSArray *m_actions;
+ id<UIActionSheetDelegate> m_realDelegate;
+}
+
+/**
+ * Add a standard button at the end of the current button list, with a specific target and action.
+ * The index of the added button is returned. Target and option are optional.
+ * Only one such button can be added, the function returns the index of the existing one if called
+ * more than once.
+ *
+ * The signature of action must be - (void)methodName:(id)sender (sender is the action sheet)
+ * or - (void)methodName
+ *
+ * This method does nothing on the iPad
+ */
+- (NSInteger)addCancelButtonWithTitle:(NSString *)cancelButtonTitle
+ target:(id)target
+ action:(SEL)action;
+
+/**
+ * Add a destructive button at the end of the current button list, with a specific target and action.
+ * The index of the added button is returned. Target and option are optional.
+ * Only one such button can be added, the function returns the index of the existing one if called
+ * more than once.
+ *
+ * The signature of action must be - (void)methodName:(id)sender (sender is the action sheet)
+ * or - (void)methodName
+ */
+- (NSInteger)addDestructiveButtonWithTitle:(NSString *)destructiveButtonTitle
+ target:(id)target
+ action:(SEL)action;
+
+/**
+ * Add a standard button at the end of the current button list, with a specific target and action.
+ * The index of the added button is returned. Target and option are optional.
+ *
+ * The signature of action must be - (void)methodName:(id)sender (sender is the action sheet)
+ * or - (void)methodName
+ */
+- (NSInteger)addButtonWithTitle:(NSString *)title
+ target:(id)target
+ action:(SEL)action;
+
+@end
View
288 PublicHeaders/HLSAnimation.h
@@ -0,0 +1,288 @@
+//
+// HLSAnimation.h
+// CoconutKit
+//
+// Created by Samuel Défago on 2/8/11.
+// Copyright 2011 Hortis. All rights reserved.
+//
+
+#import "HLSAnimationStep.h"
+
+// Forward declarations
+@class HLSZeroingWeakRef;
+@protocol HLSAnimationDelegate;
+
+/**
+ * HLSAnimation is the simplest way to create and manage complex animations made of Core Animation-based layer
+ * and / or UIView-based animations. Usually, creating complex animations made of several steps requires the
+ * implementation of delegate methods, where animations are glued together. This makes your code ugly and difficult
+ * to maintain. Moreover, it is painful to create a reverse animation (e.g. when toggling a menu), to pause
+ * and cancel animations properly, or to play such animations instantaneously to restore some view state.
+ *
+ * To eliminate all those issues and provide a convenient way to create animations for your applications, HLSAnimations
+ * are defined in a declarative way when instantiated, can be stored, replayed, reversed, cancelled, paused, played
+ * instantaneously, slowed down in the iOS simulator, and more. Implementing and tweaking animations has never been
+ * easier and fun!
+ *
+ * An animation (HLSAnimation) is a collection of animation steps (HLSAnimationStep), each representing collective
+ * changes applied to sets of views or layers during some time interval. An HLSAnimation object simply chains those
+ * changes together to play a complete animation. An HLSAnimation can be made of view-based animation steps
+ * (HLSViewAnimationStep) or layer-based animation steps (HLSLayerAnimationStep). You can mix both types of animation
+ * steps within the same animation, but you must not alter a view involved both in a view and in a layer animation steps,
+ * otherwise the behavior is undefined. In general, you should use HLSLayerAnimationSteps most of the time, except if
+ * you want to animate a view whose contents must resize appropriately (in which case you must use an HLSViewAnimationStep)
+ *
+ * Unlike UIView animation blocks, the animation delegate is not retained. This safety measure is not needed since
+ * an HLSAnimation is automatically cancelled if it has a delegate and this delegate is deallocated. This eliminates
+ * the need to cancel the animation manually when the delegate is destroyed (except, of course, if no delegate has
+ * been defined)
+ *
+ * Animations can be played animated or not (yeah, that sounds weird, but I called it that way :-) ). When played
+ * non-animated, an animation reaches its end state instantaneously. This is a perfect way to replay an animation
+ * when rebuilding a view which has been unloaded (typically after a view controller received a memory warning
+ * notification on iOS 4 & 5. Note that views are not unloaded anymore since iOS 6)
+ *
+ * Running animations (this includes animations which have been paused) are automatically paused and resumed (if they
+ * were running before) when the application enters, respectively exits background. Note that this mechanism works
+ * perfectly within the iOS simulator and on the device, though views will appear to "jump" on the device (not within
+ * the simulator). This is not a bug and has no negative effect on the animation behavior (in particular, delegate
+ * methods are still called correctly), but is a consequence of the application screenshot which is displayed when
+ * the application exits background. The screenshot made when the application enters background namely reflects the
+ * non-animated view / layer state, which explains why the views seem to jump.
+ *
+ * Delegate methods can be implemented by clients to catch animation events. An animated boolean value is received
+ * in each of them, corresponding to how the play method was called. For steps whose duration is 0, the boolean is
+ * also YES if the animation was run with animated = YES (even though the step was not actually animated, it is still
+ * part of an animation which was played animated).
+ *
+ * Designated initializer: -initWithAnimationSteps:
+ */
+@interface HLSAnimation : NSObject <NSCopying> {
+@private
+ NSArray *m_animationSteps; // a copy of the HLSAnimationSteps passed at initialization time
+ NSArray *m_animationStepCopies; // another copy made temporarily during animation
+ NSEnumerator *m_animationStepsEnumerator; // enumerator over steps
+ HLSAnimationStep *m_currentAnimationStep; // the currently played animation step
+ NSString *m_tag;
+ NSDictionary *m_userInfo;
+ BOOL m_lockingUI;
+ BOOL m_animated;
+ NSUInteger m_repeatCount;
+ NSUInteger m_currentRepeatCount;
+ NSTimeInterval m_remainingTimeBeforeStart; // the time remaining before the start time is reached
+ NSTimeInterval m_elapsedTime; // the currently elapsed time (does not include pauses)
+ BOOL m_pausedBeforeEnteringBackground; // was the animation paused before the application entered background?
+ BOOL m_running;
+ BOOL m_playing;
+ BOOL m_started;
+ BOOL m_cancelling;
+ BOOL m_terminating;
+ HLSZeroingWeakRef *m_delegateZeroingWeakRef;
+}
+
+/**
+ * Convenience constructor for creating an animation from HLSAnimationStep objects. Providing nil creates an empty
+ * animation
+ */
++ (HLSAnimation *)animationWithAnimationSteps:(NSArray *)animationSteps;
++ (HLSAnimation *)animationWithAnimationStep:(HLSAnimationStep *)animationStep;
+
+/**
+ * Create an animation using HLSAnimationStep objects. Those steps will be chained together when the animation
+ * is played. If nil is provided, an empty animation is created (such animations still fire -animationWillStart:animated:
+ * and -animationDidStop:animated: events when played)
+ *
+ * A deep copy of the animation steps is performed to prevent further changes once the steps have been assigned to an
+ * animation
+ */
+- (id)initWithAnimationSteps:(NSArray *)animationSteps;
+
+/**
+ * Tag which can optionally be used to help identifying an animation
+ */
+@property (nonatomic, retain) NSString *tag;
+
+/**
+ * Dictionary which can be freely used to convey additional information
+ */
+@property (nonatomic, retain) NSDictionary *userInfo;
+
+/**
+ * If set to YES, the user interface interaction is blocked during the time the animation is running (see
+ * the running property documentation for more information about what "running" actually means)
+ *
+ * Default is NO
+ */
+@property (nonatomic, assign) BOOL lockingUI;
+
+/**
+ * The animation delegate. Note that the animation is automatically cancelled if a delegate has been set
+ * and gets deallocated while the animation is runnning
+ */
+@property (nonatomic, assign) id<HLSAnimationDelegate> delegate;
+
+/**
+ * Play the animation. If animated is set to NO, the end state of the animation is reached instantaneously (i.e. the
+ * animation does take place synchronously at the location of the call to this method)
+ */
+- (void)playAnimated:(BOOL)animated;
+
+/**
+ * Play the animation with animated = YES, but after some delay given in seconds (invalid negative delays are fixed
+ * to 0)
+ */
+- (void)playAfterDelay:(NSTimeInterval)delay;
+
+/**
+ * Play the animation some number of times (repeatCount must be different from 0). If repeatCount = NSUIntegerMax,
+ * the animation is repeated forever (in such cases, animated must be YES)
+ *
+ * If animated is set to NO, the end state of the animation is reached instantaneously (i.e. the
+ * animation does take place synchronously at the location of the call to this method)
+ *
+ * The -animationWillStart:animated: and -animationDidStop:animated delegate methods will be respectively
+ * called once at the start and at the end of the whole animation
+ */
+- (void)playWithRepeatCount:(NSUInteger)repeatCount animated:(BOOL)animated;
+
+/**
+ * Play the animation some number of times (repeatCount must be different from 0) after some delay, with
+ * animated = YES. If repeatCount = NSUIntegerMax, the animation is repeated forever
+ *
+ * The -animationWillStart:animated: and -animationDidStop:animated: delegate methods will be respectively
+ * called once at the start and at the end of the whole animation
+ */
+- (void)playWithRepeatCount:(NSUInteger)repeatCount afterDelay:(NSTimeInterval)delay;
+
+/**
+ * Play part of an animation, starting at startTime (if 0, the animation starts at the beginning), with
+ * animated = YES. The delegate events which would have been triggered prior to startTime are not received
+ *
+ * Remark: Core Animation steps support arbitrary start times. For UIView-based animation steps, the animation
+ * starts at the end of the step which startTime belongs to
+ */
+- (void)playWithStartTime:(NSTimeInterval)startTime;
+
+/**
+ * Play part of an animation, starting at startTime (if 0, the animation starts at the beginning) and repeating
+ * it at the end, with animated = YES. If repeatCount = NSUIntegerMax, the animation is repeated forever. The
+ * delegate events which would have occurred prior to startTime are not received
+ *
+ * Remark: Core Animation steps support arbitrary start times. For UIView-based animation steps, the animation
+ * starts at the end of the step which startTime belongs to
+ */
+- (void)playWithStartTime:(NSTimeInterval)startTime repeatCount:(NSUInteger)repeatCount;
+
+/**
+ * Pause an animation being played animated (does nothing if the animation is not running or not animated). This
+ * method can also be used to pause an animation during its initial delay period
+ */
+- (void)pause;
+
+/**
+ * Resume a paused animation (does nothing if the animation has not been paused)
+ */
+- (void)resume;
+
+/**
+ * Cancel the animation. The animation immediately reaches its end state. The delegate does not receive subsequent
+ * events
+ */
+- (void)cancel;
+
+/**
+ * Terminate the animation. The animation immediately reaches its end state. The delegate still receives all
+ * subsequent events, but with animated = NO
+ */
+- (void)terminate;
+
+/**
+ * Return the total duration of the animation. This does not include delays or repeat count multiplicators which
+ * are not intrinsic properties of an animation, but rather specified when the animation is played
+ */
+@property (nonatomic, readonly, assign) NSTimeInterval duration;
+
+/**
+ * Return YES while the animation is running. An animation is considered running from the call to a play method until
+ * right after -animationDidStop:animated: has been called. Note that this property also returns YES even when the
+ * animation has been paused or is being terminated / cancelled
+ */
+@property (nonatomic, readonly, assign, getter=isRunning) BOOL running;
+
+/**
+ * Return YES while the animation is being played. An animation is considered being played from the time a play
+ * method has been called, and until right before -animationDidStop:animated: is called. Note that this property
+ * also returns YES even when the animation has been paused or is being terminated / cancelled
+ */
+@property (nonatomic, readonly, assign, getter=isPlaying) BOOL playing;
+
+/**
+ * Return YES while the animation is started. An animation is considered started right after -animationWillStart:animated:
+ * has been called, and until right before -animationDidStop:animated: is called. Note that this property also returns YES
+ * even if the animation was played with animated = NO, has been paused, terminated or cancelled
+ */
+@property (nonatomic, readonly, assign, getter=isStarted) BOOL started;
+
+/**
+ * Return YES iff the animation has been paused
+ */
+@property (nonatomic, readonly, assign, getter=isPaused) BOOL paused;
+
+/**
+ * Return YES iff the animation is being cancelled (i.e. from the time -cancel is called until after -animationDidStop:animated:
+ * has been called)
+ */
+@property (nonatomic, readonly, assign, getter=isCancelling) BOOL cancelling;
+
+/**
+ * Return YES iff the animation is being terminated (i.e. from the time -terminate is called until after -animationDidStop:animated:
+ * has been called)
+ */
+@property (nonatomic, readonly, assign, getter=isTerminating) BOOL terminating;
+
+/**
+ * Generate a copy of the animation, but overrides its total duration with a new one. The original appearance of
+ * the animation is preserved (it is only faster or slower depending on the new duration). If an invalid negative
+ * duration is provided, the method returns nil
+ */
+- (HLSAnimation *)animationWithDuration:(NSTimeInterval)duration;
+
+/**
+ * Generate the reverse animation; all attributes are copied as is, except that all tags for the animation and
+ * animation steps get and additional "reverse_" prefix. If a tag has not been filled for the receiver, the
+ * corresponding tag of the reverse animation is nil
+ */
+- (HLSAnimation *)reverseAnimation;
+
+/**
+ * Generate the corresponding loop animation by concatening self with its reverse animation. All attributes are
+ * copied as is, except that all tags for the animation and animation steps get and additional "loop_" prefix
+ * (reverse animation steps therefore begin with a "loop_reverse_" prefix). If a tag has not been filled for
+ * the receiver, the corresponding tag of the reverse animation is nil
+ */
+- (HLSAnimation *)loopAnimation;
+
+@end
+
+@protocol HLSAnimationDelegate <NSObject>
+@optional
+
+/**
+ * Called right before the first animation step is executed, but after any delay which might have been set
+ */
+- (void)animationWillStart:(HLSAnimation *)animation animated:(BOOL)animated;
+
+/**
+ * Called right after the last animation step has been executed. You can check -terminating or -cancelling
+ * to find if the animation ended normally
+ */
+- (void)animationDidStop:(HLSAnimation *)animation animated:(BOOL)animated;
+
+/**
+ * Called when a step has been executed. Since animation steps are deeply copied when assigned to an animation,
+ * you must not use animation step pointers to identify animation steps when implementing this method. Use
+ * animation step tags instead
+ */
+- (void)animation:(HLSAnimation *)animation didFinishStep:(HLSAnimationStep *)animationStep animated:(BOOL)animated;
+
+@end
View
51 PublicHeaders/HLSAnimationStep.h
@@ -0,0 +1,51 @@
+//
+// HLSAnimationStep.h
+// CoconutKit
+//
+// Created by Samuel Défago on 8/21/12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+// Forward declarations
+@protocol HLSAnimationStepDelegate;
+
+/**
+ * Abstract base class for animation steps. Do not instantiate directly
+ *
+ * Designated initializer: -init
+ */
+@interface HLSAnimationStep : NSObject <NSCopying> {
+@private
+ NSMutableArray *m_objectKeys;
+ NSMutableDictionary *m_objectToObjectAnimationMap;
+ NSString *m_tag;
+ NSDictionary *m_userInfo;
+ NSTimeInterval m_duration;
+ id<HLSAnimationStepDelegate> m_delegate;
+ BOOL m_terminating;
+}
+
+/**
+ * Convenience constructor for an animation step with default settings and nothing to animate
+ */
++ (id)animationStep;
+
+/**
+ * Optional tag to help identifying animation steps
+ */
+@property (nonatomic, retain) NSString *tag;
+
+/**
+ * Dictionary which can be freely used to convey additional information
+ */
+@property (nonatomic, retain) NSDictionary *userInfo;
+
+/**
+ * Animation duration. Unlike UIView animation blocks, the duration of an animation step is never reduced
+ * to 0 if no view is altered by the animation step
+ *
+ * Default value is 0.2
+ */
+@property (nonatomic, assign) NSTimeInterval duration;
+
+@end
View
25 PublicHeaders/HLSApplicationPreloader.h
@@ -0,0 +1,25 @@
+//
+// HLSApplicationPreloader.h
+// CoconutKit
+//
+// Created by Samuel Défago on 02.07.12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+/**
+ * Collects the code which can be executed right after an application has started so that perceived performance can be
+ * increased. For the moment only UIWebView is preloaded so that the time usually required when instantiating the first
+ * web view is reduced
+ */
+@interface HLSApplicationPreloader : NSObject <UIWebViewDelegate> {
+@private
+ UIApplication *_application;
+}
+
+/**
+ * Call this method as soon as possible if you want to enable preloading. For simplicity you should use the
+ * HLSEnableApplicationPreloading convenience macro instead (see HLSOptionalFeatures.h)
+ */
++ (void)enable;
+
+@end
View
116 PublicHeaders/HLSAssert.h
@@ -0,0 +1,116 @@
+//
+// HLSAssert.h
+// CoconutKit
+//
+// Created by Samuel Défago on 7/14/10.
+// Copyright 2010 Hortis. All rights reserved.
+//
+
+/**
+ * The following macros are only active if NS_BLOCK_ASSERTIONS is disabled for the project configuration you use
+ * (usually -DNS_BLOCK_ASSERTIONS=1)
+ */
+#ifndef NS_BLOCK_ASSERTIONS
+
+/**
+ * Assertion at compile time
+ *
+ * Remark: Using a typedef avoids "unused variable" warnings, and enclosing within a block avoids "type redefinition" errors
+ */
+#define HLSStaticAssert(expr) {typedef char static_assertion_failure[(expr) ? 1 : -1];}
+
+/**
+ * Insert this macro in the implementation of a method which is inherited but does not have any meaning for the class
+ * you are implementing. This can e.g. be helpful to disable the init NSObject inherited method (which sometimes is
+ * not meaningful)
+ */
+#define HLSForbiddenInheritedMethod() NSAssert(NO, @"Forbidden inherited method call. This method has " \
+ "been inherited from a parent class but could not " \
+ "be meaningfully overridden. It cannot therefore " \
+ "be called")
+
+/**
+ * Insert this macro in methods which must be implemented. This can be useful in the following cases:
+ * - during development, to mark methods you have not implemented yet (but which must be)
+ * - in class design: to mark methods for which a class cannot provide a meaningful implementation, which must be
+ * supplied in subclasses (abstract class, e.g. the -draw method of a Shape class)
+ */
+#define HLSMissingMethodImplementation() NSAssert(NO, @"Missing method implementation")
+
+/**
+ * The following macros check the type of objects in a collection. Useful for a class to verify that a collection it
+ * receives from a client through its public interface contains objects of the expected type. HLSAssert... macros can
+ * be used in methods only. In C-functions use the HLSCAssert... macros instead.
+ *
+ * Example: HLSAssertObjectsInEnumerationAreKindOfClass(views, UIScrollView);
+ */
+#define HLSAssertObjectsInEnumerationAreKindOfClass(enumeration, objectClassName) \
+ [[NSAssertionHandler currentHandler] handleIncorrectObjectClass:[objectClassName class] \
+ inEnumeration:enumeration \
+ strict:NO \
+ inMethod:_cmd \
+ object:self \
+ file:[NSString stringWithUTF8String:__FILE__] \
+ lineNumber:__LINE__]
+
+#define HLSCAssertObjectsInEnumerationAreKindOfClass(enumeration, objectClassName) \
+ [[NSAssertionHandler currentHandler] handleIncorrectObjectClass:[objectClassName class] \
+ inEnumeration:enumeration \
+ strict:NO \
+ inFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
+ file:[NSString stringWithUTF8String:__FILE__] \
+ lineNumber:__LINE__]
+
+#define HLSAssertObjectsInEnumerationAreMembersOfClass(enumeration, objectClassName) \
+ [[NSAssertionHandler currentHandler] handleIncorrectObjectClass:[objectClassName class] \
+ inEnumeration:enumeration \
+ strict:YES \
+ inMethod:_cmd \
+ object:self \
+ file:[NSString stringWithUTF8String:__FILE__] \
+ lineNumber:__LINE__]
+
+#define HLSCAssertObjectsInEnumerationAreMembersOfClass(enumeration, objectClassName) \
+ [[NSAssertionHandler currentHandler] handleIncorrectObjectClass:[objectClassName class] \
+ inEnumeration:enumeration \
+ strict:YES \
+ inFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
+ file:[NSString stringWithUTF8String:__FILE__] \
+ lineNumber:__LINE__]
+
+#else
+
+#define HLSStaticAssert(expr)
+
+#define HLSForbiddenInheritedMethod()
+#define HLSMissingMethodImplementation()
+
+#define HLSAssertObjectsInEnumerationAreKindOfClass(enumeration, objectClass)
+#define HLSCAssertObjectsInEnumerationAreKindOfClass(enumeration, objectClass)
+
+#define HLSAssertObjectsInEnumerationAreMembersOfClass(enumeration, objectClass)
+#define HLSCAssertObjectsInEnumerationAreMembersOfClass(enumeration, objectClass)
+
+#endif
+
+@interface NSAssertionHandler (HLSAssert)
+
+/**
+ * Check the class of objects in a collection and generate an assertion on mismatch. If strict is set to YES, all objects
+ * must be members of the class which is provided, otherwise they must be connected to it via inheritance
+ */
+- (void)handleIncorrectObjectClass:(Class)objectClass
+ inEnumeration:(id<NSFastEnumeration>)enumeration
+ strict:(BOOL)strict
+ inMethod:(SEL)selector
+ object:(id)object
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line;
+- (void)handleIncorrectObjectClass:(Class)objectClass
+ inEnumeration:(id<NSFastEnumeration>)enumeration
+ strict:(BOOL)strict
+ inFunction:(NSString *)functionName
+ file:(NSString *)fileName
+ lineNumber:(NSInteger)line;
+
+@end
View
46 PublicHeaders/HLSAutorotation.h
@@ -0,0 +1,46 @@
+//
+// HLSAutorotation.h
+// CoconutKit
+//
+// Created by Samuel Défago on 10/16/12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+/**
+ * Define the several ways for a container view controller to behave when interface rotation occurs. This means:
+ * - which view controllers decide whether rotation can occur or not
+ * - which view controllers receive rotation events (for children, this always occur from the topmost to the bottommost
+ * view controller, if they are involved)
+ *
+ * The default values are currently:
+ * - for iOS 4 and 5: HLSAutorotationModeContainerAndTopChildren
+ * - for iOS 6: HLSAutorotationModeContainer
+ */
+typedef enum {
+ HLSAutorotationModeEnumBegin = 0,
+ HLSAutorotationModeContainer = HLSAutorotationModeEnumBegin, // Default: The container implementation decides which view controllers are involved
+ // and which ones receive events (for UIKit containers this might vary between iOS
+ // versions)
+ HLSAutorotationModeContainerAndNoChildren, // The container only decides and receives events
+ HLSAutorotationModeContainerAndTopChildren, // The container and its top children decide and receive events. A container might have
+ // several top children if it displays several view controllers next to each other
+ HLSAutorotationModeContainerAndAllChildren, // The container and all its children (even those not visible) decide and receive events
+ HLSAutorotationModeEnumEnd,
+ HLSAutorotationModeEnumSize = HLSAutorotationModeEnumEnd - HLSAutorotationModeEnumBegin
+} HLSAutorotationMode;
+
+
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000
+
+// Enum available starting with the iOS 6 SDK, here made available for previous SDK versions as well
+typedef enum {
+ UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
+ UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
+ UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
+ UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
+ UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
+ UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
+ UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
+} UIInterfaceOrientationMask;
+
+#endif
View
464 PublicHeaders/HLSContainerStack.h
@@ -0,0 +1,464 @@
+//
+// HLSContainerStack.h
+// CoconutKit
+//
+// Created by Samuel Défago on 09.07.12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+#import "HLSAnimation.h"
+#import "HLSAutorotation.h"
+#import "HLSTransition.h"
+
+// Forward declarations
+@protocol HLSContainerStackDelegate;
+
+// Standard capacities
+extern const NSUInteger HLSContainerStackMinimalCapacity;
+extern const NSUInteger HLSContainerStackDefaultCapacity;
+extern const NSUInteger HLSContainerStackUnlimitedCapacity;
+
+/**
+ * The HLSContainerStack provides a convenient and easy interface to implement your own view controller containers,
+ * which is usually not a trivial task. Unlike the UIViewController containment API, this class is compatible with
+ * iOS 4 as well, and provides powerful features which let you implement custom containers correctly in a snap. The
+ * iOS 5 containment API, though powerful, namely still requires a lot of work to implement perfect containers.
+ * This is not the case with HLSContainerStack, which provides a robust way to implement the containers of your
+ * dreams.
+ *
+ * HLSContainerStack uses the smoother 1-step rotation available from iOS 3. You cannot use the 2-step rotation methods
+ * for view controllers you insert in it (they will be ignored, see UIViewController documentation). The 2-step rotation
+ * is deprecated starting with iOS 5, you should not use it anymore in your view controller implementations anyway.
+ *
+ * A lot of work has been made to provide a clean and powerful interface letting you easily implement containers with
+ * correct behavior. Most notably:
+ * - view lifecycle and rotation events are correctly forwarded to children view controllers
+ * Remark: Even if a view controller remains visible behind a transparent top view controller on top of it, it will
+ * still be considered as having disappeared (and therefore will receive the -viewWillDisappear: and
+ * -viewDidDisappear: events). It would namely be difficult and costly to determine if part of a view
+ * controller's view is visible through the view controller hierarchy on top of it (this would require
+ * finding the intersections of all view and subview rectangles, multiplicating alphas to find which
+ * parts of the view are visible and which aren't; clearly not worth it).
+ * - custom animations can be provided when inserting view controllers into a stack. A standard set of
+ * animations is provided out of the box. Animations behave correctly in all cases, even if the stack
+ * was rotated between push and pop operations, or if views have been unloaded
+ * - a delegate (usually your container implementation) can register itself with a stack to be notified when
+ * a view controller gets pushed, popped, appears or disappears. The set of delegate methods which can be
+ * implemented is far richer than the ones of UIKit built-in containers (most notably UINavigationController).
+ * Your custom containers usually just need to forward the events their users might be interested in through a
+ * dedicated delegate protocol
+ * - the methods -[UIViewController isMovingTo/FromParentViewController] return correct results, consistent
+ * with those returned when using standard built-in UIKit containers (these methods are available since iOS 5
+ * only, but CoconutKit injects implementations as well so that you can use them with custom containers on
+ * iOS 4 as well)
+ * - a capacity can be provided so that children view controller's views deep enough are automatically removed
+ * from the view hierarchy and reinserted when needed. The reason is that having too many view non-opaque
+ * view controllers can lead to performance issues, especially during animations (due to layer blending).
+ * By limiting the number of views in the container view hierarchy, such issues can be kept under control.
+ * Alternatively, a view controller can be removed from the stack as soon as it gets deep enough. This makes
+ * it possible to implement containers with a FIFO behavior (the case where the capacity is set to 1 corresponds
+ * to a stack displaying a single child view controller). Usually, the default capacity (which is given by
+ * HLSContainerStackDefaultCapacity = 2) should fulfill most needs, but if you require more transparency levels
+ * you can increase this value. Standard capacity values are provided at the beginning of this file.
+ * - custom containers implemented using HLSContainerStack behave correctly, whether they are embedded into
+ * another container (even built-in ones), displayed as the root of an application, or modally
+ * - stacks can be used to display any kind of view controllers, even standard UIKit containers like
+ * UITabBarController or UINavigationController
+ * - custom containers can be nested to create any kind of application workflow
+ * - view controllers can be preloaded into a stack before it is actually displayed
+ * - view controllers can be inserted into or removed from a stack at any position. Methods have been supplied
+ * to pop to a given view controller (even the root one) or to remove all view controllers at once
+ * - children view controller's views are instantiated right when needed, avoding wasting memory
+ * - view controllers are owned by a stack, but if you need to cache some of them for performance reasons,
+ * you still can: Simply keep and manage an external strong reference to the view controllers you want to cache
+ * - storyboards are supported (iOS 5 and above only). You are responsible of implementing segues in your own
+ * container implementations, though (see HLSPlaceholderViewController.m and HLSStackController.m for examples)
+ * - view controller containment relationships are consistent with those expected from UIKit built-in containers.
+ * In particular, some properties are automatically forwarded from a child view controller to a navigation
+ * controller if it displays a custom container, and modal view controllers are presented by the furthest
+ * ancestor container
+ * - a custom container can contain several HLSContainerStacks if it needs to display several children view
+ * controllers simultaneously
+ * - the container view can be resized at will, even when child view controllers are displayed
+ *
+ * When implementing your own view controller container, be sure to call the following HLSContainerStack
+ * methods, otherwise the behavior is undefined (refer to the documentation of these methods for more
+ * information):
+ * -releaseViews
+ * -viewWillAppear:
+ * -viewDidAppear:
+ * -viewWillDisappear:
+ * -viewDidDisappear:
+ * -shouldAutorotateToInterfaceOrientation:
+ * -willRotateToInterfaceOrientation:duration:
+ * -willAnimateRotationToInterfaceOrientation:duration:
+ * -didRotateFromInterfaceOrientation:duration:
+ * (the deprecated 2-step rotation methods are not supported, you should not have your own containers implement
+ * them)
+ *
+ * Also do not forget to set a containerView, either in your container -loadView or -viewDidLoad methods
+ *
+ * Remark: No methods have been provided for -viewDidLoad and -viewWill/DidUnload (call -releaseViews instead)
+ *
+ * The following iOS 5 methods can also be implemented by child view controllers, even on iOS 4:
+ * -willMoveToParentViewController:
+ * -didMoveToParentViewController:
+ * Implementations should call the super implementation first. Moreover, the following methods are also available
+ * for child view controllers, even on iOS 4:
+ * -isMovingToParentViewController
+ * -isMovingFromParentViewController
+ * Refer to the documentation of those methods for more information.
+ *
+ * Even though the new iOS 5 containment API is promising, implementing your own view controllers using
+ * HLSContainerStack has many advantages, and is far easier. For examples of implementations, have a look
+ * at HLSStackController.m and HLSPlaceholderViewController.m. Give it a try, you won't be disappointed!
+ *
+ * Designated initializer: -initWithContainerViewController:capacity:removing:rootViewControllerFixed:
+ */
+@interface HLSContainerStack : NSObject <HLSAnimationDelegate> {
+@private
+ UIViewController *m_containerViewController; // The container view controller implemented using HLSContainerStack
+ NSMutableArray *m_containerContents; // The contents loaded into the stack. The first element corresponds to the root view controller
+ UIView *m_containerView; // The view where the stack displays its contents
+ NSUInteger m_capacity; // The maximum number of top view controllers loaded / not removed at any time
+ BOOL m_removing; // If YES, view controllers over capacity are removed from the stack, otherwise their views are simply unloaded
+ BOOL m_rootViewControllerFixed; // Is the root view controller fixed?
+ BOOL m_animating; // Set to YES when a transition animation is running
+ BOOL m_rotating;
+ HLSAutorotationMode m_autorotationMode; // How the container decides to behave when rotation occurs
+ id<HLSContainerStackDelegate> m_delegate; // The stack delegate, usually the custom container which is implemented
+}
+
+/**
+ * Convenience constructor to instantiate a stack containing at most one child view controller
+ */
++ (id)singleControllerContainerStackWithContainerViewController:(UIViewController *)containerViewController;
+
+/**
+ * Create a stack which will manage the children view controllers of a container view controller. The containerViewController
+ * parameter is the container you want to implement (which must itself instantiate the HLSContainerStack objects it requires)
+ * and is not retained. If removing is NO, the capacity is the maximum number of view controllers whose views are loaded at
+ * any time (check the top of this file for some standard capacity constants). If removing is YES, the capacity corresponds
+ * to the maximum number of view controllers which can exist in the container at any time (the view controllers deep enough
+ * are automatically removed from the stack). If rootViewControllerFixed is set to YES, a view controller has to be
+ * pushed into the stack before it is displayed for the first time, and all operations which could later change it will
+ * abort
+ *
+ * Remark: During transition animations, the capacity is temporary increased by one to avoid view controllers popping up
+ * unnecessarily. This is not a bug
+ */
+- (id)initWithContainerViewController:(UIViewController *)containerViewController
+ capacity:(NSUInteger)capacity
+ removing:(BOOL)removing
+ rootViewControllerFixed:(BOOL)rootViewControllerFixed;
+
+/**
+ * The view where the stack must display the children view controller's views. This view must be part of the container
+ * view controller's view hierarchy and cannot be set once it has been displayed (in general, though, you need to
+ * set it once in the container view controller -loadView or -viewDidLoad method)
+ */
+@property (nonatomic, retain) UIView *containerView;
+
+/**
+ * Set how a container decides whether it must rotate or not. Your containers should in general exhibit a similar
+ * property, whose implementation must be forwarded to this HLSContainerContent property
+ *
+ * HLSAutorotationModeContainer: All child view controllers loaded according to the capacity decide whether rotation
+ * can occur, and receive the related events
+ * HLSAutorotationModeContainerAndNoChildren: No children decide whether rotation occur, and none receive the
+ * related events
+ * HLSAutorotationModeContainerAndTopChildren: The top child view controller decide whether rotation can occur,
+ * and receive the related events
+ * HLSAutorotationModeContainerAndAllChildren: All child view controllers decide whether rotation can occur, and receive
+ * the related events
+ *
+ * The default value is HLSAutorotationModeContainer
+ */
+@property (nonatomic, assign) HLSAutorotationMode autorotationMode;
+
+/**
+ * The stack delegate (usually the container view controller you are implementing)
+ */
+@property (nonatomic, assign) id<HLSContainerStackDelegate> delegate;
+
+/**
+ * Return the root view controller loaded into the stack, or nil if none
+ */
+- (UIViewController *)rootViewController;
+
+/**
+ * Return the current topmost view controller, or nil if none
+ */
+- (UIViewController *)topViewController;
+
+/**
+ * Return the view controllers currently loaded into the stack, from the bottommost to the topmost one
+ */
+- (NSArray *)viewControllers;
+
+/**
+ * Return the number of view controllers loaded into the stack
+ */
+- (NSUInteger)count;
+
+/**
+ * Push a view controller on top of the stack using a given animation class (subclass of HLSTransition). You can subclass
+ * HLSTransition to create your custom animations, or use the CoconutKit built-in ones. Refer to HLSTransiton.h for more
+ * information. If duration is set to kAnimationTransitionDefaultDuration, the view controller is pushed with the default
+ * duration defined by the animation. You can freely change this value, in which case the animation will look the same,
+ * only slower or faster. If animated is set to YES, the animation will occur, otherwise not. You can still pop the view
+ * controller later with animated = YES.
+ *
+ * This method can also be used to preload view controllers into a stack (in which case the animated parameter is ignored)
+ */
+- (void)pushViewController:(UIViewController *)viewController
+ withTransitionClass:(Class)transitionClass
+ duration:(NSTimeInterval)duration
+ animated:(BOOL)animated;
+
+/**
+ * Pop the current top view controller, playing the reverse animation corresponding to the one it has been pushed with.
+ * If the root view controller is fixed, you cannot pop it
+ */
+- (void)popViewControllerAnimated:(BOOL)animated;
+
+/**
+ * Pop all view controllers up to a given view controller (animated or not). If viewController is set to nil, this
+ * method pops all view controllers (except if the root view controller is fixed, in which case this method does
+ * nothing)
+ *
+ * When the transition is animated, the pop occurs with the reverse animation corresponding to the animation with
+ * which the topmost view controller was pushed
+ *
+ * If the view controller is not in the stack or if it is already the top view controller, this method does nothing.
+ */
+- (void)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
+
+/**
+ * Same as -popToViewController:animated:, but specifying a view controller using its index. Set index to NSUIntegerMax
+ * to pop everything (except if the root view controller is fixed, in which case this method does nothing)
+ *
+ * If the index is invalid or if it is the index of the top view controller (i.e. [self count] - 1), this method
+ * does nothing
+ */
+- (void)popToViewControllerAtIndex:(NSUInteger)index animated:(BOOL)animated;
+
+/**
+ * Pop to the root view controller (animated or not)
+ */
+- (void)popToRootViewControllerAnimated:(BOOL)animated;
+
+/**
+ * Pop all view controllers (except if the root view controller is fixed, in which case this method does nothing)
+ */
+- (void)popAllViewControllersAnimated:(BOOL)animated;
+
+/**
+ * Insert a view controller at the specified index with some transition animation properties. If index == [self count],
+ * the view controller is added at the top of the stack, and the transition animation takes place (provided animated has
+ * been set to YES). In all other cases, no animation occurs. Note that the corresponding reverse animation will still
+ * be played when the view controller is later popped
+ *
+ * If the index is invalid, or if its is 0 and the root view controller is fixed (after the stack has been displayed
+ * once), this method does nothing
+ */
+- (void)insertViewController:(UIViewController *)viewController
+ atIndex:(NSUInteger)index
+ withTransitionClass:(Class)transitionClass
+ duration:(NSTimeInterval)duration
+ animated:(BOOL)animated;
+
+/**
+ * Insert a view controller below an existing one. If the provided sibling view controller does not exist in the
+ * stack, or if the sibling view controller is the root view controller and is fixed, this method does nothing
+ */
+- (void)insertViewController:(UIViewController *)viewController
+ belowViewController:(UIViewController *)siblingViewController
+ withTransitionClass:(Class)transitionClass
+ duration:(NSTimeInterval)duration;
+
+/**
+ * Insert a view controller above an existing one. If the provided sibling view controller does not exist in the
+ * stack, this method does nothing. If siblingViewController is the current top view controller, the transition
+ * will be animated (provided animated has been set to YES), otherwise no animation will occur
+ */
+- (void)insertViewController:(UIViewController *)viewController
+ aboveViewController:(UIViewController *)siblingViewController
+ withTransitionClass:(Class)transitionClass
+ duration:(NSTimeInterval)duration
+ animated:(BOOL)animated;
+
+/**
+ * Remove the view controller at a given index. If index == [self count] - 1, the removal will be animated
+ * (provided animated has been set to YES), otherwise no animation will occur
+ *
+ * If the index is invalid, or if it is 0 and the root view controller is fixed, this method does nothing
+ */
+- (void)removeViewControllerAtIndex:(NSUInteger)index animated:(BOOL)animated;
+
+/**
+ * Remove a given view controller from the stack. If the view controller is the current top view controller, the
+ * transition will be animated (provided animated has been set to YES), otherwise no animation will occur.
+ *
+ * If the view controller is not in the stack, or if it is the root view controller and is fixed, this method
+ * does nothing
+ */
+- (void)removeViewController:(UIViewController *)viewController animated:(BOOL)animated;
+
+/**
+ * Release all view and view-related resources. On iOS 4 and 5, this also forwards the -viewWill/DidUnload messages
+ * to the corresponding view controllers
+ */
+- (void)releaseViews;
+
+/**
+ * Call this method from your container view controller -viewWillAppear: method, otherwise the behavior is undefined
+ */
+- (void)viewWillAppear:(BOOL)animated;
+
+/**
+ * Call this method from your container view controller -viewDidAppear: method, otherwise the behavior is undefined
+ */
+- (void)viewDidAppear:(BOOL)animated;
+
+/**
+ * Call this method from your container view controller -viewWillDisappear: method, otherwise the behavior is undefined
+ */
+- (void)viewWillDisappear:(BOOL)animated;
+
+/**
+ * Call this method from your container view controller -viewDidDisappear: method, otherwise the behavior is undefined
+ */
+- (void)viewDidDisappear:(BOOL)animated;
+
+/**
+ * Call this method from your container view controller -shouldAutorotate: method, otherwise the behavior is undefined
+ */
+- (BOOL)shouldAutorotate;
+
+/**
+ * Call this method from your container view controller -supportedInterfaceOrientations method, otherwise the behavior
+ * is undefined
+ */
+- (NSUInteger)supportedInterfaceOrientations;
+
+/**
+ * Call this method from your container view controller -willRotateToInterfaceOrientation:duration: method, otherwise
+ * the behavior is undefined
+ */
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
+
+/**
+ * Call this method from your container view controller -willAnimateRotationToInterfaceOrientation:duration: method,
+ * otherwise the behavior is undefined
+ */
+- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration;
+
+/**
+ * Call this method from your container view controller -didRotateFromInterfaceOrientation:duration: method, otherwise
+ * the behavior is undefined
+ */
+- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;
+
+@end
+
+/**
+ * This protocol offers more methods than the equivalent protocol of UINavigationController. This provides much
+ * more information about appearance and disappearance events (and especially since HLSContainerStack allows
+ * insertion and removal anywhere in a stack). When implementing your custom containers, you usually just need
+ * to set your container as delegate of the stack, catch the events you are interested in, and forward them to
+ * your container delegate through a dedicated protocol
+ */
+@protocol HLSContainerStackDelegate <NSObject>
+
+/**
+ * Called before pushedViewController is about to be pushed onto the stack. When called, pushedViewController does not
+ * belong to [self viewControllers] yet, and the parent-child containment relationship has not been established.
+ * The coveredViewController parameter is the view controller which is about to be covered (nil if none)
+ */
+- (void)containerStack:(HLSContainerStack *)containerStack
+willPushViewController:(UIViewController *)pushedViewController
+ coverViewController:(UIViewController *)coveredViewController
+ animated:(BOOL)animated;
+
+/**
+ * Called when a child view controller is about to be displayed. When called, viewController is always in
+ * [self viewControllers], even if this event is the result of a push
+ */
+- (void)containerStack:(HLSContainerStack *)containerStack
+willShowViewController:(UIViewController *)viewController
+ animated:(BOOL)animated;
+
+/**
+ * Called when a child view controller has been displayed
+ */
+- (void)containerStack:(HLSContainerStack *)containerStack
+ didShowViewController:(UIViewController *)viewController
+ animated:(BOOL)animated;
+
+/**
+ * Called when a view controller has been pushed onto the stack. The coveredViewController parameter is the view
+ * controller which was covered (nil if none)
+ */
+- (void)containerStack:(HLSContainerStack *)containerStack
+ didPushViewController:(UIViewController *)pushedViewController
+ coverViewController:(UIViewController *)coveredViewController
+ animated:(BOOL)animated;
+
+/**
+ * Called when a view controller is about to be popped off the stack. The revealedViewController parameter is the
+ * view controller which will be revealed (nil if none)
+ */
+- (void)containerStack:(HLSContainerStack *)containerStack
+ willPopViewController:(UIViewController *)poppedViewController
+ revealViewController:(UIViewController *)revealedViewController
+ animated:(BOOL)animated;
+
+/**
+ * Called when a child view controller is about to be hidden
+ */
+- (void)containerStack:(HLSContainerStack *)containerStack
+willHideViewController:(UIViewController *)viewController
+ animated:(BOOL)animated;
+
+/**
+ * Called when a view controller has been hidden. When called, viewController is still in [self viewControllers],
+ * even if this event is received during a pop
+ */
+- (void)containerStack:(HLSContainerStack *)containerStack
+ didHideViewController:(UIViewController *)viewController
+ animated:(BOOL)animated;
+
+/**
+ * Called when a view controller has been popped off the stack. When called, poppedViewController has been removed
+ * from [self viewControllers], and the parent-child containment relationship has been broken. The revealedViewController
+ * parameter is the view controller which has been revealed (nil if none)
+ */
+- (void)containerStack:(HLSContainerStack *)containerStack
+ didPopViewController:(UIViewController *)poppedViewController
+ revealViewController:(UIViewController *)revealedViewController
+ animated:(BOOL)animated;
+
+@end
+
+@interface UIViewController (HLSContainerStack)
+
+/**
+ * Your custom containers should implement a UIViewController method for retrieving the parent container from within
+ * a child view controller (as -navigationController or -tabBarController do). Implement your own method returning
+ * your parent view controller container (if any) by declaring a UIViewController category. Its implementation is
+ * straightforward: Simply call the method below with your container class as argument. If Nil is provided as class
+ * parameter, lookup is performed for any kind of CoconutKit-based container
+ */
+- (id)containerViewControllerKindOfClass:(Class)containerViewControllerClass;
+
+/**
+ * Return the interface orientation used for displaying the view controller. For view controllers not embedded into
+ * CoconutKit containers, this value is the same as the one returned by -[UIViewController interfaceOrientation],
+ * matching the status bar orientation. For view controllers embedded into CoconutKit containers, this is the
+ * orientation of the view controller, compatible with the container, which has been used for display (this might
+ * not necessarily match the status bar orientation)
+ */
+@property (nonatomic, readonly, assign) UIInterfaceOrientation displayedInterfaceOrientation;
+
+@end
View
50 PublicHeaders/HLSConverters.h
@@ -0,0 +1,50 @@
+//
+// HLSConverters.h
+// CoconutKit
+//
+// Created by Samuel Défago on 9/21/10.
+// Copyright 2010 Hortis. All rights reserved.
+//
+
+/**
+ * Conversions to string
+ */
+NSString *HLSStringFromBool(BOOL yesOrNo);
+NSString *HLSStringFromInterfaceOrientation(UIInterfaceOrientation interfaceOrientation);
+NSString *HLSStringFromDeviceOrientation(UIDeviceOrientation deviceOrientation);
+NSString *HLSStringFromCATransform3D(CATransform3D transform);
+
+/**
+ * Conversions to numbers
+ */
+NSNumber *HLSUnsignedIntNumberFromString(NSString *string);
+
+/**
+ * Conversions requiring several arguments. As methods since method signatures more explicit
+ *
+ * Not meant to be instantiated
+ */
+@interface HLSConverters : NSObject {
+@private
+
+}
+
++ (NSDate *)dateFromString:(NSString *)string usingFormatString:(NSString *)formatString;
+
++ (void)convertStringValueForKey:(NSString *)sourceKey
+ ofDictionary:(NSDictionary *)sourceDictionary
+ intoStringValueForKey:(NSString *)destKey
+ ofDictionary:(NSMutableDictionary *)destDictionary;
+
++ (void)convertStringValueForKey:(NSString *)sourceKey
+ ofDictionary:(NSDictionary *)sourceDictionary
+ intoUnsignedIntValueForKey:(NSString *)destKey
+ ofDictionary:(NSMutableDictionary *)destDictionary;
+
++ (void)convertStringValueForKey:(NSString *)sourceKey
+ ofDictionary:(NSDictionary *)sourceDictionary
+ intoDateValueForKey:(NSString *)destKey
+ ofDictionary:(NSMutableDictionary *)destDictionary
+ usingFormatString:(NSString *)formatString;
+
+@end
View
147 PublicHeaders/HLSCursor.h
@@ -0,0 +1,147 @@
+//
+// HLSCursor.h
+// CoconutKit
+//
+// Created by Samuel Défago on 09.06.11.
+// Copyright 2011 Hortis. All rights reserved.
+//
+
+// Macros
+#define kCursorShadowOffsetDefault CGSizeMake(0, -1)
+
+// Forward declarations
+@protocol HLSCursorDataSource;
+@protocol HLSCursorDelegate;
+
+/**
+ * A class for creating value cursors, i.e. sets of elements from which one is exactly active at any time. The current
+ * element is identified by a graphical pointer. This pointer can either be moved by clicking another value or by dragging
+ * it.
+ *
+ * Adding a cursor to your application is very easy:
+ * - add a HLSCursor, either programmatically or using Interface Builder
+ * - implement a data source (HLSCursorDataSource protocol) to set the elements to display
+ * - implement a delegate (HLSCursorDelegate protocol) to respond to cursor events
+ *
+ * The cursor layout is automatically created for you: You just need to set the main cursor frame size, the layout is
+ * calculated for you depending on the size of the elements which need to be displayed. During development, if you use the
+ * debug version of the library, warnings will be displayed in the console if the frame is too small to display the cursor
+ * contents correctly (see HLSLogger for the available logging levels).
+ *
+ * There are two ways to set the cursor contents. Both can be mixed within the same cursor:
+ * - basic: You just set the text and basic text properties (font, colors, shadows)
+ * - custom: Each element is a view and can be customized using Interface Builder
+ * Cursors using both ways of customisation can coexist in the same source file.
+ *
+ * Designated initializer: -initWithFrame:
+ */
+@interface HLSCursor : UIView {
+@private
+ NSArray *m_elementViews;
+ CGFloat m_spacing;
+ UIView *m_pointerView;
+ UIView *m_pointerContainerView;
+ CGSize m_pointerViewTopLeftOffset;
+ CGSize m_pointerViewBottomRightOffset;
+ NSUInteger m_selectedIndex;
+ BOOL m_dragging;
+ CGFloat m_initialDraggingXOffset;
+ BOOL m_grabbed;
+ BOOL m_viewsCreated;
+ NSUInteger m_initialIndex;
+ id<HLSCursorDataSource> m_dataSource;
+ id<HLSCursorDelegate> m_delegate;
+}
+
+/**
+ * Spacing between elements displayed by the cursor (default is 20 px)
+ */
+@property (nonatomic, assign) CGFloat spacing;
+
+/**
+ * The pointer view, which can either be set programatically or using a xib. If nil, the default pointer will be used.
+ * If you use a custom view, be sure it can stretch properly since the pointer view frame will be adjusted depending
+ * on the element it is on. In general, your custom pointer view is likely to be transparent so that the element
+ * below it can be seen.
+ *
+ * As soon as the pointer view has been set it cannot be changed anymore.
+ */
+@property (nonatomic, retain) IBOutlet UIView *pointerView;
+
+/**
+ * Pointer view offsets. Use these offsets to make the pointer rectangle larger or smaller than the element it points
+ * at. By default the pointer view frame is 10px larger in all directions
+ */
+@property (nonatomic, assign) CGSize pointerViewTopLeftOffset; // Default is (-10px, -10px)
+@property (nonatomic, assign) CGSize pointerViewBottomRightOffset; // Default is (10px, 10px)
+
+/**
+ * Get the currently selected element. During the time the pointer is moved the selected index is not updated. This value
+ * is only updated as soon as the pointer reaches a new element
+ */
+- (NSUInteger)selectedIndex;
+
+/**
+ * Move the pointer to a specific element. This setter can also be used to set the initially selected element before the
+ * cursor is displayed (in this case, the animated parameter is ignored)
+ */
+- (void)moveToIndex:(NSUInteger)index animated:(BOOL)animated;
+
+/**
+ * Reload the cursor from the data source. The pointer is left at the same index where it was, except if the index
+ * is out of range after the reload (in which case the pointer is reset to point on the first element)
+ */
+- (void)reloadData;
+
+/**
+ * Set / get the data source used to fill the cursor with elements
+ */
+@property (nonatomic, assign) id<HLSCursorDataSource> dataSource;
+
+/**
+ * Set / get the cursor delegate receiving the cursor events
+ */
+@property (nonatomic, assign) id<HLSCursorDelegate> delegate;
+
+@end
+
+@protocol HLSCursorDataSource <NSObject>
+
+@required
+// The number of elements to display
+- (NSUInteger)numberOfElementsForCursor:(HLSCursor *)cursor;
+
+@optional
+// Fully customized by specifying a view. You can use the selected boolean to set a different view for selected and
+// non-selected elements
+- (UIView *)cursor:(HLSCursor *)cursor viewAtIndex:(NSUInteger)index selected:(BOOL)selected;
+
+// Less customisation, but no view is needed. You can use the selected boolean to set different properties for
+// selected and non-selected elements
+- (NSString *)cursor:(HLSCursor *)cursor titleAtIndex:(NSUInteger)index;
+- (UIFont *)cursor:(HLSCursor *)cursor fontAtIndex:(NSUInteger)index selected:(BOOL)selected; // if not implemented or returning nil: system font, size 17
+- (UIColor *)cursor:(HLSCursor *)cursor textColorAtIndex:(NSUInteger)index selected:(BOOL)selected; // if not implemented or returning nil: invert background color
+- (UIColor *)cursor:(HLSCursor *)cursor shadowColorAtIndex:(NSUInteger)index selected:(BOOL)selected; // none if not implemented or returning nil
+- (CGSize)cursor:(HLSCursor *)cursor shadowOffsetAtIndex:(NSUInteger)index selected:(BOOL)selected; // top-shadow if not implemented or returning kCursorShadowOffsetDefault
+
+@end
+
+@protocol HLSCursorDelegate <NSObject>
+
+@optional
+// Triggered when the pointer leaves a selected element at a given index
+- (void)cursor:(HLSCursor *)cursor didMoveFromIndex:(NSUInteger)index;
+
+// Triggered when the pointer stops moving, selecting a new element
+- (void)cursor:(HLSCursor *)cursor didMoveToIndex:(NSUInteger)index;
+
+// Triggered when the user starts dragging the pointer
+- (void)cursorDidStartDragging:(HLSCursor *)cursor;
+
+// Triggered when the user is dragging the pointer. The nearest index is given as parameter
+- (void)cursor:(HLSCursor *)cursor didDragNearIndex:(NSUInteger)index;
+
+// Triggered when the user stops dragging the pointer
+- (void)cursorDidStopDragging:(HLSCursor *)cursor;
+
+@end
View
64 PublicHeaders/HLSError.h
@@ -0,0 +1,64 @@
+//
+// HLSError.h
+// CoconutKit
+//
+// Created by Samuel Défago on 10.12.11.
+// Copyright (c) 2011 Hortis. All rights reserved.
+//
+
+/**
+ * Lightweight abstract subclass of HLSError providing a convenient way to create errors and to define and access
+ * their properties.
+ *
+ * This class enforces the link between accessor methods and underlying userInfo dictionary keys. This is not
+ * required, as explained in the documentation:
+ * http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorHandling/ErrorHandling.html
+ *
+ * Designated initializer: -initWithDomain:Code:
+ */
+@interface HLSError : NSError {
+@private
+ NSDictionary *m_internalUserInfo;
+}
+
+/**
+ * Instantiate an error with some code within a domain. The error is created with no information, use the mutators below to
+ * add the information you need
+ */
++ (id)errorWithDomain:(NSString *)domain code:(NSInteger)code;
+
+/**
+ * Convenience instantiation method for the most common case (an error conveying a description message). You can still
+ * use the mutators below to add more information if needed
+ */
++ (id)errorWithDomain:(NSString *)domain code:(NSInteger)code localizedDescription:(NSString *)localizedDescription;
+
+/**
+ * Initialize an error with some code within a domain. The error is created with no information, use the mutators below to
+ * add the information you need
+ */
+- (id)initWithDomain:(NSString *)domain code:(NSInteger)code;
+
+/**
+ * Various mutators for setting standard NSError properties. Please refer to the NSError documentation for more information
+ */
+- (void)setLocalizedDescription:(NSString *)localizedDescription;
+- (void)setLocalizedFailureReason:(NSString *)localizedFailureReason;
+- (void)setLocalizedRecoverySuggestion:(NSString *)localizedRecoverySuggestion;
+- (void)setLocalizedRecoveryOptions:(NSArray *)localizedRecoveryOptions;
+- (void)setRecoveryAttempter:(id)recoveryAttempter;
+- (void)setHelpAnchor:(NSString *)helpAnchor;
+
+/**
+ * Set a nested error
+ */
+- (void)setUnderlyingError:(NSError *)underlyingError;
+
+/**
+ * Sets an object for some key. The key can either be a reserved one (see NSError) or a custom one. Instead
+ * of using this generic mutator to set objects corresponding to reserved keys, use the mutators provided
+ * by HLSError
+ */
+- (void)setObject:(id)object forKey:(NSString *)key;
+
+@end
View
98 PublicHeaders/HLSExpandingSearchBar.h
@@ -0,0 +1,98 @@
+//
+// HLSExpandingSearchBar.h
+// CoconutKit
+//
+// Created by Samuel Défago on 11.06.12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+#import "HLSAnimation.h"
+
+// Search button alignment
+typedef enum {
+ HLSExpandingSearchBarAlignmentLeft = 0,
+ HLSExpandingSearchBarAlignmentRight,
+} HLSExpandingSearchBarAlignment;
+
+// Forward declarations
+@protocol HLSExpandingSearchBarDelegate;
+
+/**
+ * A search bar which reduces to a button and can be expanded / collapsed when needed by clicking on the
+ * magnifying glass icon. Completely similar to a UISearchBar otherwise.
+ *
+ * The search bar frame corresponds to the area where the search bar stretches when it expands. You can control
+ * whether the search bar collapses to a button on the left or on the right using the alignment property.
+ *
+ * A search bar always has a standard height of 44px and no flexible height. This is automatically enforced by
+ * HLSExpandingSearchBar if this happens not to be the case (a message is logged at warning level).
+ *
+ * Note that the search criterium gets cleared and cannot be set when the search bar is collapsed.
+ */
+@interface HLSExpandingSearchBar : UIView <HLSAnimationDelegate, UISearchBarDelegate> {
+@private
+ UISearchBar *m_searchBar;
+ UIButton *m_searchButton;
+ NSString *m_prompt;
+ NSString *m_placeholder;
+ BOOL m_showsBookmarkButton;
+ BOOL m_showsSearchResultsButton;
+ HLSExpandingSearchBarAlignment m_alignment;
+ id<HLSExpandingSearchBarDelegate> m_delegate;
+ BOOL m_layoutDone;
+ BOOL m_expanded;
+ BOOL m_animating;
+}
+
+/**
+ * These properties are exactly the same as for UISearchBar. Refer to their documentation for more information.
+ * Note that you cannot have bookmark and search results buttons at the same time
+ */
+@property (nonatomic, copy) NSString *text;
+@property (nonatomic, copy) NSString *prompt;
+@property (nonatomic, copy) NSString *placeholder;
+@property (nonatomic, assign) BOOL showsBookmarkButton;
+@property (nonatomic, assign) BOOL showsSearchResultsButton;
+
+@property (nonatomic, assign) UITextAutocapitalizationType autocapitalizationType;
+@property (nonatomic, assign) UITextAutocorrectionType autocorrectionType;
+@property (nonatomic, assign) UITextSpellCheckingType spellCheckingType;
+@property (nonatomic, assign) UIKeyboardType keyboardType;
+
+/**
+ * Set whether the search button is left-aligned (expansion to the right) or right-aligned (expansion to the left).
+ * Default value is HLSExpandingSearchBarAlignmentLeft
+ */
+@property (nonatomic, assign) HLSExpandingSearchBarAlignment alignment;
+
+/**
+ * The search bar delegate
+ */
+@property (nonatomic, assign) id<HLSExpandingSearchBarDelegate> delegate;
+
+/**
+ * Expand or collapse the search bar. Can be used to create a search bar initially expanded
+ */
+- (void)setExpanded:(BOOL)expanded animated:(BOOL)animated;
+
+@end
+
+@protocol HLSExpandingSearchBarDelegate <NSObject>
+
+// Called when the search bar expands or collapses
+- (void)expandingSearchBarDidExpand:(HLSExpandingSearchBar *)searchBar animated:(BOOL)animated;
+- (void)expandingSearchBarDidCollapse:(HLSExpandingSearchBar *)searchBar animated:(BOOL)animated;
+
+// Refer to the documentation of the same methods declared by UISearchBarDelegate
+- (BOOL)expandingSearchBarShouldBeginEditing:(HLSExpandingSearchBar *)searchBar;
+- (void)expandingSearchBarTextDidBeginEditing:(HLSExpandingSearchBar *)searchBar;
+- (BOOL)expandingSearchBarShouldEndEditing:(HLSExpandingSearchBar *)searchBar;
+- (void)expandingSearchBarTextDidEndEditing:(HLSExpandingSearchBar *)searchBar;
+- (void)expandingSearchBar:(HLSExpandingSearchBar *)searchBar textDidChange:(NSString *)searchText;
+- (BOOL)expandingSearchBar:(HLSExpandingSearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
+
+- (void)expandingSearchBarSearchButtonClicked:(HLSExpandingSearchBar *)searchBar;
+- (void)expandingSearchBarBookmarkButtonClicked:(HLSExpandingSearchBar *)searchBar;
+- (void)expandingSearchBarResultsListButtonClicked:(HLSExpandingSearchBar *)searchBar;
+
+@end
View
57 PublicHeaders/HLSFloat.h
@@ -0,0 +1,57 @@
+//
+// HLSFloat.h
+// CoconutKit
+//
+// Created by Samuel Défago on 9/19/10.
+// Copyright 2010 Hortis. All rights reserved.
+//
+
+// Default distance used by macros without distance parameter
+#define HLSFloatDefaultMaxDist 5
+
+/**
+ * Macros for comparing float or double values
+ */
+#define floatle_dist(x, y, maxDist) ((x) < (y) || floateq_dist((x), (y), (maxDist)))
+#define floatge_dist(x, y, maxDist) ((x) > (y) || floateq_dist((x), (y), (maxDist)))
+#define floatlt_dist(x, y, maxDist) ! floatge_dist((x), (y), (maxDist))
+#define floatgt_dist(x, y, maxDist) ! floatle_dist((x), (y), (maxDist))
+
+#define doublele_dist(x, y, maxDist) ((x) < (y) || doubleeq_dist((x), (y), (maxDist)))
+#define doublege_dist(x, y, maxDist) ((x) > (y) || doubleeq_dist((x), (y), (maxDist)))
+#define doublelt_dist(x, y, maxDist) ! doublege_dist((x), (y), (maxDist))
+#define doublegt_dist(x, y, maxDist) ! doublele_dist((x), (y), (maxDist))
+
+#define floateq(x, y) floateq_dist((x), (y), HLSFloatDefaultMaxDist)
+#define doubleeq(x, y) doubleeq_dist((x), (y), HLSFloatDefaultMaxDist)
+
+#define floatle(x, y) floatle_dist((x), (y), HLSFloatDefaultMaxDist)
+#define floatge(x, y) floatge_dist((x), (y), HLSFloatDefaultMaxDist)
+#define floatlt(x, y) floatlt_dist((x), (y), HLSFloatDefaultMaxDist)
+#define floatgt(x, y) floatgt_dist((x), (y), HLSFloatDefaultMaxDist)
+
+#define doublele(x, y) doublele_dist((x), (y), HLSFloatDefaultMaxDist)
+#define doublege(x, y) doublege_dist((x), (y), HLSFloatDefaultMaxDist)
+#define doublelt(x, y) doublelt_dist((x), (y), HLSFloatDefaultMaxDist)
+#define doublegt(x, y) doublegt_dist((x), (y), HLSFloatDefaultMaxDist)
+
+#define floatmin(x, y) floatmin_dist((x), (y), HLSFloatDefaultMaxDist)
+#define floatmax(x, y) floatmax_dist((x), (y), HLSFloatDefaultMaxDist)
+
+#define doublemin(x, y) doublemin_dist((x), (y), HLSFloatDefaultMaxDist)
+#define doublemax(x, y) doublemax_dist((x), (y), HLSFloatDefaultMaxDist)
+
+/**
+ * Comparison function for floating point numbers. The parameter maxDist is the maximum distance between two (discrete)
+ * numbers so that they can be considered to be equal
+ */
+BOOL floateq_dist(float x, float y, uint32_t maxDist);
+BOOL doubleeq_dist(double x, double y, uint64_t maxDist);
+
+/**
+ * Max / min functions (not macros; this would have provided weaker type-checking)
+ */
+float floatmin_dist(float x, float y, uint32_t maxDist);
+float floatmax_dist(float x, float y, uint32_t maxDist);
+double doublemin_dist(double x, double y, uint64_t maxDist);
+double doublemax_dist(double x, double y, uint64_t maxDist);
View
53 PublicHeaders/HLSKeyboardInformation.h
@@ -0,0 +1,53 @@
+//
+// HLSKeyboardInformation.h
+// CoconutKit
+//
+// Created by Samuel Défago on 2/17/11.
+// Copyright 2011 Hortis. All rights reserved.
+//
+
+/**
+ * This class makes keyboard properties accessible at any time in a convenient way. Just access the +keyboardInformation
+ * method. If the returned object is not nil, then the keyboard is docked and visible (or soon will) and you can check its
+ * properties. The object is nil if the keyboard is floating (iPad) or invisible.
+ *
+ * Not meant to be instantiated directly. Simply use the +keyboardInformation class method.
+ */
+@interface HLSKeyboardInformation : NSObject {
+@private
+ CGRect m_beginFrame;
+ CGRect m_endFrame;
+ NSTimeInterval m_animationDuration;
+ UIViewAnimationCurve m_animationCurve;
+}
+
+/**
+ * Return the keyboard information if docked and displayed (or about to be displayed), nil if the keyboard is not visible,
+ * about to be hidden, or floating
+ */
++ (HLSKeyboardInformation *)keyboardInformation;
+
+/**
+ * Start frame of the keyboard before it is displayed (in the window coordinate system). Refer to the
+ * UIKeyboardFrameBeginUserInfoKey documentation for how to translate this frame into a meaningful coordinate system
+ */
+@property (nonatomic, readonly, assign) CGRect beginFrame;
+
+/**
+ * Start frame of the keyboard after it is displayed (in the window coordinate system). This is the most interesting
+ * keyboard property since it lets you find which screen area the keyboard covers when displayed. Refer to the
+ * UIKeyboardFrameEndUserInfoKey documentation for how to translate this frame into a meaningful coordinate system
+ */
+@property (nonatomic, readonly, assign) CGRect endFrame;
+
+/**
+ * Duration of the animation showing the keyboard
+ */
+@property (nonatomic, readonly, assign) NSTimeInterval animationDuration;
+
+/**
+ * Curve of the animation showing the keyboard
+ */
+@property (nonatomic, readonly, assign) UIViewAnimationCurve animationCurve;
+
+@end
View
43 PublicHeaders/HLSLabel.h
@@ -0,0 +1,43 @@
+//
+// HLSLabel.h
+// CoconutKit
+//
+// Created by Joris Heuberger on 12.04.12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+/**
+ * Vertical alignments
+ */
+typedef enum {
+ HLSLabelVerticalAlignmentEnumBegin = 0,
+ HLSLabelVerticalAlignmentMiddle = HLSLabelVerticalAlignmentEnumBegin,
+ HLSLabelVerticalAlignmentTop,
+ HLSLabelVerticalAlignmentBottom,
+ HLSLabelVerticalAlignmentEnumEnd,
+ HLSLabelVerticalAlignmentEnumSize = HLSLabelVerticalAlignmentEnumEnd - HLSLabelVerticalAlignmentEnumBegin
+} HLSLabelVerticalAlignment;
+
+/**
+ * An HLSLabel is like a UILabel but differs in the following ways:
+ * - a vertical alignment can be specified
+ * - the font size can be automatically adjusted to fit the label width (adjustsFontSizeToFitWidth property)
+ * even if several lines can be displayed by the label (numberOfLines property)
+ * - the minimumFontSize property can be used to set a minimal font size when adjustments occur (even if the
+ * number of lines is larger than 1). Unlike UILabel, the font size can never be smaller than this minimum
+ * value (even if no size adjustment is needed)
+ * - the baselineAdjustment property is ignored
+ */
+@interface HLSLabel : UILabel {
+@private
+ HLSLabelVerticalAlignment _verticalAlignment;
+}
+
+/**
+ * Vertical alignment of the string in the label
+ *
+ * Default value is HLSLabelVerticalAlignmentMiddle
+ */
+@property (nonatomic, assign) HLSLabelVerticalAlignment verticalAlignment;
+
+@end
View
119 PublicHeaders/HLSLayerAnimation.h
@@ -0,0 +1,119 @@
+//
+// HLSLayerAnimation.h
+// CoconutKit
+//
+// Created by Samuel Défago on 8/20/12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+#import "HLSObjectAnimation.h"
+
+#import "HLSVector.h"
+
+/**
+ * A layer animation (HLSLayerAnimation) describes the changes applied to a layer within an animation step
+ * (HLSLayerAnimationStep). An animation step is the combination of several layer animations applied
+ * to a set of layers, and represent the collective set of changes applied to them during some time interval.
+ * An animation (HLSAnimation) is then simply a collection of animation steps, either view-based
+ * (HLSViewAnimationStep) or layer-based (HLSLayerAnimationStep).
+ *
+ * A layer animation animates layer transforms, not frames. This choice was made because frame animation would
+ * restrict transforms to affine transforms, for which HLSViewAnimation can be used instead (provided the layer
+ * belongs to a view, of course). Moreover, unlike views, layers do not layout their sublayers automatically based
+ * on autoresizing properties on iOS
+ *
+ * Since the layer transform is animated, none of the -[CALayer layoutSublayers] or -[UIView layoutSublayersOfLayer:]
+ * methods need to be implemented for HLSLayerAnimation-based animations.
+ *
+ * In general, and if you do not need to animate view frames to resize subviews during animations, you should
+ * use layer animations instead of view animations since they have far more capabilities.
+ *
+ * Designated initializer: -init (create a layer animation step with default settings)
+ */
+@interface HLSLayerAnimation : HLSObjectAnimation {
+@private
+ HLSVector4 m_rotationParameters;
+ HLSVector3 m_scaleParameters;
+ HLSVector3 m_translationParameters;
+ HLSVector3 m_anchorPointTranslationParameters;
+ HLSVector4 m_sublayerRotationParameters;
+ HLSVector3 m_sublayerScaleParameters;
+ HLSVector3 m_sublayerTranslationParameters;
+ CGFloat m_sublayerCameraTranslationZ;
+ CGFloat m_opacityIncrement;
+ BOOL m_togglingShouldRasterize;
+ CGFloat m_rasterizationScaleIncrement;
+}
+
+/**
+ * Geometric transform parameters to be applied during the layer animation. The resulting transform applies the rotation,
+ * the scale and finally the translation
+ */
+- (void)rotateByAngle:(CGFloat)angle aboutVectorWithX:(CGFloat)x y:(CGFloat)y z:(CGFloat)z;
+- (void)scaleWithXFactor:(CGFloat)xFactor yFactor:(CGFloat)yFactor zFactor:(CGFloat)zFactor;
+- (void)translateByVectorWithX:(CGFloat)x y:(CGFloat)y z:(CGFloat)z;
+
+/**
+ * Same geometric transforms as above, but for transforms in a plane (the most common case)
+ */
+- (void)rotateByAngle:(CGFloat)angle;
+- (void)scaleWithXFactor:(CGFloat)xFactor yFactor:(CGFloat)yFactor;
+- (void)translateByVectorWithX:(CGFloat)x y:(CGFloat)y;
+
+/**
+ * Anchor point translation
+ *
+ * Remark: x and y are in relative coordinates. Refer to the -[CALayer anchorPoint] documentation for more information
+ */
+- (void)translateAnchorPointByVectorWithX:(CGFloat)x y:(CGFloat)y z:(CGFloat)z;
+- (void)translateAnchorPointByVectorWithX:(CGFloat)x y:(CGFloat)y;
+
+/**
+ * Geometric transform parameters to be applied to sublayers during the layer animation
+ */
+- (void)rotateSublayersByAngle:(CGFloat)angle aboutVectorWithX:(CGFloat)x y:(CGFloat)y z:(CGFloat)z;
+- (void)scaleSublayersWithXFactor:(CGFloat)xFactor yFactor:(CGFloat)yFactor zFactor:(CGFloat)zFactor;
+- (void)translateSublayersByVectorWithX:(CGFloat)x y:(CGFloat)y z:(CGFloat)z;
+
+/**
+ * Move the position of the camera from which sublayers are seen. The usual position is (0, 0, 0), which
+ * means no perspective is applied (the sublayers are seen from infinity, i.e. z = infinity). Providing
+ * a non-zero meaningful value for z (usually some factor of the layer or screen dimensions) applies a
+ * 3D perspective to sublayers
+ */
+- (void)translateSublayerCameraByVectorWithZ:(CGFloat)z;
+
+/**
+ * Same geometric transforms as above, but for transforms in a plane (the most common case)
+ */
+- (void)rotateSublayersByAngle:(CGFloat)angle;
+- (void)scaleSublayersWithXFactor:(CGFloat)xFactor yFactor:(CGFloat)yFactor;
+- (void)translateSublayersByVectorWithX:(CGFloat)x y:(CGFloat)y;
+
+/**
+ * Convenience method to calculate the layer animation parameters needed to transform a rect into another one
+ *
+ * Be careful: During an animation, the frame of a layer changes. If you set fromRect to layer.frame, this will be
+ * the frame of the layer at the time the animation is created, not right before the layer animation is performed.
+ * Those might be the same, but in general this is not the case!
+ */
+- (void)transformFromRect:(CGRect)fromRect toRect:(CGRect)toRect;
+
+/**
+ * Opacity increment or decrement to be applied during the layer animation. Any value between 1.f and -1.f can be provided,
+ * though you should ensure that opacity never reaches a value outside [0, 1] during the course of an animation.
+ */
+- (void)addToOpacity:(CGFloat)opacityIncrement;
+
+/**
+ * Whether the shouldRasterize flag should be changed during the animation
+ */
+@property (nonatomic, assign, getter=isTogglingShouldRasterize) BOOL togglingShouldRasterize;
+
+/**
+ * Rasterization scale increment or decrement to be applied during the layer animation. You can use this parameter
+ * to pixelize layers (small rasterization scale value) or to give them a blurry appearance (medium values)
+ */
+- (void)addToRasterizationScale:(CGFloat)rasterizationScaleIncrement;
+
+@end
View
55 PublicHeaders/HLSLayerAnimationStep.h
@@ -0,0 +1,55 @@
+//
+// HLSLayerAnimationStep.h
+// CoconutKit
+//
+// Created by Samuel Défago on 8/21/12.
+// Copyright (c) 2012 Hortis. All rights reserved.
+//
+
+#import "HLSAnimationStep.h"
+#import "HLSLayerAnimation.h"
+
+/**
+ * A layer animation step (HLSLayerAnimationStep) is the combination of several layer animations (HLSLayerAnimation) applied
+ * to a set of layers, and represent the collective set of changes applied to them during some time interval. An animation
+ * (HLSAnimation) is then simply a collection of animation steps, either view-based (HLSViewAnimationStep) or layer-based
+ * (HLSLayerAnimationStep).
+ *
+ * To create a layer animation step, simply instantiate it using the +animationStep class method, then add layer animations
+ * to it, and set its duration and curve
+ *
+ * Designated initializer: -init (create an animation step with default settings)
+ */
+@interface HLSLayerAnimationStep : HLSAnimationStep {
+@private
+ CAMediaTimingFunction *m_timingFunction;
+ UIView *m_dummyView;
+ NSUInteger m_numberOfLayerAnimations;
+ BOOL m_numberOfStartedLayerAnimations;
+ NSUInteger m_numberOfFinishedLayerAnimations;
+ CFTimeInterval m_startTime;
+ CFTimeInterval m_pauseTime;
+ CFTimeInterval m_previousPauseDuration;
+}
+
+/**
+ * Setting a layer animation for a layer. Only one layer animation can be defined at most for a layer within an
+ * animation step. The layer is not retained
+ *
+ * The layer animation is deeply copied to prevent further changes once assigned to a step
+ */
+- (void)addLayerAnimation:(HLSLayerAnimation *)layerAnimation forLayer:(CALayer *)layer;
+
+/**
+ * Convenience method to add a layer animation for a view layer
+ */
+- (void)addLayerAnimation:(HLSLayerAnimation *)layerAnimation forView:(UIView *)view;
+
+/**
+ * The animation timing function to use
+ *
+ * Default value is the function corresponding to the kCAMediaTimingFunctionEaseInEaseOut constant
+ */
+@property (nonatomic, retain) CAMediaTimingFunction *timingFunction;
+
+@end
View
97 PublicHeaders/HLSLogger.h
@@ -0,0 +1,97 @@
+//
+// HLSLogger.h
+// CoconutKit
+//
+// Created by Samuel Défago on 7/14/10.
+// Copyright 2010 Hortis. All rights reserved.
+//
+
+/**
+ * Logging macros. Only active if HLS_LOGGER is added to your configuration preprocessor flags (-DHLS_LOGGER)
+ */
+#ifdef HLS_LOGGER
+
+// Note the ## in front of __VA_ARGS__ to support 0 variable arguments
+#define HLSLoggerDebug(format, ...) [[HLSLogger sharedLogger] debug:[NSString stringWithFormat:@"(%s) - %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:format, ## __VA_ARGS__]]]
+#define HLSLoggerInfo(format, ...) [[HLSLogger sharedLogger] info:[NSString stringWithFormat:@"(%s) - %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:format, ## __VA_ARGS__]]]
+#define HLSLoggerWarn(format, ...) [[HLSLogger sharedLogger] warn:[NSString stringWithFormat:@"(%s) - %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:format, ## __VA_ARGS__]]]
+#define HLSLoggerError(format, ...) [[HLSLogger sharedLogger] error:[NSString stringWithFormat:@"(%s) - %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:format, ## __VA_ARGS__]]]
+#define HLSLoggerFatal(format, ...) [[HLSLogger sharedLogger] fatal:[NSString stringWithFormat:@"(%s) - %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:format, ## __VA_ARGS__]]]
+
+#else
+
+#define HLSLoggerDebug(format, ...)
+#define HLSLoggerInfo(format, ...)
+#define HLSLoggerWarn(format, ...)
+#define HLSLoggerError(format, ...)
+#define HLSLoggerFatal(format, ...)
+
+#endif
+
+/**
+ * Logging levels
+ */
+typedef enum {
+ HLSLoggerLevelEnumBegin = 0,
+ // Values
+ HLSLoggerLevelAll = HLSLoggerLevelEnumBegin,
+ HLSLoggerLevelDebug = HLSLoggerLevelAll,
+ HLSLoggerLevelInfo,
+ HLSLoggerLevelWarn,
+ HLSLoggerLevelError,
+ HLSLoggerLevelFatal,
+ HLSLoggerLevelNone,
+ // End of values
+ HLSLoggerLevelEnumEnd = HLSLoggerLevelNone,
+ HLSLoggerLevelEnumSize = HLSLoggerLevelEnumEnd - HLSLoggerLevelEnumBegin
+} HLSLoggerLevel;
+
+/**
+ * Basic logging facility writing to the console. Thread-safe
+ *
+ * To enable logging, you can use either the release or debug version of this library, the logging code exists in both
+ * (the linker ensures that you do not pay for it if your do not actually use it). To add logging to your project,
+ * use the logging macros above. Those will strip off the logging code for your release builds. Debug builds with
+ * logging enabled must be configured as follows:
+ * - in your project target settings, add -DHLS_LOGGER to the "Other C flags" parameter. This disables logging code