appjam 0.1.8.8 → 0.1.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. data/README.md +22 -62
  2. data/lib/appjam/generators/gist.yml +1 -1
  3. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.pbxproj +1166 -482
  4. data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/xcuserdata/eiffel.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  5. data/lib/appjam/generators/templates/blank/EiffelApplication/EiffelApplication-Prefix.pch.tt +26 -0
  6. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenu.h +52 -0
  7. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenu.m +412 -0
  8. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenuItem.h +44 -0
  9. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenuItem.m +97 -0
  10. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton-highlighted.png +0 -0
  11. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton-highlighted@2x.png +0 -0
  12. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton.png +0 -0
  13. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton@2x.png +0 -0
  14. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem-highlighted.png +0 -0
  15. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem-highlighted@2x.png +0 -0
  16. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem.png +0 -0
  17. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem@2x.png +0 -0
  18. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus-highlighted.png +0 -0
  19. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus-highlighted@2x.png +0 -0
  20. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus.png +0 -0
  21. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus@2x.png +0 -0
  22. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-star.png +0 -0
  23. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-star@2x.png +0 -0
  24. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/CMPopTipView/CMPopTipView.h +167 -0
  25. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/CMPopTipView/CMPopTipView.m +639 -0
  26. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.h +97 -0
  27. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.m +1080 -0
  28. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MBProgressHUD/MBProgressHUD.h +451 -0
  29. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MBProgressHUD/MBProgressHUD.m +865 -0
  30. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FacingView.h +42 -0
  31. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FacingView.m +56 -0
  32. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FoldView.h +90 -0
  33. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FoldView.m +316 -0
  34. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/MultiFoldView.h +104 -0
  35. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/MultiFoldView.m +516 -0
  36. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldConstants.h +49 -0
  37. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldNavigationController.h +18 -0
  38. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldNavigationController.m +88 -0
  39. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_left.png +0 -0
  40. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_left@2x.png +0 -0
  41. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_right.png +0 -0
  42. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_right@2x.png +0 -0
  43. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldSwipeHintView.h +25 -0
  44. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldSwipeHintView.m +76 -0
  45. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldView.h +131 -0
  46. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldView.m +941 -0
  47. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/Resources/swipe_guide.psd +0 -0
  48. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/Resources/swipe_guide2.psd +0 -0
  49. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/ShadowView.h +46 -0
  50. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/ShadowView.m +82 -0
  51. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/TouchThroughUIView.h +39 -0
  52. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/TouchThroughUIView.m +72 -0
  53. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/UIView+Screenshot.h +42 -0
  54. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/UIView+Screenshot.m +100 -0
  55. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/NSBubbleData.h +34 -0
  56. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/NSBubbleData.m +140 -0
  57. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleHeaderTableViewCell.h +17 -0
  58. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleHeaderTableViewCell.m +57 -0
  59. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableView.h +30 -0
  60. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableView.m +233 -0
  61. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewCell.h +19 -0
  62. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewCell.m +122 -0
  63. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewDataSource.h +24 -0
  64. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTypingTableViewCell.h +20 -0
  65. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTypingTableViewCell.m +56 -0
  66. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleMine.png +0 -0
  67. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleMine@2x.png +0 -0
  68. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleSomeone.png +0 -0
  69. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleSomeone@2x.png +0 -0
  70. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/missingAvatar.png +0 -0
  71. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/missingAvatar@2x.png +0 -0
  72. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingMine.png +0 -0
  73. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingMine@2x.png +0 -0
  74. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingSomeone.png +0 -0
  75. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingSomeone@2x.png +0 -0
  76. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIGlossyButton.h +124 -0
  77. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIGlossyButton.m +545 -0
  78. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIView+LayerEffects.h +22 -0
  79. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIView+LayerEffects.m +32 -0
  80. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFIncrementalStore.h +344 -0
  81. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFIncrementalStore.m +848 -0
  82. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFRESTClient.h +135 -0
  83. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFRESTClient.m +441 -0
  84. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/NSString+InflectorKit.h +40 -0
  85. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/NSString+InflectorKit.m +36 -0
  86. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/TTTStringInflector.h +76 -0
  87. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/TTTStringInflector.m +270 -0
  88. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/MKAnnotationView+WebCache.h +95 -0
  89. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/MKAnnotationView+WebCache.m +78 -0
  90. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDImageCache.h +144 -0
  91. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDImageCache.m +311 -0
  92. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageCompat.h +40 -0
  93. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageCompat.m +54 -0
  94. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDecoder.h +18 -0
  95. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDecoder.m +70 -0
  96. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloader.h +102 -0
  97. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloader.m +226 -0
  98. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloaderOperation.h +25 -0
  99. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloaderOperation.m +339 -0
  100. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageManager.h +167 -0
  101. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageManager.m +244 -0
  102. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageOperation.h +15 -0
  103. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImagePrefetcher.h +58 -0
  104. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImagePrefetcher.m +127 -0
  105. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIButton+WebCache.h +173 -0
  106. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIButton+WebCache.m +129 -0
  107. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIImageView+WebCache.h +140 -0
  108. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIImageView+WebCache.m +84 -0
  109. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationProgram.h +28 -0
  110. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationSequence.h +28 -0
  111. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationStep.h +49 -0
  112. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationProgram.m +100 -0
  113. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationSequence.m +85 -0
  114. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationStep.m +122 -0
  115. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaAsyncSocket/GCDAsyncSocket.h +1074 -0
  116. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaAsyncSocket/GCDAsyncSocket.m +7430 -0
  117. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDData.h +14 -0
  118. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDData.m +158 -0
  119. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDNumber.h +12 -0
  120. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDNumber.m +88 -0
  121. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDRange.h +56 -0
  122. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDRange.m +104 -0
  123. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPAuthenticationRequest.h +45 -0
  124. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPAuthenticationRequest.m +195 -0
  125. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPConnection.h +119 -0
  126. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPConnection.m +2708 -0
  127. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPLogging.h +136 -0
  128. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPMessage.h +48 -0
  129. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPMessage.m +113 -0
  130. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPResponse.h +149 -0
  131. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPServer.h +205 -0
  132. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPServer.m +772 -0
  133. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.h +65 -0
  134. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.m +529 -0
  135. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.h +33 -0
  136. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.m +86 -0
  137. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.h +23 -0
  138. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.m +211 -0
  139. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.h +75 -0
  140. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.m +405 -0
  141. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDataResponse.h +13 -0
  142. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDataResponse.m +79 -0
  143. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.h +52 -0
  144. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.m +292 -0
  145. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.h +9 -0
  146. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.m +38 -0
  147. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPFileResponse.h +25 -0
  148. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m +237 -0
  149. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.h +12 -0
  150. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.m +73 -0
  151. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/WebSocket.h +105 -0
  152. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/WebSocket.m +791 -0
  153. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.h +7 -0
  154. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.m +160 -0
  155. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.h +11 -0
  156. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.m +372 -0
  157. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.h +7 -0
  158. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.m +49 -0
  159. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.h +8 -0
  160. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.m +69 -0
  161. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHpple.h +54 -0
  162. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHpple.m +102 -0
  163. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHppleElement.h +103 -0
  164. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHppleElement.m +200 -0
  165. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/XPathQuery.h +10 -0
  166. data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/XPathQuery.m +197 -0
  167. data/lib/appjam/version.rb +1 -1
  168. metadata +164 -3
@@ -0,0 +1,97 @@
1
+ //
2
+ // FXLabel.h
3
+ //
4
+ // Version 1.5 beta
5
+ //
6
+ // Created by Nick Lockwood on 20/08/2011.
7
+ // Copyright 2011 Charcoal Design
8
+ //
9
+ // Distributed under the permissive zlib license
10
+ // Get the latest version from here:
11
+ //
12
+ // https://github.com/nicklockwood/FXLabel
13
+ //
14
+ // This software is provided 'as-is', without any express or implied
15
+ // warranty. In no event will the authors be held liable for any damages
16
+ // arising from the use of this software.
17
+ //
18
+ // Permission is granted to anyone to use this software for any purpose,
19
+ // including commercial applications, and to alter it and redistribute it
20
+ // freely, subject to the following restrictions:
21
+ //
22
+ // 1. The origin of this software must not be misrepresented; you must not
23
+ // claim that you wrote the original software. If you use this software
24
+ // in a product, an acknowledgment in the product documentation would be
25
+ // appreciated but is not required.
26
+ //
27
+ // 2. Altered source versions must be plainly marked as such, and must not be
28
+ // misrepresented as being the original software.
29
+ //
30
+ // 3. This notice may not be removed or altered from any source distribution.
31
+ //
32
+
33
+
34
+ #import <UIKit/UIKit.h>
35
+
36
+
37
+ @interface NSString (FXLabelDrawing)
38
+
39
+ - (CGSize)sizeWithFont:(UIFont *)font
40
+ minFontSize:(CGFloat)minFontSize
41
+ actualFontSize:(CGFloat *)actualFontSize
42
+ forWidth:(CGFloat)width
43
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
44
+ characterSpacing:(CGFloat)characterSpacing
45
+ kerningTable:(NSDictionary *)kerningTable;
46
+
47
+ - (CGSize)drawAtPoint:(CGPoint)point
48
+ forWidth:(CGFloat)width
49
+ withFont:(UIFont *)font
50
+ minFontSize:(CGFloat)minFontSize
51
+ actualFontSize:(CGFloat *)actualFontSize
52
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
53
+ baselineAdjustment:(UIBaselineAdjustment)baselineAdjustment
54
+ characterSpacing:(CGFloat)characterSpacing
55
+ kerningTable:(NSDictionary *)kerningTable;
56
+
57
+ - (CGSize)sizeWithFont:(UIFont *)font
58
+ constrainedToSize:(CGSize)size
59
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
60
+ lineSpacing:(CGFloat)lineSpacing
61
+ characterSpacing:(CGFloat)characterSpacing
62
+ kerningTable:(NSDictionary *)kerningTable
63
+ allowOrphans:(BOOL)allowOrphans;
64
+
65
+ - (CGSize)drawInRect:(CGRect)rect
66
+ withFont:(UIFont *)font
67
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
68
+ alignment:(NSTextAlignment)alignment
69
+ lineSpacing:(CGFloat)lineSpacing
70
+ characterSpacing:(CGFloat)characterSpacing
71
+ kerningTable:(NSDictionary *)kerningTable
72
+ allowOrphans:(BOOL)allowOrphans;
73
+ @end
74
+
75
+
76
+ @interface FXLabel : UILabel
77
+
78
+ @property (nonatomic) CGFloat shadowBlur;
79
+ @property (nonatomic) CGFloat innerShadowBlur;
80
+ @property (nonatomic) CGSize innerShadowOffset;
81
+ @property (nonatomic, strong) UIColor *innerShadowColor;
82
+ @property (nonatomic, strong) UIColor *gradientStartColor;
83
+ @property (nonatomic, strong) UIColor *gradientEndColor;
84
+ @property (nonatomic, copy) NSArray *gradientColors;
85
+ @property (nonatomic) CGPoint gradientStartPoint;
86
+ @property (nonatomic) CGPoint gradientEndPoint;
87
+ @property (nonatomic) NSUInteger oversampling;
88
+ @property (nonatomic) UIEdgeInsets textInsets;
89
+ @property (nonatomic) CGFloat lineSpacing;
90
+ @property (nonatomic) CGFloat characterSpacing;
91
+ @property (nonatomic) CGFloat baselineOffset;
92
+ @property (nonatomic, copy) NSDictionary *kerningTable;
93
+ @property (nonatomic) BOOL allowOrphans;
94
+
95
+ - (void)setUp;
96
+
97
+ @end
@@ -0,0 +1,1080 @@
1
+ //
2
+ // FXLabel.m
3
+ //
4
+ // Version 1.5 beta
5
+ //
6
+ // Created by Nick Lockwood on 20/08/2011.
7
+ // Copyright 2011 Charcoal Design
8
+ //
9
+ // Distributed under the permissive zlib license
10
+ // Get the latest version from here:
11
+ //
12
+ // https://github.com/nicklockwood/FXLabel
13
+ //
14
+ // This software is provided 'as-is', without any express or implied
15
+ // warranty. In no event will the authors be held liable for any damages
16
+ // arising from the use of this software.
17
+ //
18
+ // Permission is granted to anyone to use this software for any purpose,
19
+ // including commercial applications, and to alter it and redistribute it
20
+ // freely, subject to the following restrictions:
21
+ //
22
+ // 1. The origin of this software must not be misrepresented; you must not
23
+ // claim that you wrote the original software. If you use this software
24
+ // in a product, an acknowledgment in the product documentation would be
25
+ // appreciated but is not required.
26
+ //
27
+ // 2. Altered source versions must be plainly marked as such, and must not be
28
+ // misrepresented as being the original software.
29
+ //
30
+ // 3. This notice may not be removed or altered from any source distribution.
31
+ //
32
+
33
+
34
+ #import "FXLabel.h"
35
+
36
+
37
+ #import <Availability.h>
38
+ #if !__has_feature(objc_arc)
39
+ #error This class requires automatic reference counting
40
+ #endif
41
+
42
+
43
+ @implementation NSString (FXLabelDrawing)
44
+
45
+ - (CGContextRef)FXLabel_sizingContext
46
+ {
47
+ static CGContextRef context = NULL;
48
+ if (!context)
49
+ {
50
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
51
+ context = CGBitmapContextCreate(NULL, 1, 1, 8, 0, colorSpace, 0);
52
+ CGContextSetTextDrawingMode(context, kCGTextInvisible);
53
+ CGColorSpaceRelease(colorSpace);
54
+ }
55
+ return context;
56
+ }
57
+
58
+ - (BOOL)FXLabel_isPunctuation
59
+ {
60
+ return [[NSSet setWithObjects:
61
+ @"-", //hyphen
62
+ @"–", //en-dash
63
+ @"—", //em-dash
64
+ @";",
65
+ nil] containsObject:self];
66
+ }
67
+
68
+ - (NSArray *)FXLabel_characters
69
+ {
70
+ NSUInteger length = [self length];
71
+ NSMutableArray *characters = [NSMutableArray arrayWithCapacity:length];
72
+ for (NSUInteger i = 0; i < length; i++)
73
+ {
74
+ NSRange range = [self rangeOfComposedCharacterSequenceAtIndex:i];
75
+ [characters addObject:[self substringWithRange:range]];
76
+ i += range.length - 1;
77
+ }
78
+ return characters;
79
+ }
80
+
81
+ - (NSArray *)FXLabel_linesWithFont:(UIFont *)font
82
+ constrainedToSize:(CGSize)size
83
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
84
+ lineSpacing:(CGFloat)lineSpacing
85
+ characterSpacing:(CGFloat)characterSpacing
86
+ kerningTable:(NSDictionary *)kerningTable
87
+ allowOrphans:(BOOL)allowOrphans
88
+ {
89
+ NSInteger index = 0;
90
+ NSMutableArray *lines = [NSMutableArray array];
91
+ if (lineBreakMode == NSLineBreakByCharWrapping)
92
+ {
93
+ //split text into individual characters
94
+ NSArray *characters = [self FXLabel_characters];
95
+
96
+ //calculate lines
97
+ while (index < [characters count])
98
+ {
99
+ NSInteger lineCount = [lines count];
100
+ if (lineCount && ((lineCount + 1) * font.lineHeight + lineCount * font.pointSize * lineSpacing) > size.height)
101
+ {
102
+ //append remaining text to last line
103
+ NSArray *remainingChars = [characters subarrayWithRange:NSMakeRange(index, [characters count] - index)];
104
+ NSString *line = [lines lastObject];
105
+ NSString *newLine = [line length]? line: @"";
106
+ newLine = [newLine stringByAppendingString:[remainingChars componentsJoinedByString:@""]];
107
+ [lines replaceObjectAtIndex:lineCount - 1 withObject:newLine];
108
+ break;
109
+ }
110
+ NSString *line = nil;
111
+ for (int i = index; i < [characters count]; i++)
112
+ {
113
+ NSString *character = characters[i];
114
+ NSString *newLine = line? [line stringByAppendingString:character]: character;
115
+ CGFloat lineWidth = [newLine sizeWithFont:font
116
+ minFontSize:font.pointSize
117
+ actualFontSize:NULL
118
+ forWidth:INFINITY
119
+ lineBreakMode:lineBreakMode
120
+ characterSpacing:characterSpacing
121
+ kerningTable:kerningTable].width;
122
+
123
+ if ([character isEqualToString:@"\n"])
124
+ {
125
+ //add line and prepare for next
126
+ [lines addObject:line ?: @""];
127
+ index = i + 1;
128
+ break;
129
+ }
130
+ else if (lineWidth > size.width && line)
131
+ {
132
+ //add line and prepare for next
133
+ [lines addObject:line];
134
+ index = i;
135
+ break;
136
+ }
137
+ else if (i == [characters count] - 1)
138
+ {
139
+ //add line and finish
140
+ [lines addObject:newLine];
141
+ index = i + 1;
142
+ break;
143
+ }
144
+ else
145
+ {
146
+ //continue
147
+ line = newLine;
148
+ }
149
+ }
150
+ }
151
+ }
152
+ else
153
+ {
154
+ //split text into words
155
+ NSString *text = [self stringByReplacingOccurrencesOfString:@"\t" withString:@" "];
156
+ text = [text stringByReplacingOccurrencesOfString:@"\n" withString:@" \n "];
157
+ NSArray *words = [text componentsSeparatedByString:@" "];
158
+ words = [words filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"length > 0"]];
159
+
160
+ //calculate lines
161
+ while (index < [words count])
162
+ {
163
+ NSInteger lineCount = [lines count];
164
+ if (lineCount && ((lineCount + 1) * font.lineHeight + lineCount * font.pointSize * lineSpacing) > size.height)
165
+ {
166
+ //append remaining text to last line
167
+ NSArray *remainingWords = [words subarrayWithRange:NSMakeRange(index, [words count] - index)];
168
+ NSString *line = [lines lastObject];
169
+ NSString *newLine = [line length]? [line stringByAppendingString:@" "]: @"";
170
+ newLine = [newLine stringByAppendingString:[remainingWords componentsJoinedByString:@" "]];
171
+ newLine = [newLine stringByReplacingOccurrencesOfString:@"\n " withString:@"\n"];
172
+ newLine = [newLine stringByReplacingOccurrencesOfString:@" \n" withString:@"\n"];
173
+ [lines replaceObjectAtIndex:lineCount - 1 withObject:newLine];
174
+ break;
175
+ }
176
+ NSString *line = nil;
177
+ for (int i = index; i < [words count]; i++)
178
+ {
179
+ NSString *word = words[i];
180
+ NSString *newLine = line? [line stringByAppendingFormat:@" %@", word]: word;
181
+ CGFloat lineWidth = [newLine sizeWithFont:font
182
+ minFontSize:font.pointSize
183
+ actualFontSize:NULL
184
+ forWidth:INFINITY
185
+ lineBreakMode:lineBreakMode
186
+ characterSpacing:characterSpacing
187
+ kerningTable:kerningTable].width;
188
+
189
+ if ([word isEqualToString:@"\n"])
190
+ {
191
+ //add line and prepare for next
192
+ [lines addObject:line ?: @""];
193
+ index = i + 1;
194
+ break;
195
+ }
196
+ else if (lineWidth > size.width && line)
197
+ {
198
+ //check for orphans
199
+ if (!allowOrphans && i > 0 &&
200
+ (i == [words count] - 1 || [words[i + 1] isEqualToString:@"\n"]) &&
201
+ ![words[i - 1] FXLabel_isPunctuation])
202
+ {
203
+ //force line break
204
+ NSRange range = [line rangeOfString:@" " options:NSBackwardsSearch];
205
+ if (range.location != NSNotFound)
206
+ {
207
+ line = [line substringToIndex:range.location];
208
+ i --;
209
+ }
210
+ }
211
+
212
+ //add line and prepare for next
213
+ [lines addObject:line];
214
+ index = i;
215
+ break;
216
+ }
217
+ else if (i == [words count] - 1)
218
+ {
219
+ //add line and finish
220
+ [lines addObject:newLine];
221
+ index = i + 1;
222
+ break;
223
+ }
224
+ else
225
+ {
226
+ //continue
227
+ line = newLine;
228
+ }
229
+ }
230
+ }
231
+ }
232
+ return lines;
233
+ }
234
+
235
+ - (CGSize)FXLabel_sizeWithFont:(UIFont *)font
236
+ minFontSize:(CGFloat)minFontSize
237
+ actualFontSize:(CGFloat *)actualFontSize
238
+ forWidth:(CGFloat)width
239
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
240
+ characterSpacing:(CGFloat)characterSpacing
241
+ kerningTable:(NSDictionary *)kerningTable
242
+ charactersFitted:(NSInteger *)charactersFitted
243
+ includesEllipsis:(BOOL *)includesEllipsis
244
+ {
245
+ UIGraphicsPushContext([self FXLabel_sizingContext]);
246
+
247
+ if (includesEllipsis) *includesEllipsis = NO;
248
+ minFontSize = minFontSize ?: font.pointSize;
249
+ UIFont *subFont = font;
250
+ while (true)
251
+ {
252
+ //TODO: doesn't correctly handle head or center truncation
253
+
254
+ int i = 0;
255
+ CGFloat x = 0.0f;
256
+ NSArray *characters = [self FXLabel_characters];
257
+ NSInteger charCount = [characters count];
258
+ NSMutableArray *widths = [NSMutableArray arrayWithCapacity:charCount];
259
+ for (i = 0; i < [characters count]; i++)
260
+ {
261
+ //get character width
262
+ NSString *character = characters[i];
263
+ CGFloat charWidth = [character drawAtPoint:CGPointZero withFont:subFont].width;
264
+ if (i == charCount - 1 || x + charWidth > width)
265
+ {
266
+ [widths addObject:@(charWidth)];
267
+ x += charWidth;
268
+ break;
269
+ }
270
+ else
271
+ {
272
+ charWidth += ([kerningTable[character] floatValue] + characterSpacing) * subFont.pointSize;
273
+ [widths addObject:@(charWidth)];
274
+ x += charWidth;
275
+ }
276
+ }
277
+ if (floorf(x) <= ceilf(width))
278
+ {
279
+ //the text fits, return size
280
+ UIGraphicsPopContext();
281
+ if (actualFontSize) *actualFontSize = subFont.pointSize;
282
+ if (charactersFitted) *charactersFitted = charCount;
283
+ return CGSizeMake(x, font.lineHeight);
284
+ }
285
+ else if (subFont.pointSize == minFontSize)
286
+ {
287
+ //text is truncated
288
+ if (lineBreakMode == NSLineBreakByClipping)
289
+ {
290
+ //subtract width of last character
291
+ x -= [[widths lastObject] floatValue];
292
+
293
+ UIGraphicsPopContext();
294
+ if (actualFontSize) *actualFontSize = subFont.pointSize;
295
+ if (charactersFitted) *charactersFitted = i + 1;
296
+ return CGSizeMake(x, font.lineHeight);
297
+ }
298
+ else
299
+ {
300
+ //allow space for ellipsis
301
+ CGFloat ellipsisWidth = [@"…" sizeWithFont:subFont].width;
302
+ if (ellipsisWidth > width)
303
+ {
304
+ //can't fit any text at all
305
+ UIGraphicsPopContext();
306
+ if (actualFontSize) *actualFontSize = subFont.pointSize;
307
+ if (charactersFitted) *charactersFitted = 0;
308
+ return CGSizeMake(0.0f, font.lineHeight);
309
+ }
310
+ else
311
+ {
312
+ //remove enough characters to allow space for ellipsis
313
+ for (i = [widths count] - 1; i >= 0; i--)
314
+ {
315
+ x -= [widths[i] floatValue];
316
+ if (x + ellipsisWidth <= width) break;
317
+ }
318
+ UIGraphicsPopContext();
319
+ if (actualFontSize) *actualFontSize = subFont.pointSize;
320
+ if (charactersFitted) *charactersFitted = MAX(0, i);
321
+ if (includesEllipsis) *includesEllipsis = YES;
322
+ return CGSizeMake(x + ellipsisWidth, font.lineHeight);
323
+ }
324
+ }
325
+ }
326
+ else
327
+ {
328
+ //try again with the next point size
329
+ CGFloat pointSize = MAX(minFontSize, subFont.pointSize - 1.0f);
330
+ subFont = [font fontWithSize:pointSize];
331
+ }
332
+ }
333
+ }
334
+
335
+ - (CGSize)sizeWithFont:(UIFont *)font
336
+ minFontSize:(CGFloat)minFontSize
337
+ actualFontSize:(CGFloat *)actualFontSize
338
+ forWidth:(CGFloat)width
339
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
340
+ characterSpacing:(CGFloat)characterSpacing
341
+ kerningTable:(NSDictionary *)kerningTable
342
+ {
343
+ if (characterSpacing || [kerningTable count])
344
+ {
345
+ CGSize size = [self FXLabel_sizeWithFont:font
346
+ minFontSize:minFontSize
347
+ actualFontSize:actualFontSize
348
+ forWidth:width
349
+ lineBreakMode:lineBreakMode
350
+ characterSpacing:characterSpacing
351
+ kerningTable:kerningTable
352
+ charactersFitted:NULL
353
+ includesEllipsis:NULL];
354
+
355
+ //round up size to nearest point like normal NSString size functions do
356
+ return CGSizeMake(ceilf(size.width), ceilf(size.height));
357
+ }
358
+ else
359
+ {
360
+ //use standard implementation
361
+ return [self sizeWithFont:font
362
+ minFontSize:minFontSize
363
+ actualFontSize:actualFontSize
364
+ forWidth:width
365
+ lineBreakMode:lineBreakMode];
366
+ }
367
+ }
368
+
369
+ - (CGSize)drawAtPoint:(CGPoint)point
370
+ forWidth:(CGFloat)width
371
+ withFont:(UIFont *)font
372
+ minFontSize:(CGFloat)minFontSize
373
+ actualFontSize:(CGFloat *)actualFontSize
374
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
375
+ baselineAdjustment:(UIBaselineAdjustment)baselineAdjustment
376
+ characterSpacing:(CGFloat)characterSpacing
377
+ kerningTable:(NSDictionary *)kerningTable
378
+ {
379
+ if (characterSpacing || [kerningTable count])
380
+ {
381
+ //TODO: draw text to image and then paste into context to avoid overlap issues
382
+ //TODO: doesn't correctly handle head or center truncation
383
+
384
+ NSInteger charactersFitted = 0;
385
+ BOOL includesEllipsis = NO;
386
+ CGFloat fontSize = font.pointSize;
387
+ CGSize size = [self FXLabel_sizeWithFont:font
388
+ minFontSize:minFontSize
389
+ actualFontSize:&fontSize
390
+ forWidth:width
391
+ lineBreakMode:lineBreakMode
392
+ characterSpacing:characterSpacing
393
+ kerningTable:kerningTable
394
+ charactersFitted:&charactersFitted
395
+ includesEllipsis:&includesEllipsis];
396
+
397
+ CGFloat y = point.y;
398
+ UIFont *subFont = [font fontWithSize:fontSize];
399
+ if (fontSize < font.pointSize)
400
+ {
401
+ switch (baselineAdjustment)
402
+ {
403
+ case UIBaselineAdjustmentAlignCenters:
404
+ {
405
+ y += (font.lineHeight - subFont.lineHeight) / 2.0f;
406
+ break;
407
+ }
408
+ case UIBaselineAdjustmentAlignBaselines:
409
+ {
410
+ y += (font.ascender - subFont.ascender);
411
+ break;
412
+ }
413
+ case UIBaselineAdjustmentNone:
414
+ default:
415
+ {
416
+ //no adjustment needed
417
+ break;
418
+ }
419
+ }
420
+ }
421
+
422
+ CGFloat x = point.x;
423
+ for (int i = 0; i < charactersFitted; i++)
424
+ {
425
+ NSString *character = [self substringWithRange:NSMakeRange(i, 1)];
426
+ CGFloat charWidth = [character drawAtPoint:CGPointMake(x, y) withFont:subFont].width;
427
+ x += charWidth + ([kerningTable[character] floatValue] + characterSpacing) * subFont.pointSize;
428
+ }
429
+ if (includesEllipsis)
430
+ {
431
+ [@"…" drawAtPoint:CGPointMake(x, point.y) withFont:subFont];
432
+ }
433
+
434
+ if (actualFontSize) *actualFontSize = fontSize;
435
+ return size;
436
+ }
437
+ else
438
+ {
439
+ //use standard implementation
440
+ return [self drawAtPoint:point
441
+ forWidth:width
442
+ withFont:font
443
+ minFontSize:minFontSize
444
+ actualFontSize:actualFontSize
445
+ lineBreakMode:lineBreakMode
446
+ baselineAdjustment:baselineAdjustment];
447
+ }
448
+ }
449
+
450
+ - (CGSize)sizeWithFont:(UIFont *)font
451
+ constrainedToSize:(CGSize)size
452
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
453
+ lineSpacing:(CGFloat)lineSpacing
454
+ characterSpacing:(CGFloat)characterSpacing
455
+ kerningTable:(NSDictionary *)kerningTable
456
+ allowOrphans:(BOOL)allowOrphans
457
+ {
458
+ if (lineSpacing || characterSpacing || [kerningTable count] || !allowOrphans)
459
+ {
460
+ NSArray *lines = [self FXLabel_linesWithFont:font
461
+ constrainedToSize:size
462
+ lineBreakMode:lineBreakMode
463
+ lineSpacing:lineSpacing
464
+ characterSpacing:characterSpacing
465
+ kerningTable:kerningTable
466
+ allowOrphans:allowOrphans];
467
+ CGSize total = CGSizeZero;
468
+ total.height = ceilf(MIN(size.height, [lines count] * font.lineHeight + ([lines count] - 1) * roundf(font.pointSize *lineSpacing)));
469
+ for (NSString *line in lines)
470
+ {
471
+ total.width = ceilf(MAX(total.width, [line sizeWithFont:font
472
+ minFontSize:font.pointSize
473
+ actualFontSize:NULL
474
+ forWidth:size.width
475
+ lineBreakMode:lineBreakMode
476
+ characterSpacing:characterSpacing
477
+ kerningTable:kerningTable].width));
478
+ }
479
+ return total;
480
+ }
481
+ else
482
+ {
483
+ //use standard implementation
484
+ return [self sizeWithFont:font
485
+ constrainedToSize:size
486
+ lineBreakMode:lineBreakMode];
487
+ }
488
+ }
489
+
490
+ - (CGSize)drawInRect:(CGRect)rect
491
+ withFont:(UIFont *)font
492
+ lineBreakMode:(NSLineBreakMode)lineBreakMode
493
+ alignment:(NSTextAlignment)alignment
494
+ lineSpacing:(CGFloat)lineSpacing
495
+ characterSpacing:(CGFloat)characterSpacing
496
+ kerningTable:(NSDictionary *)kerningTable
497
+ allowOrphans:(BOOL)allowOrphans
498
+ {
499
+ if (lineSpacing || characterSpacing || [kerningTable count] || !allowOrphans)
500
+ {
501
+ //TODO: draw text to image and then paste into context to avoid overlap issues
502
+
503
+ NSArray *lines = [self FXLabel_linesWithFont:font
504
+ constrainedToSize:rect.size
505
+ lineBreakMode:lineBreakMode
506
+ lineSpacing:lineSpacing
507
+ characterSpacing:characterSpacing
508
+ kerningTable:kerningTable
509
+ allowOrphans:allowOrphans];
510
+ CGSize total = CGSizeZero;
511
+ total.height = [lines count] * font.lineHeight + ([lines count] - 1) * roundf(font.pointSize * lineSpacing);
512
+ CGPoint offset = rect.origin;
513
+ for (NSString *line in lines)
514
+ {
515
+ CGSize size = [line sizeWithFont:font
516
+ minFontSize:font.pointSize
517
+ actualFontSize:NULL
518
+ forWidth:CGRectGetWidth(rect)
519
+ lineBreakMode:lineBreakMode
520
+ characterSpacing:characterSpacing
521
+ kerningTable:kerningTable];
522
+
523
+ if (alignment == NSTextAlignmentCenter)
524
+ {
525
+ offset.x = roundf(rect.origin.x + (CGRectGetWidth(rect) - size.width)/ 2.0f);
526
+ }
527
+ else if (alignment == NSTextAlignmentRight)
528
+ {
529
+ offset.x = roundf(rect.origin.x + (CGRectGetWidth(rect) - size.width));
530
+ }
531
+ [line drawAtPoint:offset
532
+ forWidth:CGRectGetWidth(rect)
533
+ withFont:font
534
+ minFontSize:font.pointSize
535
+ actualFontSize:NULL
536
+ lineBreakMode:lineBreakMode
537
+ baselineAdjustment:UIBaselineAdjustmentAlignBaselines
538
+ characterSpacing:characterSpacing
539
+ kerningTable:kerningTable];
540
+
541
+ total.width = MAX(total.width, offset.x + size.width);
542
+ offset.y += roundf(font.lineHeight + font.pointSize * lineSpacing);
543
+ }
544
+ return total;
545
+ }
546
+ else
547
+ {
548
+ //use standard implementation
549
+ return [self drawInRect:rect
550
+ withFont:font
551
+ lineBreakMode:lineBreakMode
552
+ alignment:alignment];
553
+ }
554
+ }
555
+
556
+ @end
557
+
558
+
559
+ @interface FXLabel ()
560
+
561
+ @property (nonatomic, assign) NSUInteger minSamples;
562
+ @property (nonatomic, assign) NSUInteger maxSamples;
563
+
564
+ @end
565
+
566
+
567
+ @implementation FXLabel
568
+
569
+ @synthesize shadowBlur; //no leading _ to avoid conflict with private property
570
+
571
+ - (void)setUp
572
+ {
573
+ _gradientStartPoint = CGPointMake(0.5f, 0.0f);
574
+ _gradientEndPoint = CGPointMake(0.5f, 0.75f);
575
+ _minSamples = _maxSamples = 1;
576
+ if ([UIScreen instancesRespondToSelector:@selector(scale)])
577
+ {
578
+ _minSamples = [UIScreen mainScreen].scale;
579
+ _maxSamples = 32;
580
+ }
581
+ _oversampling = _minSamples;
582
+ _allowOrphans = YES;
583
+ }
584
+
585
+ - (id)initWithFrame:(CGRect)frame
586
+ {
587
+ if ((self = [super initWithFrame:frame]))
588
+ {
589
+ self.backgroundColor = nil;
590
+ [self setUp];
591
+ }
592
+ return self;
593
+ }
594
+
595
+ - (id)initWithCoder:(NSCoder *)aDecoder
596
+ {
597
+ if ((self = [super initWithCoder:aDecoder]))
598
+ {
599
+ [self setUp];
600
+ }
601
+ return self;
602
+ }
603
+
604
+ - (void)setShadowBlur:(CGFloat)blur
605
+ {
606
+ if (shadowBlur != blur)
607
+ {
608
+ shadowBlur = blur;
609
+ [self setNeedsDisplay];
610
+ }
611
+ }
612
+
613
+ - (void)setInnerShadowBlur:(CGFloat)blur
614
+ {
615
+ if (_innerShadowBlur != blur)
616
+ {
617
+ _innerShadowBlur = blur;
618
+ [self setNeedsDisplay];
619
+ }
620
+ }
621
+
622
+ - (void)setInnerShadowOffset:(CGSize)offset
623
+ {
624
+ if (!CGSizeEqualToSize(_innerShadowOffset, offset))
625
+ {
626
+ _innerShadowOffset = offset;
627
+ [self setNeedsDisplay];
628
+ }
629
+ }
630
+
631
+ - (void)setInnerShadowColor:(UIColor *)color
632
+ {
633
+ if (_innerShadowColor != color)
634
+ {
635
+ _innerShadowColor = color;
636
+ [self setNeedsDisplay];
637
+ }
638
+ }
639
+
640
+ - (UIColor *)gradientStartColor
641
+ {
642
+ return [_gradientColors count]? _gradientColors[0]: nil;
643
+ }
644
+
645
+ - (void)setGradientStartColor:(UIColor *)color
646
+ {
647
+ if (color == nil)
648
+ {
649
+ self.gradientColors = nil;
650
+ }
651
+ else if ([_gradientColors count] < 2)
652
+ {
653
+ self.gradientColors = @[color, color];
654
+ }
655
+ else if (_gradientColors[0] != color)
656
+ {
657
+ NSMutableArray *colors = [NSMutableArray arrayWithArray:_gradientColors];
658
+ colors[0] = color;
659
+ self.gradientColors = colors;
660
+ }
661
+ }
662
+
663
+ - (UIColor *)gradientEndColor
664
+ {
665
+ return [_gradientColors lastObject];
666
+ }
667
+
668
+ - (void)setGradientEndColor:(UIColor *)color
669
+ {
670
+ if (color == nil)
671
+ {
672
+ self.gradientColors = nil;
673
+ }
674
+ else if ([_gradientColors count] < 2)
675
+ {
676
+ self.gradientColors = @[color, color];
677
+ }
678
+ else if ([_gradientColors lastObject] != color)
679
+ {
680
+ NSMutableArray *colors = [NSMutableArray arrayWithArray:_gradientColors];
681
+ colors[[colors count] - 1] = color;
682
+ self.gradientColors = colors;
683
+ }
684
+ }
685
+
686
+ - (void)setGradientColors:(NSArray *)colors
687
+ {
688
+ if (_gradientColors != colors)
689
+ {
690
+ _gradientColors = [colors copy];
691
+ [self setNeedsDisplay];
692
+ }
693
+ }
694
+
695
+ - (void)setOversampling:(NSUInteger)samples
696
+ {
697
+ samples = MIN(_maxSamples, MAX(_minSamples, samples));
698
+ if (_oversampling != samples)
699
+ {
700
+ _oversampling = samples;
701
+ [self setNeedsDisplay];
702
+ }
703
+ }
704
+
705
+ - (void)setTextInsets:(UIEdgeInsets)insets
706
+ {
707
+ if (!UIEdgeInsetsEqualToEdgeInsets(_textInsets, insets))
708
+ {
709
+ _textInsets = insets;
710
+ [self setNeedsDisplay];
711
+ }
712
+ }
713
+
714
+ - (void)setLineSpacing:(CGFloat)lineSpacing
715
+ {
716
+ if (_lineSpacing != lineSpacing)
717
+ {
718
+ _lineSpacing = lineSpacing;
719
+ [self setNeedsDisplay];
720
+ }
721
+ }
722
+
723
+ - (void)setCharacterSpacing:(CGFloat)characterSpacing
724
+ {
725
+ if (_characterSpacing != characterSpacing)
726
+ {
727
+ _characterSpacing = characterSpacing;
728
+ [self setNeedsDisplay];
729
+ }
730
+ }
731
+
732
+ - (void)setBaselineOffset:(CGFloat)baselineOffset
733
+ {
734
+ if (_baselineOffset != baselineOffset)
735
+ {
736
+ _baselineOffset = baselineOffset;
737
+ [self setNeedsDisplay];
738
+ }
739
+ }
740
+
741
+ - (void)setCharacterKerning:(NSDictionary *)kerningTable
742
+ {
743
+ if (_kerningTable != kerningTable)
744
+ {
745
+ _kerningTable = [kerningTable copy];
746
+ [self setNeedsDisplay];
747
+ }
748
+ }
749
+
750
+ - (void)setAllowOrphans:(BOOL)allowOrphans
751
+ {
752
+ if (_allowOrphans != allowOrphans)
753
+ {
754
+ _allowOrphans = allowOrphans;
755
+ [self setNeedsDisplay];
756
+ }
757
+ }
758
+
759
+ - (CGSize)FXLabel_sizeThatFits:(CGSize)size actualFontSize:(CGFloat *)actualFontSize
760
+ {
761
+ size.width = size.width ?: INFINITY;
762
+ size.height = size.height ?: INFINITY;
763
+
764
+ if (self.numberOfLines == 1)
765
+ {
766
+
767
+ #if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
768
+
769
+ CGFloat minimumFontSize = self.minimumFontSize ?: self.font.pointSize;
770
+
771
+ #else
772
+
773
+ CGFloat minimumFontSize = self.minimumScaleFactor? self.minimumScaleFactor * self.font.pointSize: self.font.pointSize;
774
+
775
+ #endif
776
+ size = [self.text sizeWithFont:self.font
777
+ minFontSize:minimumFontSize
778
+ actualFontSize:actualFontSize
779
+ forWidth:size.width
780
+ lineBreakMode:self.lineBreakMode
781
+ characterSpacing:_characterSpacing
782
+ kerningTable:_kerningTable];
783
+ }
784
+ else
785
+ {
786
+ if (actualFontSize)
787
+ {
788
+ *actualFontSize = self.font.pointSize;
789
+ }
790
+ size = [self.text sizeWithFont:self.font
791
+ constrainedToSize:size
792
+ lineBreakMode:self.lineBreakMode
793
+ lineSpacing:_lineSpacing
794
+ characterSpacing:_characterSpacing
795
+ kerningTable:_kerningTable
796
+ allowOrphans:_allowOrphans];
797
+
798
+ if (self.numberOfLines > 0)
799
+ {
800
+ size.height = MIN(size.height, self.numberOfLines * self.font.lineHeight + (self.numberOfLines - 1) * self.font.pointSize * _lineSpacing);
801
+ }
802
+ }
803
+ return size;
804
+ }
805
+
806
+ - (CGSize)sizeThatFits:(CGSize)size
807
+ {
808
+ size.width -= (_textInsets.left + _textInsets.right);
809
+ size.height -= (_textInsets.top + _textInsets.bottom);
810
+ size = [self FXLabel_sizeThatFits:size actualFontSize:NULL];
811
+ size.width += (_textInsets.left + _textInsets.right);
812
+ size.height += (_textInsets.top + _textInsets.bottom);
813
+ return size;
814
+ }
815
+
816
+ - (void)FXLabel_getComponents:(CGFloat *)rgba forColor:(CGColorRef)color
817
+ {
818
+ CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color));
819
+ const CGFloat *components = CGColorGetComponents(color);
820
+ switch (model)
821
+ {
822
+ case kCGColorSpaceModelMonochrome:
823
+ {
824
+ rgba[0] = components[0];
825
+ rgba[1] = components[0];
826
+ rgba[2] = components[0];
827
+ rgba[3] = components[1];
828
+ break;
829
+ }
830
+ case kCGColorSpaceModelRGB:
831
+ {
832
+ rgba[0] = components[0];
833
+ rgba[1] = components[1];
834
+ rgba[2] = components[2];
835
+ rgba[3] = components[3];
836
+ break;
837
+ }
838
+ default:
839
+ {
840
+ NSLog(@"Unsupported gradient color format: %i", model);
841
+ rgba[0] = 0.0f;
842
+ rgba[1] = 0.0f;
843
+ rgba[2] = 0.0f;
844
+ rgba[3] = 1.0f;
845
+ break;
846
+ }
847
+ }
848
+ }
849
+
850
+ - (UIColor *)FXLabel_color:(CGColorRef)a blendedWithColor:(CGColorRef)b
851
+ {
852
+ CGFloat aRGBA[4];
853
+ [self FXLabel_getComponents:aRGBA forColor:a];
854
+ CGFloat bRGBA[4];
855
+ [self FXLabel_getComponents:bRGBA forColor:b];
856
+ CGFloat source = aRGBA[3];
857
+ CGFloat dest = 1.0f - source;
858
+ return [UIColor colorWithRed:source * aRGBA[0] + dest * bRGBA[0]
859
+ green:source * aRGBA[1] + dest * bRGBA[1]
860
+ blue:source * aRGBA[2] + dest * bRGBA[2]
861
+ alpha:bRGBA[3] + (1.0f - bRGBA[3]) * aRGBA[3]];
862
+ }
863
+
864
+ - (void)FXLabel_drawTextInRect:(CGRect)rect withFont:(UIFont *)font
865
+ {
866
+ rect.origin.y += font.pointSize * _baselineOffset;
867
+ if (self.numberOfLines == 1)
868
+ {
869
+ [self.text drawAtPoint:rect.origin
870
+ forWidth:rect.size.width
871
+ withFont:self.font
872
+ minFontSize:font.pointSize
873
+ actualFontSize:NULL
874
+ lineBreakMode:self.lineBreakMode
875
+ baselineAdjustment:self.baselineAdjustment
876
+ characterSpacing:_characterSpacing
877
+ kerningTable:_kerningTable];
878
+ }
879
+ else
880
+ {
881
+ [self.text drawInRect:rect
882
+ withFont:font
883
+ lineBreakMode:self.lineBreakMode
884
+ alignment:self.textAlignment
885
+ lineSpacing:_lineSpacing
886
+ characterSpacing:_characterSpacing
887
+ kerningTable:_kerningTable
888
+ allowOrphans:_allowOrphans];
889
+ }
890
+ }
891
+
892
+ - (void)drawRect:(CGRect)rect
893
+ {
894
+ //get drawing context
895
+ BOOL subcontext = _oversampling > _minSamples || (self.backgroundColor && ![self.backgroundColor isEqual:[UIColor clearColor]]);
896
+ if (subcontext)
897
+ {
898
+ UIGraphicsBeginImageContextWithOptions(rect.size, NO, _oversampling);
899
+ }
900
+ CGContextRef context = UIGraphicsGetCurrentContext();
901
+
902
+ //apply insets
903
+ CGRect contentRect = CGRectMake(0.0f, 0.0f, self.bounds.size.width, self.bounds.size.height);
904
+ contentRect.origin.x += _textInsets.left;
905
+ contentRect.origin.y += _textInsets.top;
906
+ contentRect.size.width -= (_textInsets.left + _textInsets.right);
907
+ contentRect.size.height -= (_textInsets.top + _textInsets.bottom);
908
+
909
+ //get dimensions
910
+ CGFloat fontSize = 0.0f;
911
+ CGRect textRect = contentRect;
912
+ textRect.size = [self FXLabel_sizeThatFits:contentRect.size actualFontSize:&fontSize];
913
+
914
+ //set font
915
+ UIFont *font = [self.font fontWithSize:fontSize];
916
+
917
+ //adjust for minimum height
918
+ textRect.size.height = MAX(textRect.size.height, font.lineHeight);
919
+
920
+ //set color
921
+ UIColor *highlightedColor = self.highlightedTextColor ?: self.textColor;
922
+ UIColor *textColor = self.highlighted? highlightedColor: self.textColor;
923
+ textColor = textColor ?: [UIColor clearColor];
924
+
925
+ //set alignment
926
+ switch (self.textAlignment)
927
+ {
928
+ case NSTextAlignmentCenter:
929
+ {
930
+ textRect.origin.x = contentRect.origin.x + roundf((contentRect.size.width - textRect.size.width) / 2.0f);
931
+ break;
932
+ }
933
+ case NSTextAlignmentRight:
934
+ {
935
+ textRect.origin.x = contentRect.origin.x + contentRect.size.width - textRect.size.width;
936
+ break;
937
+ }
938
+ default:
939
+ {
940
+ textRect.origin.x = contentRect.origin.x;
941
+ break;
942
+ }
943
+ }
944
+ switch (self.contentMode)
945
+ {
946
+ case UIViewContentModeTop:
947
+ case UIViewContentModeTopLeft:
948
+ case UIViewContentModeTopRight:
949
+ {
950
+ textRect.origin.y = contentRect.origin.y;
951
+ break;
952
+ }
953
+ case UIViewContentModeBottom:
954
+ case UIViewContentModeBottomLeft:
955
+ case UIViewContentModeBottomRight:
956
+ {
957
+ textRect.origin.y = contentRect.origin.y + contentRect.size.height - textRect.size.height;
958
+ break;
959
+ }
960
+ default:
961
+ {
962
+ textRect.origin.y = contentRect.origin.y + (contentRect.size.height - textRect.size.height)/2.0f;
963
+ break;
964
+ }
965
+ }
966
+
967
+ BOOL hasShadow = self.shadowColor &&
968
+ ![self.shadowColor isEqual:[UIColor clearColor]] &&
969
+ (shadowBlur > 0.0f || !CGSizeEqualToSize(self.shadowOffset, CGSizeZero));
970
+
971
+ BOOL hasInnerShadow = _innerShadowColor &&
972
+ ![_innerShadowColor isEqual:[UIColor clearColor]] &&
973
+ (_innerShadowBlur > 0.0f || !CGSizeEqualToSize(_innerShadowOffset, CGSizeZero));
974
+
975
+ BOOL hasGradient = [_gradientColors count] > 1;
976
+ BOOL needsMask = hasInnerShadow || hasGradient;
977
+
978
+ CGImageRef alphaMask = NULL;
979
+ if (needsMask)
980
+ {
981
+ //draw mask
982
+ CGContextSaveGState(context);
983
+ [self FXLabel_drawTextInRect:textRect withFont:font];
984
+ CGContextRestoreGState(context);
985
+
986
+ //create an image mask from what we've drawn so far
987
+ alphaMask = CGBitmapContextCreateImage(context);
988
+
989
+ //clear the context
990
+ CGContextClearRect(context, textRect);
991
+ }
992
+
993
+ if (hasShadow)
994
+ {
995
+ //set up shadow
996
+ CGContextSaveGState(context);
997
+ CGFloat textAlpha = CGColorGetAlpha(textColor.CGColor);
998
+ CGContextSetShadowWithColor(context, self.shadowOffset, shadowBlur, self.shadowColor.CGColor);
999
+ [needsMask? [self.shadowColor colorWithAlphaComponent:textAlpha]: textColor setFill];
1000
+ [self FXLabel_drawTextInRect:textRect withFont:font];
1001
+ CGContextRestoreGState(context);
1002
+ }
1003
+ else if (!needsMask)
1004
+ {
1005
+ //just draw the text
1006
+ [textColor setFill];
1007
+ [self FXLabel_drawTextInRect:textRect withFont:font];
1008
+ }
1009
+
1010
+ if (needsMask)
1011
+ {
1012
+ //clip the context
1013
+ CGContextSaveGState(context);
1014
+ CGContextTranslateCTM(context, 0, contentRect.size.height);
1015
+ CGContextScaleCTM(context, 1.0, -1.0);
1016
+ CGContextClipToMask(context, contentRect, alphaMask);
1017
+
1018
+ if (hasGradient)
1019
+ {
1020
+ //create array of pre-blended CGColors
1021
+ NSMutableArray *colors = [NSMutableArray arrayWithCapacity:[_gradientColors count]];
1022
+ for (UIColor *color in _gradientColors)
1023
+ {
1024
+ UIColor *blended = [self FXLabel_color:color.CGColor blendedWithColor:textColor.CGColor];
1025
+ [colors addObject:(__bridge id)blended.CGColor];
1026
+ }
1027
+
1028
+ //draw gradient
1029
+ CGContextSaveGState(context);
1030
+ CGContextScaleCTM(context, 1.0, -1.0);
1031
+ CGContextTranslateCTM(context, 0, -contentRect.size.height);
1032
+ CGGradientRef gradient = CGGradientCreateWithColors(NULL, (__bridge CFArrayRef)colors, NULL);
1033
+ CGPoint startPoint = CGPointMake(textRect.origin.x + _gradientStartPoint.x * textRect.size.width,
1034
+ textRect.origin.y + _gradientStartPoint.y * textRect.size.height);
1035
+ CGPoint endPoint = CGPointMake(textRect.origin.x + _gradientEndPoint.x * textRect.size.width,
1036
+ textRect.origin.y + _gradientEndPoint.y * textRect.size.height);
1037
+ CGContextDrawLinearGradient(context, gradient, startPoint, endPoint,
1038
+ kCGGradientDrawsAfterEndLocation | kCGGradientDrawsBeforeStartLocation);
1039
+ CGGradientRelease(gradient);
1040
+ CGContextRestoreGState(context);
1041
+ }
1042
+ else
1043
+ {
1044
+ //fill text
1045
+ [textColor setFill];
1046
+ UIRectFill(textRect);
1047
+ }
1048
+
1049
+ if (hasInnerShadow)
1050
+ {
1051
+ //generate inverse mask
1052
+ UIGraphicsBeginImageContextWithOptions(rect.size, NO, _oversampling);
1053
+ CGContextRef shadowContext = UIGraphicsGetCurrentContext();
1054
+ [[_innerShadowColor colorWithAlphaComponent:1.0f] setFill];
1055
+ UIRectFill(rect);
1056
+ CGContextClipToMask(shadowContext, rect, alphaMask);
1057
+ CGContextClearRect(shadowContext, rect);
1058
+ UIImage *shadowImage = UIGraphicsGetImageFromCurrentImageContext();
1059
+ UIGraphicsEndImageContext();
1060
+
1061
+ //draw shadow
1062
+ CGContextSetShadowWithColor(context, _innerShadowOffset, _innerShadowBlur, _innerShadowColor.CGColor);
1063
+ CGContextSetBlendMode(context, kCGBlendModeDarken);
1064
+ [shadowImage drawInRect:rect];
1065
+ }
1066
+
1067
+ //end clipping
1068
+ CGContextRestoreGState(context);
1069
+ CGImageRelease(alphaMask);
1070
+ }
1071
+
1072
+ if (subcontext)
1073
+ {
1074
+ UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
1075
+ UIGraphicsEndImageContext();
1076
+ [image drawInRect:rect];
1077
+ }
1078
+ }
1079
+
1080
+ @end