Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit before code cleanup

  • Loading branch information...
commit 741958b4f2f6ed0b7c632185faadf947dbec1189 0 parents
@gshipley gshipley authored
Showing with 46,073 additions and 0 deletions.
  1. +1 −0  .gitignore
  2. +23 −0 .project
  3. +1 −0  CHANGELOG.txt
  4. +219 −0 LICENSE
  5. +1 −0  LICENSE.txt
  6. +18 −0 README
  7. BIN  Resources/KS_nav_ui.png
  8. BIN  Resources/KS_nav_views.png
  9. BIN  Resources/Powered-By-BreweryDB.png
  10. BIN  Resources/The-Simpsons-Duff-Pint-Glass_8637-l.jpg
  11. +431 −0 Resources/app.js
  12. BIN  Resources/background.png
  13. BIN  Resources/beer-icon.png
  14. +108 −0 Resources/drankWindow.js
  15. +109 −0 Resources/firehoseWindow.js
  16. BIN  Resources/icon-drank.png
  17. BIN  Resources/icon-drink.png
  18. BIN  Resources/icon-firehose.png
  19. BIN  Resources/icon_calculator.png
  20. BIN  Resources/icon_settings.png
  21. BIN  Resources/iphone/Default-Landscape.png
  22. BIN  Resources/iphone/Default-Portrait.png
  23. BIN  Resources/iphone/Default.png
  24. BIN  Resources/iphone/Default@2x.png
  25. BIN  Resources/iphone/appicon.png
  26. BIN  Resources/loading-gif-animation.gif
  27. BIN  Resources/login-btn.png
  28. BIN  Resources/navbar.png
  29. BIN  Resources/openshift-logo-white-scaled.png
  30. BIN  Resources/openshift-logo-white.png
  31. BIN  Resources/pint glass.jpg
  32. BIN  Resources/pitcher.jpg
  33. +191 −0 Resources/settingsWindow.js
  34. +4,353 −0 build/iphone/BeerShift.xcodeproj/project.pbxproj
  35. +17 −0 build/iphone/BeerShift_Prefix.pch
  36. +48 −0 build/iphone/Classes/AFOpenFlow/AFItemView.h
  37. +97 −0 build/iphone/Classes/AFOpenFlow/AFItemView.m
  38. +33 −0 build/iphone/Classes/AFOpenFlow/AFOpenFlowConstants.h
  39. +87 −0 build/iphone/Classes/AFOpenFlow/AFOpenFlowView.h
  40. +472 −0 build/iphone/Classes/AFOpenFlow/AFOpenFlowView.m
  41. +37 −0 build/iphone/Classes/AFOpenFlow/AFUIImageReflection.h
  42. +102 −0 build/iphone/Classes/AFOpenFlow/AFUIImageReflection.m
  43. +38 −0 build/iphone/Classes/AFOpenFlow/UIImageExtras.h
  44. +80 −0 build/iphone/Classes/AFOpenFlow/UIImageExtras.m
  45. +19 −0 build/iphone/Classes/APIModule.h
  46. +120 −0 build/iphone/Classes/APIModule.m
  47. +104 −0 build/iphone/Classes/AQRecorder.h
  48. +361 −0 build/iphone/Classes/AQRecorder.mm
  49. +35 −0 build/iphone/Classes/ASI/ASIAuthenticationDialog.h
  50. +487 −0 build/iphone/Classes/ASI/ASIAuthenticationDialog.m
  51. +103 −0 build/iphone/Classes/ASI/ASICacheDelegate.h
  52. +42 −0 build/iphone/Classes/ASI/ASIDataCompressor.h
  53. +219 −0 build/iphone/Classes/ASI/ASIDataCompressor.m
  54. +41 −0 build/iphone/Classes/ASI/ASIDataDecompressor.h
  55. +218 −0 build/iphone/Classes/ASI/ASIDataDecompressor.m
  56. +42 −0 build/iphone/Classes/ASI/ASIDownloadCache.h
  57. +511 −0 build/iphone/Classes/ASI/ASIDownloadCache.m
  58. +76 −0 build/iphone/Classes/ASI/ASIFormDataRequest.h
  59. +361 −0 build/iphone/Classes/ASI/ASIFormDataRequest.m
  60. +1,010 −0 build/iphone/Classes/ASI/ASIHTTPRequest.h
  61. +5,117 −0 build/iphone/Classes/ASI/ASIHTTPRequest.m
  62. +37 −0 build/iphone/Classes/ASI/ASIHTTPRequestConfig.h
  63. +35 −0 build/iphone/Classes/ASI/ASIHTTPRequestDelegate.h
  64. +26 −0 build/iphone/Classes/ASI/ASIInputStream.h
  65. +136 −0 build/iphone/Classes/ASI/ASIInputStream.m
  66. +108 −0 build/iphone/Classes/ASI/ASINetworkQueue.h
  67. +343 −0 build/iphone/Classes/ASI/ASINetworkQueue.m
  68. +38 −0 build/iphone/Classes/ASI/ASIProgressDelegate.h
  69. +193 −0 build/iphone/Classes/ASI/Reachability.h
  70. +817 −0 build/iphone/Classes/ASI/Reachability.m
  71. +19 −0 build/iphone/Classes/AccelerometerModule.h
  72. +48 −0 build/iphone/Classes/AccelerometerModule.m
  73. +22 −0 build/iphone/Classes/AnalyticsModule.h
  74. +705 −0 build/iphone/Classes/AnalyticsModule.mm
  75. +53 −0 build/iphone/Classes/AppModule.h
  76. +426 −0 build/iphone/Classes/AppModule.m
  77. +17 −0 build/iphone/Classes/ApplicationDefaults.h
  78. +20 −0 build/iphone/Classes/ApplicationDefaults.m
  79. +11 −0 build/iphone/Classes/ApplicationMods.h
  80. +15 −0 build/iphone/Classes/ApplicationMods.m
  81. +10 −0 build/iphone/Classes/ApplicationRouting.h
  82. +15 −0 build/iphone/Classes/ApplicationRouting.m
  83. +690 −0 build/iphone/Classes/AsyncSocket.h
  84. +4,368 −0 build/iphone/Classes/AsyncSocket.m
  85. +366 −0 build/iphone/Classes/AsyncUdpSocket.h
  86. +2,343 −0 build/iphone/Classes/AsyncUdpSocket.m
  87. +138 −0 build/iphone/Classes/AudioStreamer/AudioStreamer.h
  88. +181 −0 build/iphone/Classes/AudioStreamer/AudioStreamer.m
  89. +87 −0 build/iphone/Classes/AudioStreamer/AudioStreamerBC.h
  90. +1,534 −0 build/iphone/Classes/AudioStreamer/AudioStreamerBC.m
  91. +108 −0 build/iphone/Classes/AudioStreamer/AudioStreamerCUR.h
  92. +1,805 −0 build/iphone/Classes/AudioStreamer/AudioStreamerCUR.m
  93. +232 −0 build/iphone/Classes/Base64Transcoder.c
  94. +44 −0 build/iphone/Classes/Base64Transcoder.h
  95. +36 −0 build/iphone/Classes/Bridge.h
  96. +84 −0 build/iphone/Classes/Bridge.m
  97. +94 −0 build/iphone/Classes/CADebugMacros.cpp
  98. +443 −0 build/iphone/Classes/CADebugMacros.h
  99. +74 −0 build/iphone/Classes/CAMath.h
  100. +554 −0 build/iphone/Classes/CAStreamBasicDescription.cpp
  101. +312 −0 build/iphone/Classes/CAStreamBasicDescription.h
  102. +56 −0 build/iphone/Classes/CAXException.cpp
  103. +218 −0 build/iphone/Classes/CAXException.h
  104. +42 −0 build/iphone/Classes/CodecModule.h
  105. +351 −0 build/iphone/Classes/CodecModule.m
  106. +54 −0 build/iphone/Classes/ContactsModule.h
  107. +467 −0 build/iphone/Classes/ContactsModule.m
  108. +26 −0 build/iphone/Classes/DatabaseModule.h
  109. +52 −0 build/iphone/Classes/DatabaseModule.m
  110. +25 −0 build/iphone/Classes/FBConnect/FBConnect.h
  111. +165 −0 build/iphone/Classes/FBConnect/FBDialog.h
  112. +650 −0 build/iphone/Classes/FBConnect/FBDialog.m
  113. +41 −0 build/iphone/Classes/FBConnect/FBLoginButton.h
  114. +92 −0 build/iphone/Classes/FBConnect/FBLoginButton.m
  115. +47 −0 build/iphone/Classes/FBConnect/FBLoginDialog.h
  116. +115 −0 build/iphone/Classes/FBConnect/FBLoginDialog.m
  117. +121 −0 build/iphone/Classes/FBConnect/FBRequest.h
  118. +358 −0 build/iphone/Classes/FBConnect/FBRequest.m
  119. +126 −0 build/iphone/Classes/FBConnect/Facebook.h
  120. +660 −0 build/iphone/Classes/FBConnect/Facebook.m
  121. +45 −0 build/iphone/Classes/FacebookModule.h
  122. +646 −0 build/iphone/Classes/FacebookModule.m
  123. +31 −0 build/iphone/Classes/FilesystemModule.h
  124. +176 −0 build/iphone/Classes/FilesystemModule.m
  125. +235 −0 build/iphone/Classes/GDataXMLNode.h
  126. +1,938 −0 build/iphone/Classes/GDataXMLNode.m
  127. +70 −0 build/iphone/Classes/GeolocationModule.h
  128. +822 −0 build/iphone/Classes/GeolocationModule.mm
  129. +30 −0 build/iphone/Classes/GestureModule.h
  130. +119 −0 build/iphone/Classes/GestureModule.m
  131. +84 −0 build/iphone/Classes/ImageLoader.h
  132. +817 −0 build/iphone/Classes/ImageLoader.m
  133. +49 −0 build/iphone/Classes/JSON/JSON.h
  134. +8 −0 build/iphone/Classes/JSON/MASS-TODO
  135. +70 −0 build/iphone/Classes/JSON/NSObject+SBJSON.h
  136. +54 −0 build/iphone/Classes/JSON/NSObject+SBJSON.m
  137. +59 −0 build/iphone/Classes/JSON/NSString+SBJSON.h
  138. +56 −0 build/iphone/Classes/JSON/NSString+SBJSON.m
  139. +76 −0 build/iphone/Classes/JSON/SBJSON.h
  140. +213 −0 build/iphone/Classes/JSON/SBJSON.m
  141. +87 −0 build/iphone/Classes/JSON/SBJsonBase.h
  142. +79 −0 build/iphone/Classes/JSON/SBJsonBase.m
  143. +87 −0 build/iphone/Classes/JSON/SBJsonParser.h
  144. +476 −0 build/iphone/Classes/JSON/SBJsonParser.m
  145. +129 −0 build/iphone/Classes/JSON/SBJsonWriter.h
  146. +238 −0 build/iphone/Classes/JSON/SBJsonWriter.m
  147. +73 −0 build/iphone/Classes/KrollBridge.h
  148. +954 −0 build/iphone/Classes/KrollBridge.mm
  149. +81 −0 build/iphone/Classes/KrollCallback.h
  150. +249 −0 build/iphone/Classes/KrollCallback.m
  151. +181 −0 build/iphone/Classes/KrollContext.h
  152. +1,358 −0 build/iphone/Classes/KrollContext.mm
  153. +69 −0 build/iphone/Classes/KrollCoverage.h
  154. +293 −0 build/iphone/Classes/KrollCoverage.m
  155. +52 −0 build/iphone/Classes/KrollMethod.h
  156. +323 −0 build/iphone/Classes/KrollMethod.m
  157. +26 −0 build/iphone/Classes/KrollMethodDelegate.h
  158. +48 −0 build/iphone/Classes/KrollMethodDelegate.m
  159. +87 −0 build/iphone/Classes/KrollObject.h
Sorry, we could not display the entire diff because too many files (997) changed.
1  .gitignore
@@ -0,0 +1 @@
+tmp
23 .project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>BeerShift</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.aptana.ide.core.unifiedBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.appcelerator.titanium.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.appcelerator.titanium.mobile.nature</nature>
+ <nature>com.aptana.projects.webnature</nature>
+ </natures>
+</projectDescription>
1  CHANGELOG.txt
@@ -0,0 +1 @@
+Place your change log text here. This file will be incorporated with your app at package time.
219 LICENSE
@@ -0,0 +1,219 @@
+Copyright 2009 Appcelerator, Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ (or the full text of the license is below)
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
1  LICENSE.txt
@@ -0,0 +1 @@
+Place your license text here. This file will be incorporated with your app at package time.
18 README
@@ -0,0 +1,18 @@
+Welcome to your Appcelerator Titanium Mobile Project
+
+This is a blank project. Start by editing your application's app.js to
+make your first mobile project using Titanium.
+
+
+
+----------------------------------
+Stuff our legal folk make us say:
+
+Appcelerator, Appcelerator Titanium and associated marks and logos are
+trademarks of Appcelerator, Inc.
+
+Titanium is Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
+
+Titanium is licensed under the Apache Public License (Version 2). Please
+see the LICENSE file for the full license.
+
BIN  Resources/KS_nav_ui.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/KS_nav_views.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/Powered-By-BreweryDB.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/The-Simpsons-Duff-Pint-Glass_8637-l.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
431 Resources/app.js
@@ -0,0 +1,431 @@
+var tabGroup = Ti.UI.createTabGroup();
+
+var windowDrink = Ti.UI.createWindow({
+ width : 320,
+ height : 480,
+ top : 0,
+ left : 0,
+ backgroundColor : 'black',
+ title : 'BeerShift',
+ barImage : 'navbar.png'
+});
+
+function createDetailWindow(e) {
+ var windowBeerDetails = Ti.UI.createWindow({
+ width : 320,
+ height : 480,
+ top : 0,
+ left : 0,
+ backgroundColor : 'black',
+ title : 'Beer Details',
+ barImage : 'navbar.png'
+ });
+
+ var detailsView = Ti.UI.createView({
+ width : 320,
+ height : windowBeerDetails.height - 134,
+ left : 0,
+ top : 0,
+ backgroundColor : 'black',
+ borderRadius : 5
+ });
+
+ // Let start adding our UI elements
+ var beerImage = Titanium.UI.createImageView({
+ image : 'pitcher.jpg',
+ width : 80,
+ height : 62,
+ left : 10,
+ top : 20
+ });
+
+ var labelBeerDetailName = Titanium.UI.createLabel({
+ width : 'auto',
+ height : 30,
+ top : 40,
+ left : 100,
+ color : 'white',
+ font : {
+ fontSize : 14,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold'
+ },
+ text : e._title
+ });
+ var labelBreweryName = Titanium.UI.createLabel({
+ width : 'auto',
+ height : 30,
+ top : 58,
+ left : 100,
+ color : 'white',
+ font : {
+ fontSize : 14,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold'
+ },
+ text : e._brewery
+ });
+
+ var textareaDescription = Titanium.UI.createTextArea({
+ color : 'white',
+ backgroundColor : 'black',
+ value : e._description,
+ height : 200,
+ width : 300,
+ top : 105,
+ left : 10,
+ font : {
+ fontSize : 12,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold',
+ color : 'white'
+ },
+ borderColor : '#000',
+ editable : false
+ });
+ var labelDrinkTheBeer = Titanium.UI.createLabel({
+ width : 'auto',
+ height : 30,
+ top : 320,
+ left : 130,
+ color : 'white',
+ font : {
+ fontSize : 14,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold'
+ },
+ text : 'Drink It!'
+ });
+
+ labelDrinkTheBeer.addEventListener('click', function(e) {
+ Ti.API.info(Ti.App.Properties.getString('username') + " just drank a beer (" + labelBeerDetailName.text + ")");
+
+ var now = new Date();
+
+ // Post the data to our database
+ var drinkPostURL = 'http://localhost/api/beers/';
+ var postRequest = Ti.Network.createHTTPClient();
+ postRequest.open('POST', drinkPostURL);
+ postRequest.send({
+ username : Ti.App.Properties.getString('username'),
+ beerName : labelBeerDetailName.text,
+ when : dateFormat(now, "dddd, mmmm dS, yyyy, h:MM:ss TT")
+ });
+
+ tabGroup.setActiveTab(1);
+ });
+ detailsView.add(labelDrinkTheBeer);
+ detailsView.add(labelBeerDetailName);
+ detailsView.add(labelBreweryName);
+ detailsView.add(beerImage);
+ detailsView.add(textareaDescription);
+ windowBeerDetails.add(detailsView);
+
+ return windowBeerDetails;
+}
+
+var view = Ti.UI.createView({
+ width : 320,
+ height : windowDrink.height - 134,
+ left : 0,
+ top : 0,
+ backgroundColor : 'black',
+ borderRadius : 5
+});
+
+//define our table view
+
+var labelBeerName = Titanium.UI.createLabel({
+ width : 'auto',
+ height : 30,
+ top : 20,
+ left : 10,
+ color : 'white',
+ font : {
+ fontSize : 14,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold'
+ },
+ text : 'Beer Name: '
+});
+view.add(labelBeerName);
+
+var tfBeerName = Ti.UI.createTextField({
+ width : 200,
+ height : 30,
+ top : 20,
+ right : 0,
+ font : {
+ fontSize : 14,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold'
+ },
+ borderStyle : Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
+ returnKeyType : Ti.UI.RETURNKEY_DONE,
+ hintText : 'What am I drinking?'
+});
+tfBeerName.addEventListener('return', function(e) {
+ populateTableWithBeer(e.value);
+});
+view.add(tfBeerName);
+
+function populateTableWithBeer(beerName) {
+
+ var data = [];
+
+ var tblBeers = Titanium.UI.createTableView({
+ height : 380,
+ width : 320,
+ top : 55,
+ left : 5,
+ rowHeight : 35,
+ borderRadius : 5,
+ data : data
+ });
+ view.add(tblBeers);
+ var data = [];
+ var pintlabURL = "http://localhost/api/beers/name/" + beerName;
+ var request = Titanium.Network.createHTTPClient();
+ request.open('GET', pintlabURL);
+ request.send();
+ //this method will process the remote data
+ request.onload = function() {
+ //create a json object using the JSON.PARSE function
+ var response = JSON.parse(request.responseText);
+
+ //loop each item in the json object
+ for(var i = 0; i < response.data.length; i++) {
+ //create a table row
+ var row = Titanium.UI.createTableViewRow({
+ hasChild : true,
+ className : 'recipe-row',
+ backgroundColor : '#fff',
+ _title : response.data[i].name,
+ _description : response.data[i].description,
+ _brewery : response.data[i].breweries[0].name
+ });
+ //title label
+ var titleLabel = Titanium.UI.createLabel({
+ text : response.data[i].name,
+ font : {
+ fontSize : 14,
+ fontWeight : 'bold'
+ },
+ left : 50,
+ top : 5,
+ height : 20,
+ width : 210,
+ color : '#000'
+ });
+ row.add(titleLabel);
+
+ //add our little icon to the left of the row
+ var iconImage = Titanium.UI.createImageView({
+ image : 'beer-icon.png',
+ width : 24,
+ height : 24,
+ left : 10,
+ top : 5
+ });
+ row.add(iconImage);
+
+ //add the table row to our data[] object
+ data.push(row);
+ }
+
+ //finally, set the data property of the tableView to our data[] object
+ tblBeers.visible = false;
+ tblBeers.setData(data);
+ tblBeers.addEventListener('click', function(e) {
+ drinkTab.open(createDetailWindow(e.rowData))
+ });
+ tblBeers.visible = true;
+ }
+}
+
+//view.add(tblBeers);
+
+windowDrink.add(view);
+
+var drinkTab = Ti.UI.createTab({
+ icon : 'icon-drink.png',
+ title : 'Drink',
+ window : windowDrink
+});
+var windowDrank = Ti.UI.createWindow({
+ width : 320,
+ height : 480,
+ top : 0,
+ left : 0,
+ backgroundColor : "black",
+ url : 'drankWindow.js',
+ title : 'Drank',
+ barImage : 'navbar.png'
+});
+
+var windowFirehose = Ti.UI.createWindow({
+ width : 320,
+ height : 480,
+ top : 0,
+ left : 0,
+ backgroundColor : "black",
+ url : 'firehoseWindow.js',
+ title : 'Firehose',
+ barImage : 'navbar.png'
+});
+
+var drankTab = Ti.UI.createTab({
+ icon : 'icon-drank.png',
+ title : 'Drank',
+ window : windowDrank
+});
+
+var windowSettings = Ti.UI.createWindow({
+ width : 320,
+ height : 480,
+ top : 0,
+ left : 0,
+ backgroundColor : "black",
+ url : 'settingsWindow.js',
+ title : 'Settings',
+ barImage : 'navbar.png',
+ mainTabGroup : tabGroup
+});
+
+var fireHouseTab = Ti.UI.createTab({
+ icon : 'icon-firehose.png',
+ title : 'Fire Hose',
+ window : windowFirehose
+});
+
+var settingsTab = Ti.UI.createTab({
+ icon : 'icon_settings.png',
+ title : 'Settings',
+ window : windowSettings
+});
+
+tabGroup.addTab(drinkTab);
+tabGroup.addTab(drankTab);
+tabGroup.addTab(fireHouseTab);
+tabGroup.addTab(settingsTab);
+
+//Determine if we need to set the settings tab as the default if the user has not logged in
+if(Ti.App.Properties.getString("username") == null || Ti.App.Properties.getString("username").length < 1) {
+ tabGroup.setActiveTab(3);
+}
+
+tabGroup.open();
+
+
+
+var dateFormat = function () {
+ var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
+ timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
+ timezoneClip = /[^-+\dA-Z]/g,
+ pad = function (val, len) {
+ val = String(val);
+ len = len || 2;
+ while (val.length < len) val = "0" + val;
+ return val;
+ };
+
+ // Regexes and supporting functions are cached through closure
+ return function (date, mask, utc) {
+ var dF = dateFormat;
+
+ // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
+ if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
+ mask = date;
+ date = undefined;
+ }
+
+ // Passing date through Date applies Date.parse, if necessary
+ date = date ? new Date(date) : new Date;
+ if (isNaN(date)) throw SyntaxError("invalid date");
+
+ mask = String(dF.masks[mask] || mask || dF.masks["default"]);
+
+ // Allow setting the utc argument via the mask
+ if (mask.slice(0, 4) == "UTC:") {
+ mask = mask.slice(4);
+ utc = true;
+ }
+
+ var _ = utc ? "getUTC" : "get",
+ d = date[_ + "Date"](),
+ D = date[_ + "Day"](),
+ m = date[_ + "Month"](),
+ y = date[_ + "FullYear"](),
+ H = date[_ + "Hours"](),
+ M = date[_ + "Minutes"](),
+ s = date[_ + "Seconds"](),
+ L = date[_ + "Milliseconds"](),
+ o = utc ? 0 : date.getTimezoneOffset(),
+ flags = {
+ d: d,
+ dd: pad(d),
+ ddd: dF.i18n.dayNames[D],
+ dddd: dF.i18n.dayNames[D + 7],
+ m: m + 1,
+ mm: pad(m + 1),
+ mmm: dF.i18n.monthNames[m],
+ mmmm: dF.i18n.monthNames[m + 12],
+ yy: String(y).slice(2),
+ yyyy: y,
+ h: H % 12 || 12,
+ hh: pad(H % 12 || 12),
+ H: H,
+ HH: pad(H),
+ M: M,
+ MM: pad(M),
+ s: s,
+ ss: pad(s),
+ l: pad(L, 3),
+ L: pad(L > 99 ? Math.round(L / 10) : L),
+ t: H < 12 ? "a" : "p",
+ tt: H < 12 ? "am" : "pm",
+ T: H < 12 ? "A" : "P",
+ TT: H < 12 ? "AM" : "PM",
+ Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
+ o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
+ S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
+ };
+
+ return mask.replace(token, function ($0) {
+ return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
+ });
+ };
+}();
+
+// Some common format strings
+dateFormat.masks = {
+ "default": "ddd mmm dd yyyy HH:MM:ss",
+ shortDate: "m/d/yy",
+ mediumDate: "mmm d, yyyy",
+ longDate: "mmmm d, yyyy",
+ fullDate: "dddd, mmmm d, yyyy",
+ shortTime: "h:MM TT",
+ mediumTime: "h:MM:ss TT",
+ longTime: "h:MM:ss TT Z",
+ isoDate: "yyyy-mm-dd",
+ isoTime: "HH:MM:ss",
+ isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
+ isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
+};
+
+// Internationalization strings
+dateFormat.i18n = {
+ dayNames: [
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+ ],
+ monthNames: [
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
+ ]
+};
+
+// For convenience...
+Date.prototype.format = function (mask, utc) {
+ return dateFormat(this, mask, utc);
+};
BIN  Resources/background.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/beer-icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
108 Resources/drankWindow.js
@@ -0,0 +1,108 @@
+//reference the current window
+var drankWindow = Titanium.UI.currentWindow;
+
+// get the tabGroup
+var tabGroup = Ti.UI.currentWindow.tabGroup;
+
+
+//create the view, this will hold all of our UI controls
+var view = Titanium.UI.createView({
+ width : 300,
+ height : 400,
+ left : 10,
+ top : 10,
+ backgroundColor : 'black',
+ borderRadius : 5
+});
+
+
+function populateTableWithBeer() {
+
+ var data = [];
+
+ var tblBeers = Titanium.UI.createTableView({
+ height : 340,
+ width : 320,
+ top : 0,
+ left : 5,
+ rowHeight : 35,
+ borderRadius : 5,
+ data : data
+ });
+ view.add(tblBeers);
+ var data = [];
+ var pintlabURL = "http://localhost/api/userbeers/username/" + Ti.App.Properties.getString("username");;
+ Ti.API.info(pintlabURL);
+ var request = Titanium.Network.createHTTPClient();
+ request.open('GET', pintlabURL);
+ request.send();
+ //this method will process the remote data
+ request.onload = function() {
+ //create a json object using the JSON.PARSE function
+ var response = JSON.parse(request.responseText);
+
+ //loop each item in the json object
+ for(var i = 0; i < response.length; i++) {
+ //create a table row
+ var row = Titanium.UI.createTableViewRow({
+ hasChild : true,
+ className : 'recipe-row',
+ backgroundColor : '#fff',
+ _beerName : response[i].beer,
+ _when : response[i].when
+ });
+ //title label
+ var titleLabel = Titanium.UI.createLabel({
+ text : response[i].beer,
+ font : {
+ fontSize : 14,
+ fontWeight : 'bold'
+ },
+ left : 50,
+ top : 5,
+ height : 20,
+ width : 210,
+ color : '#000'
+ });
+ row.add(titleLabel);
+
+ //add our little icon to the left of the row
+ var iconImage = Titanium.UI.createImageView({
+ image : 'beer-icon.png',
+ width : 24,
+ height : 24,
+ left : 10,
+ top : 5
+ });
+ row.add(iconImage);
+
+ var whenLabel = Titanium.UI.createLabel({
+ text: response[i].when,
+ font: {fontSize: 10, fontWeight: 'normal'},
+ left: 50,
+ top: 17,
+ height: 20,
+ width: 200,
+ color: '#000'
+ });
+ row.add(whenLabel);
+ //add the table row to our data[] object
+ data.push(row);
+ }
+
+ //finally, set the data property of the tableView to our data[] object
+ tblBeers.visible = false;
+ tblBeers.setData(data);
+ tblBeers.addEventListener('click', function(e) {
+ drinkTab.open(createDetailWindow(e.rowData))
+ });
+ tblBeers.visible = true;
+ }
+}
+
+populateTableWithBeer();
+drankWindow.add(view);
+drankWindow.addEventListener('focus', function(e){
+ Ti.API.info('window has focus');
+ populateTableWithBeer();
+});
109 Resources/firehoseWindow.js
@@ -0,0 +1,109 @@
+//reference the current window
+var firehoseWindow = Titanium.UI.currentWindow;
+
+// get the tabGroup
+var tabGroup = Ti.UI.currentWindow.tabGroup;
+
+
+//create the view, this will hold all of our UI controls
+var view = Titanium.UI.createView({
+ width : 300,
+ height : 400,
+ left : 10,
+ top : 10,
+ backgroundColor : 'black',
+ borderRadius : 5
+});
+
+
+function populateTableWithBeer() {
+
+ var data = [];
+
+ var tblBeers = Titanium.UI.createTableView({
+ height : 340,
+ width : 320,
+ top : 0,
+ left : 5,
+ rowHeight : 35,
+ borderRadius : 5,
+ data : data
+ });
+ view.add(tblBeers);
+ var data = [];
+ var pintlabURL = "http://localhost/api/firehose/";
+ Ti.API.info(pintlabURL);
+ var request = Titanium.Network.createHTTPClient();
+ request.open('GET', pintlabURL);
+ request.send();
+ //this method will process the remote data
+ request.onload = function() {
+ //create a json object using the JSON.PARSE function
+ var response = JSON.parse(request.responseText);
+
+ //loop each item in the json object
+ for(var i = 0; i < response.length; i++) {
+ //create a table row
+ var row = Titanium.UI.createTableViewRow({
+ hasChild : true,
+ className : 'recipe-row',
+ backgroundColor : '#fff',
+ _username : response[i].username,
+ _beerName : response[i].beer,
+ _when : response[i].when
+ });
+ //title label
+ var titleLabel = Titanium.UI.createLabel({
+ text : response[i].username + " drank " + response[i].beer,
+ font : {
+ fontSize : 14,
+ fontWeight : 'bold'
+ },
+ left : 50,
+ top : 5,
+ height : 20,
+ width : 210,
+ color : '#000'
+ });
+ row.add(titleLabel);
+
+ //add our little icon to the left of the row
+ var iconImage = Titanium.UI.createImageView({
+ image : 'beer-icon.png',
+ width : 24,
+ height : 24,
+ left : 10,
+ top : 5
+ });
+ row.add(iconImage);
+
+ var whenLabel = Titanium.UI.createLabel({
+ text: response[i].when,
+ font: {fontSize: 10, fontWeight: 'normal'},
+ left: 50,
+ top: 17,
+ height: 20,
+ width: 200,
+ color: '#000'
+ });
+ row.add(whenLabel);
+ //add the table row to our data[] object
+ data.push(row);
+ }
+
+ //finally, set the data property of the tableView to our data[] object
+ tblBeers.visible = false;
+ tblBeers.setData(data);
+ tblBeers.addEventListener('click', function(e) {
+ drinkTab.open(createDetailWindow(e.rowData))
+ });
+ tblBeers.visible = true;
+ }
+}
+
+populateTableWithBeer();
+firehoseWindow.add(view);
+firehoseWindow.addEventListener('focus', function(e){
+ Ti.API.info('window has focus');
+ populateTableWithBeer();
+});
BIN  Resources/icon-drank.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/icon-drink.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/icon-firehose.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/icon_calculator.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/icon_settings.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/iphone/Default-Landscape.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/iphone/Default-Portrait.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/iphone/Default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/iphone/Default@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/iphone/appicon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/loading-gif-animation.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/login-btn.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/navbar.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/openshift-logo-white-scaled.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/openshift-logo-white.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/pint glass.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  Resources/pitcher.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
191 Resources/settingsWindow.js
@@ -0,0 +1,191 @@
+//reference the current window
+var settingsWindow = Titanium.UI.currentWindow;
+
+// get the tabGroup
+var tabGroup = Ti.UI.currentWindow.tabGroup;
+
+// Check our properties to autofill if this user already exists.
+var username = Ti.App.Properties.getString("username");
+var password = Ti.App.Properties.getString("password");
+
+//create the view, this will hold all of our UI controls
+var view = Titanium.UI.createView({
+ width : 300,
+ height : 400,
+ left : 10,
+ top : 10,
+ backgroundColor : 'black',
+ borderRadius : 5
+});
+
+// create the openshift logo
+var logo = Ti.UI.createImageView({
+ image: 'openshift-logo-white-scaled.png',
+ width: 141,
+ height: 56,
+ left: 85,
+ top: 200
+});
+
+var breweryDBLogo = Ti.UI.createImageView({
+ image: 'Powered-By-BreweryDB.png',
+ width: 141,
+ height: 56,
+ left: 85,
+ top: 275
+});
+
+
+view.add(logo);
+view.add(breweryDBLogo);
+
+var labelUsername = Titanium.UI.createLabel({
+ width : 'auto',
+ height : 30,
+ top : 20,
+ left : 10,
+ color : 'white',
+ font : {
+ fontSize : 14,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold'
+ },
+ text : 'Username: '
+});
+view.add(labelUsername);
+
+var tfUsername = Ti.UI.createTextField({
+ width : 200,
+ height : 30,
+ top : 20,
+ right : 10,
+ borderStyle : Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
+ returnKeyType : Ti.UI.RETURNKEY_DONE,
+ hintText : 'BeerShift Username'
+});
+
+// fill the username textfield with the existing username
+if(username != null) {
+ tfUsername.value = username;
+}
+
+view.add(tfUsername);
+
+var labelPassword = Titanium.UI.createLabel({
+ width : 'auto',
+ height : 30,
+ top : 70,
+ left : 10,
+ color : 'white',
+ font : {
+ fontSize : 14,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold'
+ },
+ text : 'Password: '
+});
+view.add(labelPassword);
+
+var tfPassword = Ti.UI.createTextField({
+ width : 200,
+ height : 30,
+ top : 70,
+ right : 10,
+ borderStyle : Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
+ returnKeyType : Ti.UI.RETURNKEY_DONE,
+ passwordMask : true,
+ hintText : 'password'
+});
+
+view.add(tfUsername);
+view.add(tfPassword);
+
+// create our Button to login
+var buttonLogin = Ti.UI.createButton({
+ image : 'login-btn.png',
+ id : 1,
+ top : 120,
+ width : 74,
+ height : 24,
+ left : 123,
+ backgroundColor : 'black'
+});
+
+buttonLogin.addEventListener('click', loginUser);
+
+view.add(buttonLogin);
+settingsWindow.add(view);
+
+function loginUser(e) {
+ // Set the login button to not show
+ buttonLogin.visible = false;
+
+ // Show our Authenticating label
+ var labelAuthenticating = Titanium.UI.createLabel({
+ width : 'auto',
+ height : 30,
+ top : 120,
+ left : 10,
+ color : 'white',
+ font : {
+ fontSize : 14,
+ fontFamily : 'Helvetica',
+ fontWeight : 'bold'
+ },
+ text : 'Authenticating'
+ });
+
+ view.add(labelAuthenticating);
+
+ // Make a call out to openshift to validate / create user
+ //First, you'll want to check the user is connected to the intertubes
+ if(Titanium.Network.online == true) {
+
+ // I could set a global var here that is a boolean to block until a response is received
+ // maybe have an animated gif imgView or something
+ var request = Titanium.Network.createHTTPClient();
+ var getURL = 'http://localhost/api/user/username/' + tfUsername.value;
+ request.open('GET', getURL);
+ request.send();
+ request.onload = function() {
+ var statusCode = request.status;
+ if(statusCode == 404) {
+ // The username doesn't exist so lets create a new user
+ var postURL = 'http://localhost/api/user/';
+ var postRequest = Ti.Network.createHTTPClient();
+ postRequest.open('POST', postURL);
+ postRequest.send({
+ username : tfUsername.value,
+ password : tfPassword.value
+ });
+ }
+ if(statusCode == 200) {
+ var response = request.responseText;
+ var jsonResult = JSON.parse(response);
+ var backUser = jsonResult[0].username;
+ var backPassword = jsonResult[0].password;
+ if(tfUsername.value == backUser && tfPassword.value == backPassword) {
+ labelAuthenticating.visible = false;
+ // Show the login button again to allow user to switch accounts
+ buttonLogin.visible = true;
+ // Set the properties
+ Ti.App.Properties.setString('username', tfUsername.value);
+ Ti.App.Properties.setString('password', tfPassword.value);
+ // Put the user back on the drink tab
+ tabGroup.setActiveTab(0);
+ } else {
+ if(tfUsername.value == backUser && tfPassword.value != backPassword) {
+ labelAuthenticating.visible = false;
+ // Show an alert telling the user the password is not correct
+ var alertDialog = Titanium.UI.createAlertDialog({
+ title : 'Bad Password',
+ message : 'Password is not correct for this user'
+ });
+ alertDialog.show();
+ buttonLogin.visible = true;
+ }
+ }
+ }
+ }
+ }
+}
4,353 build/iphone/BeerShift.xcodeproj/project.pbxproj
4,353 additions, 0 deletions not shown
17 build/iphone/BeerShift_Prefix.pch
@@ -0,0 +1,17 @@
+//
+// Prefix header for all source files of the 'Titanium' target in the 'Titanium' project
+//
+
+#ifdef __OBJC__
+ #import <Foundation/Foundation.h>
+ #import <UIKit/UIKit.h>
+#endif
+
+
+// this was defined in 1.3+
+// to allow us to include this define in the PCH
+// but not break pre-1.3
+#ifdef TI_POST_1_2
+ #import "defines.h"
+#endif
+
48 build/iphone/Classes/AFOpenFlow/AFItemView.h
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2009 Alex Fajkowski, Apparent Logic LLC
+ *
+ * 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.
+ */
+#if defined(USE_TI_UIIOSCOVERFLOWVIEW) || defined(USE_TI_UICOVERFLOWVIEW)
+
+#import <UIKit/UIKit.h>
+
+
+@interface AFItemView : UIView {
+ UIImageView *imageView;
+ int number;
+ CGFloat horizontalPosition;
+ CGFloat verticalPosition;
+ CGFloat originalImageHeight;
+}
+
+@property int number;
+@property (nonatomic, readonly) CGFloat horizontalPosition;
+@property (nonatomic, readonly) CGFloat verticalPosition;
+@property (nonatomic, readonly) UIImageView *imageView;
+
+- (void)setImage:(UIImage *)newImage originalImageHeight:(CGFloat)imageHeight reflectionFraction:(CGFloat)reflectionFraction;
+- (CGSize)calculateNewSize:(CGSize)originalImageSize boundingBox:(CGSize)boundingBox;
+
+@end
+
+#endif
97 build/iphone/Classes/AFOpenFlow/AFItemView.m
@@ -0,0 +1,97 @@
+/**
+ * Copyright (c) 2009 Alex Fajkowski, Apparent Logic LLC
+ *
+ * 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.
+ */
+#if defined(USE_TI_UIIOSCOVERFLOWVIEW) || defined(USE_TI_UICOVERFLOWVIEW)
+
+#import "AFItemView.h"
+#import <QuartzCore/QuartzCore.h>
+#import "AFOpenFlowConstants.h"
+
+
+@implementation AFItemView
+@synthesize imageView, horizontalPosition, verticalPosition;
+
+- (id)initWithFrame:(CGRect)frame {
+ if (self = [super initWithFrame:frame]) {
+ self.opaque = YES;
+ self.backgroundColor = NULL;
+ verticalPosition = 0;
+ horizontalPosition = 0;
+
+ // Image View
+ imageView = [[UIImageView alloc] initWithFrame:frame];
+ imageView.opaque = YES;
+ [self addSubview:imageView];
+ }
+
+ return self;
+}
+
+- (void)setImage:(UIImage *)newImage originalImageHeight:(CGFloat)imageHeight reflectionFraction:(CGFloat)reflectionFraction {
+ [imageView setImage:newImage];
+ verticalPosition = imageHeight * reflectionFraction / 2;
+ originalImageHeight = imageHeight;
+ self.frame = CGRectMake(0, 0, newImage.size.width, newImage.size.height);
+}
+
+- (int)number {
+ return number;
+}
+
+- (void)setNumber:(int)newNumber {
+ horizontalPosition = COVER_SPACING * newNumber;
+ number = newNumber;
+}
+
+- (CGSize)calculateNewSize:(CGSize)baseImageSize boundingBox:(CGSize)boundingBox {
+ CGFloat boundingRatio = boundingBox.width / boundingBox.height;
+ CGFloat originalImageRatio = baseImageSize.width / baseImageSize.height;
+
+ CGFloat newWidth;
+ CGFloat newHeight;
+ if (originalImageRatio > boundingRatio) {
+ newWidth = boundingBox.width;
+ newHeight = boundingBox.width * baseImageSize.height / baseImageSize.width;
+ } else {
+ newHeight = boundingBox.height;
+ newWidth = boundingBox.height * baseImageSize.width / baseImageSize.height;
+ }
+
+ return CGSizeMake(newWidth, newHeight);
+}
+
+- (void)setFrame:(CGRect)newFrame {
+ [super setFrame:newFrame];
+ [imageView setFrame:newFrame];
+}
+
+- (void)dealloc {
+ [imageView release];
+
+ [super dealloc];
+}
+
+@end
+
+#endif
33 build/iphone/Classes/AFOpenFlow/AFOpenFlowConstants.h
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2009 Alex Fajkowski, Apparent Logic LLC
+ *
+ * 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.
+ */
+#if defined(USE_TI_UIIOSCOVERFLOWVIEW) || defined(USE_TI_UICOVERFLOWVIEW)
+
+// For OpenFlow
+#define COVER_SPACING 40
+#define CENTER_COVER_OFFSET 70
+#define SIDE_COVER_ANGLE .79
+#define SIDE_COVER_ZPOSITION -80
+
+#endif
87 build/iphone/Classes/AFOpenFlow/AFOpenFlowView.h
@@ -0,0 +1,87 @@
+/**
+ * Copyright (c) 2009 Alex Fajkowski, Apparent Logic LLC
+ *
+ * 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.
+ */
+#if defined(USE_TI_UIIOSCOVERFLOWVIEW) || defined(USE_TI_UICOVERFLOWVIEW)
+
+#import <UIKit/UIKit.h>
+#import "AFItemView.h"
+#import <QuartzCore/QuartzCore.h>
+
+
+@protocol AFOpenFlowViewDataSource;
+@protocol AFOpenFlowViewDelegate;
+
+@interface AFOpenFlowView : UIView {
+ id <AFOpenFlowViewDataSource> dataSource;
+ id <AFOpenFlowViewDelegate> viewDelegate;
+ NSMutableSet *offscreenCovers;
+ NSMutableDictionary *onscreenCovers;
+ NSMutableDictionary *coverImages;
+ NSMutableDictionary *coverImageHeights;
+ UIImage *defaultImage;
+ CGFloat defaultImageHeight;
+
+ UIScrollView *scrollView;
+ int lowerVisibleCover;
+ int upperVisibleCover;
+ int numberOfImages;
+ int beginningCover;
+
+ AFItemView *selectedCoverView;
+
+ CATransform3D leftTransform, rightTransform;
+
+ CGFloat halfScreenHeight;
+ CGFloat halfScreenWidth;
+
+ Boolean isSingleTap;
+ Boolean isDoubleTap;
+ Boolean isDraggingACover;
+ CGFloat startPosition;
+}
+
+@property (nonatomic, assign) id <AFOpenFlowViewDataSource> dataSource;
+@property (nonatomic, assign) id <AFOpenFlowViewDelegate> viewDelegate;
+@property (nonatomic, retain) UIImage *defaultImage;
+@property (nonatomic) int numberOfImages;
+
+- (void)setSelectedCover:(int)newSelectedCover;
+- (void)centerOnSelectedCover:(BOOL)animated;
+- (void)setImage:(UIImage *)image forIndex:(int)index;
+- (void)updateLayout;
+
+@end
+
+@protocol AFOpenFlowViewDelegate <NSObject>
+@optional
+- (void)openFlowView:(AFOpenFlowView *)openFlowView click:(int)index;
+- (void)openFlowView:(AFOpenFlowView *)openFlowView selectionDidChange:(int)index;
+@end
+
+@protocol AFOpenFlowViewDataSource <NSObject>
+- (void)openFlowView:(AFOpenFlowView *)openFlowView requestImageForIndex:(int)index;
+- (UIImage *)defaultImage;
+@end
+
+#endif
472 build/iphone/Classes/AFOpenFlow/AFOpenFlowView.m
@@ -0,0 +1,472 @@
+/**
+ * Copyright (c) 2009 Alex Fajkowski, Apparent Logic LLC
+ *
+ * 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.
+ */
+#if defined(USE_TI_UIIOSCOVERFLOWVIEW) || defined(USE_TI_UICOVERFLOWVIEW)
+
+#import "AFOpenFlowView.h"
+#import "AFOpenFlowConstants.h"
+#import "AFUIImageReflection.h"
+
+
+@interface AFOpenFlowView (hidden)
+
+- (void)setUpInitialState;
+- (AFItemView *)coverForIndex:(int)coverIndex;
+- (void)updateCoverImage:(AFItemView *)aCover;
+- (AFItemView *)dequeueReusableCover;
+- (void)layoutCovers:(int)selected fromCover:(int)lowerBound toCover:(int)upperBound;
+- (void)layoutCover:(AFItemView *)aCover selectedCover:(int)selectedIndex animated:(Boolean)animated;
+- (AFItemView *)findCoverOnscreen:(CALayer *)targetLayer;
+
+@end
+
+@implementation AFOpenFlowView (hidden)
+
+const static CGFloat kReflectionFraction = 0.85;
+
+- (void)setUpInitialState {
+ // Set up the default image for the coverflow.
+ self.defaultImage = [self.dataSource defaultImage];
+
+ // Create data holders for onscreen & offscreen covers & UIImage objects.
+ coverImages = [[NSMutableDictionary alloc] init];
+ coverImageHeights = [[NSMutableDictionary alloc] init];
+ offscreenCovers = [[NSMutableSet alloc] init];
+ onscreenCovers = [[NSMutableDictionary alloc] init];
+
+ scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
+ scrollView.userInteractionEnabled = NO;
+ scrollView.multipleTouchEnabled = NO;
+ scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ [self addSubview:scrollView];
+
+ self.multipleTouchEnabled = NO;
+ self.userInteractionEnabled = YES;
+ self.autoresizesSubviews = YES;
+ self.layer.position=CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
+
+ // Initialize the visible and selected cover range.
+ lowerVisibleCover = upperVisibleCover = -1;
+ selectedCoverView = nil;
+
+ // Set up the cover's left & right transforms.
+ leftTransform = CATransform3DTranslate(CATransform3DIdentity, 0, 0, SIDE_COVER_ZPOSITION);
+ leftTransform = CATransform3DRotate(leftTransform, SIDE_COVER_ANGLE, 0.0f, 1.0f, 0.0f);
+ rightTransform = CATransform3DTranslate(CATransform3DIdentity, 0, 0, SIDE_COVER_ZPOSITION);
+ rightTransform = CATransform3DRotate(rightTransform, SIDE_COVER_ANGLE, 0.0f, -1.0f, 0.0f);
+
+ // Set some perspective
+ CATransform3D sublayerTransform = CATransform3DIdentity;
+ sublayerTransform.m34 = -0.01;
+ [scrollView.layer setSublayerTransform:sublayerTransform];
+
+ [self updateLayout];
+}
+
+- (AFItemView *)coverForIndex:(int)coverIndex {
+ AFItemView *coverView = [self dequeueReusableCover];
+ if (!coverView)
+ coverView = [[[AFItemView alloc] initWithFrame:CGRectZero] autorelease];
+
+ coverView.number = coverIndex;
+
+ return coverView;
+}
+
+- (void)updateCoverImage:(AFItemView *)aCover {
+ NSNumber *coverNumber = [NSNumber numberWithInt:aCover.number];
+ UIImage *coverImage = (UIImage *)[coverImages objectForKey:coverNumber];
+ if (coverImage) {
+ NSNumber *coverImageHeightNumber = (NSNumber *)[coverImageHeights objectForKey:coverNumber];
+ if (coverImageHeightNumber)
+ [aCover setImage:coverImage originalImageHeight:[coverImageHeightNumber floatValue] reflectionFraction:kReflectionFraction];
+ } else {
+ // Bugfix for invalid defaultImage - SPT
+ UIImage* cover = defaultImage;
+ if (cover == nil) {
+ cover = [self.dataSource defaultImage];
+ }
+ [aCover setImage:cover originalImageHeight:defaultImageHeight reflectionFraction:kReflectionFraction];
+ [self.dataSource openFlowView:self requestImageForIndex:aCover.number];
+ }
+}
+
+- (AFItemView *)dequeueReusableCover {
+ AFItemView *aCover = [offscreenCovers anyObject];
+ if (aCover) {
+ [[aCover retain] autorelease];
+ [offscreenCovers removeObject:aCover];
+ }
+ return aCover;
+}
+
+- (void)layoutCover:(AFItemView *)aCover selectedCover:(int)selectedIndex animated:(Boolean)animated {
+ int coverNumber = aCover.number;
+ CATransform3D newTransform;
+ CGPoint newPosition;
+
+ newPosition.x = halfScreenWidth + aCover.horizontalPosition;
+ newPosition.y = halfScreenHeight + aCover.verticalPosition;
+ if (coverNumber < selectedIndex) {
+ newPosition.x -= CENTER_COVER_OFFSET;
+ newTransform = leftTransform;
+ } else if (coverNumber > selectedIndex) {
+ newPosition.x += CENTER_COVER_OFFSET;
+ newTransform = rightTransform;
+ } else {
+ newTransform = CATransform3DIdentity;
+ }
+
+ if (animated) {
+ [UIView beginAnimations:nil context:nil];
+ [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
+ [UIView setAnimationBeginsFromCurrentState:YES];
+ }
+
+ aCover.layer.transform = newTransform;
+ aCover.layer.position = newPosition;
+
+ if (animated) {
+ [UIView commitAnimations];
+ }
+}
+
+- (void)layoutCovers:(int)selected fromCover:(int)lowerBound toCover:(int)upperBound {
+ AFItemView *cover;
+ NSNumber *coverNumber;
+ for (int i = lowerBound; i <= upperBound; i++) {
+ coverNumber = [[NSNumber alloc] initWithInt:i];
+ cover = (AFItemView *)[onscreenCovers objectForKey:coverNumber];
+ [coverNumber release];
+ [self layoutCover:cover selectedCover:selected animated:YES];
+ }
+}
+
+- (AFItemView *)findCoverOnscreen:(CALayer *)targetLayer {
+ // See if this layer is one of our covers.
+ NSEnumerator *coverEnumerator = [onscreenCovers objectEnumerator];
+ AFItemView *aCover = nil;
+ while (aCover = (AFItemView *)[coverEnumerator nextObject])
+ if ([[aCover.imageView layer] isEqual:targetLayer])
+ break;
+
+ return aCover;
+}
+@end
+
+
+@implementation AFOpenFlowView
+@synthesize dataSource, viewDelegate, numberOfImages, defaultImage;
+
+#define COVER_BUFFER 6
+
+- (void)awakeFromNib {
+ [self setUpInitialState];
+}
+
+- (id)initWithFrame:(CGRect)frame {
+ if (self = [super initWithFrame:frame]) {
+ [self setUpInitialState];
+ }
+
+ return self;
+}
+
+- (void)dealloc {
+ [defaultImage release];
+ [scrollView release];
+
+ [coverImages release];
+ [coverImageHeights release];
+ [offscreenCovers removeAllObjects];
+ [offscreenCovers release];
+
+ [onscreenCovers removeAllObjects];
+ [onscreenCovers release];
+
+ [super dealloc];
+}
+
+- (void)updateLayout
+{
+ halfScreenWidth = self.bounds.size.width / 2;
+ halfScreenHeight = self.bounds.size.height / 2;
+
+ int lowerBound = MAX(-1, selectedCoverView.number - COVER_BUFFER);
+ int upperBound = MIN(self.numberOfImages - 1, selectedCoverView.number + COVER_BUFFER);
+
+ [self layoutCovers:selectedCoverView.number fromCover:lowerBound toCover:upperBound];
+ [self centerOnSelectedCover:NO];
+}
+
+- (void)setFrame:(CGRect)newSize {
+ [super setFrame:newSize];
+ [self updateLayout];
+}
+
+- (void)setBounds:(CGRect)newSize {
+ [super setBounds:newSize];
+ [self updateLayout];
+}
+
+- (void)setNumberOfImages:(int)newNumberOfImages {
+ numberOfImages = newNumberOfImages;
+ scrollView.contentSize = CGSizeMake(newNumberOfImages * COVER_SPACING + self.bounds.size.width, self.bounds.size.height);
+
+ int lowerBound = MAX(0, selectedCoverView.number - COVER_BUFFER);
+ int upperBound = MIN(self.numberOfImages - 1, selectedCoverView.number + COVER_BUFFER);
+
+ if (selectedCoverView)
+ [self layoutCovers:selectedCoverView.number fromCover:lowerBound toCover:upperBound];
+ else
+ [self setSelectedCover:0];
+
+ [self centerOnSelectedCover:NO];
+}
+
+- (void)setDefaultImage:(UIImage *)newDefaultImage {
+ [defaultImage release];
+ if (newDefaultImage)
+ {
+ defaultImageHeight = newDefaultImage.size.height;
+ defaultImage = [AddImageReflection(newDefaultImage,kReflectionFraction) retain];
+ }
+}
+
+- (void)setImage:(UIImage *)image forIndex:(int)index {
+ if (image==nil) return;
+ // Create a reflection for this image.
+ UIImage *imageWithReflection = AddImageReflection(image,kReflectionFraction);
+ NSNumber *coverNumber = [NSNumber numberWithInt:index];
+ [coverImages setObject:imageWithReflection forKey:coverNumber];
+ [coverImageHeights setObject:[NSNumber numberWithFloat:image.size.height] forKey:coverNumber];
+
+ // If this cover is onscreen, set its image and call layoutCover.
+ AFItemView *aCover = (AFItemView *)[onscreenCovers objectForKey:[NSNumber numberWithInt:index]];
+ if (aCover) {
+ [aCover setImage:imageWithReflection originalImageHeight:image.size.height reflectionFraction:kReflectionFraction];
+ [self layoutCover:aCover selectedCover:selectedCoverView.number animated:NO];
+ }
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+ CGPoint startPoint = [[touches anyObject] locationInView:self];
+ isDraggingACover = NO;
+
+ // Which cover did the user tap?
+ CALayer *targetLayer = (CALayer *)[scrollView.layer hitTest:startPoint];
+ AFItemView *targetCover = [self findCoverOnscreen:targetLayer];
+ isDraggingACover = (targetCover != nil);
+
+ beginningCover = selectedCoverView.number;
+ // Make sure the user is tapping on a cover.
+ startPosition = (startPoint.x / 1.5) + scrollView.contentOffset.x;
+
+ if (isSingleTap)
+ isDoubleTap = YES;
+
+ isSingleTap = ([touches count] == 1);
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+ isSingleTap = NO;
+ isDoubleTap = NO;
+
+ // Only scroll if the user started on a cover.
+ if (!isDraggingACover)
+ return;
+
+ CGPoint movedPoint = [[touches anyObject] locationInView:self];
+ CGFloat offset = startPosition - (movedPoint.x / 1.5);
+ CGPoint newPoint = CGPointMake(offset, 0);
+ scrollView.contentOffset = newPoint;
+ int newCover = offset / COVER_SPACING;
+ if (newCover != selectedCoverView.number) {
+ if (newCover < 0)
+ [self setSelectedCover:0];
+ else if (newCover >= self.numberOfImages)
+ [self setSelectedCover:self.numberOfImages - 1];
+ else
+ [self setSelectedCover:newCover];
+ }
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+ if (isSingleTap) {
+ // Which cover did the user tap?
+ CGPoint targetPoint = [[touches anyObject] locationInView:self];
+ CALayer *targetLayer = (CALayer *)[scrollView.layer hitTest:targetPoint];
+ AFItemView *targetCover = [self findCoverOnscreen:targetLayer];
+ if (targetCover && (targetCover.number != selectedCoverView.number))
+ [self setSelectedCover:targetCover.number];
+
+ //jhaynie: modification to send click events on single taps
+ if ([self.viewDelegate respondsToSelector:@selector(openFlowView:click:)])
+ {
+ [self.viewDelegate openFlowView:self click:selectedCoverView.number];
+ }
+ }
+ [self centerOnSelectedCover:YES];
+
+ // And send the delegate the newly selected cover message.
+ if (beginningCover != selectedCoverView.number)
+ if ([self.viewDelegate respondsToSelector:@selector(openFlowView:selectionDidChange:)])
+ [self.viewDelegate openFlowView:self selectionDidChange:selectedCoverView.number];
+}
+
+- (void)centerOnSelectedCover:(BOOL)animated {
+ CGPoint selectedOffset = CGPointMake(COVER_SPACING * selectedCoverView.number, 0);
+ [scrollView setContentOffset:selectedOffset animated:animated];
+}
+
+- (void)setSelectedCover:(int)newSelectedCover {
+ if (selectedCoverView && (newSelectedCover == selectedCoverView.number))
+ return;
+
+ AFItemView *cover;
+ int newLowerBound = MAX(0, newSelectedCover - COVER_BUFFER);
+ int newUpperBound = MIN(self.numberOfImages - 1, newSelectedCover + COVER_BUFFER);
+ if (!selectedCoverView) {
+ // Allocate and display covers from newLower to newUpper bounds.
+ for (int i=newLowerBound; i <= newUpperBound; i++) {
+ cover = [self coverForIndex:i];
+ [onscreenCovers setObject:cover forKey:[NSNumber numberWithInt:i]];
+ [self updateCoverImage:cover];
+ [scrollView.layer addSublayer:cover.layer];
+ [self layoutCover:cover selectedCover:newSelectedCover animated:NO];
+ }
+
+ lowerVisibleCover = newLowerBound;
+ upperVisibleCover = newUpperBound;
+ selectedCoverView = (AFItemView *)[onscreenCovers objectForKey:[NSNumber numberWithInt:newSelectedCover]];
+
+ return;
+ }
+
+ // Check to see if the new & current ranges overlap.
+ if ((newLowerBound > upperVisibleCover) || (newUpperBound < lowerVisibleCover)) {
+ // They do not overlap at all.
+ // This does not animate--assuming it's programmatically set from view controller.
+ // Recycle all onscreen covers.
+ AFItemView *cover;
+ for (int i = lowerVisibleCover; i <= upperVisibleCover; i++) {
+ cover = (AFItemView *)[onscreenCovers objectForKey:[NSNumber numberWithInt:i]];
+ [offscreenCovers addObject:cover];
+ [cover.layer removeFromSuperlayer];
+ [onscreenCovers removeObjectForKey:[NSNumber numberWithInt:cover.number]];
+ }
+
+ // Move all available covers to new location.
+ for (int i=newLowerBound; i <= newUpperBound; i++) {
+ cover = [self coverForIndex:i];
+ [onscreenCovers setObject:cover forKey:[NSNumber numberWithInt:i]];
+ [self updateCoverImage:cover];
+ [scrollView.layer addSublayer:cover.layer];
+ }
+
+ lowerVisibleCover = newLowerBound;
+ upperVisibleCover = newUpperBound;
+ selectedCoverView = (AFItemView *)[onscreenCovers objectForKey:[NSNumber numberWithInt:newSelectedCover]];
+ [self layoutCovers:newSelectedCover fromCover:newLowerBound toCover:newUpperBound];
+
+ return;
+ } else if (newSelectedCover > selectedCoverView.number) {
+ // Move covers that are now out of range on the left to the right side,
+ // but only if appropriate (within the range set by newUpperBound).
+ for (int i=lowerVisibleCover; i < newLowerBound; i++) {
+ cover = (AFItemView *)[onscreenCovers objectForKey:[NSNumber numberWithInt:i]];
+ if (upperVisibleCover < newUpperBound) {
+ // Tack it on the right side.
+ upperVisibleCover++;
+ cover.number = upperVisibleCover;
+ [self updateCoverImage:cover];
+ [onscreenCovers setObject:cover forKey:[NSNumber numberWithInt:cover.number]];
+ [self layoutCover:cover selectedCover:newSelectedCover animated:NO];
+ } else {
+ // Recycle this cover.
+ [offscreenCovers addObject:cover];
+ [cover.layer removeFromSuperlayer];
+ }
+ [onscreenCovers removeObjectForKey:[NSNumber numberWithInt:i]];
+ }
+ lowerVisibleCover = newLowerBound;
+
+ // Add in any missing covers on the right up to the newUpperBound.
+ for (int i=upperVisibleCover + 1; i <= newUpperBound; i++) {
+ cover = [self coverForIndex:i];
+ [onscreenCovers setObject:cover forKey:[NSNumber numberWithInt:i]];
+ [self updateCoverImage:cover];
+ [scrollView.layer addSublayer:cover.layer];
+ [self layoutCover:cover selectedCover:newSelectedCover animated:NO];
+ }
+ upperVisibleCover = newUpperBound;
+ } else {
+ // Move covers that are now out of range on the right to the left side,
+ // but only if appropriate (within the range set by newLowerBound).
+ for (int i=upperVisibleCover; i > newUpperBound; i--) {
+ cover = (AFItemView *)[onscreenCovers objectForKey:[NSNumber numberWithInt:i]];
+ if (lowerVisibleCover > newLowerBound) {
+ // Tack it on the left side.
+ lowerVisibleCover --;
+ cover.number = lowerVisibleCover;
+ [self updateCoverImage:cover];
+ [onscreenCovers setObject:cover forKey:[NSNumber numberWithInt:lowerVisibleCover]];
+ [self layoutCover:cover selectedCover:newSelectedCover animated:NO];
+ } else {
+ // Recycle this cover.
+ [offscreenCovers addObject:cover];
+ [cover.layer removeFromSuperlayer];
+ }
+ [onscreenCovers removeObjectForKey:[NSNumber numberWithInt:i]];
+ }
+ upperVisibleCover = newUpperBound;
+
+ // Add in any missing covers on the left down to the newLowerBound.
+ for (int i=lowerVisibleCover - 1; i >= newLowerBound; i--) {
+ cover = [self coverForIndex:i];
+ [onscreenCovers setObject:cover forKey:[NSNumber numberWithInt:i]];
+ [self updateCoverImage:cover];
+ [scrollView.layer addSublayer:cover.layer];
+ [self layoutCover:cover selectedCover:newSelectedCover animated:NO];
+ }
+ lowerVisibleCover = newLowerBound;
+ }
+
+ if (selectedCoverView.number > newSelectedCover)
+ [self layoutCovers:newSelectedCover fromCover:newSelectedCover toCover:selectedCoverView.number];
+ else if (newSelectedCover > selectedCoverView.number)
+ [self layoutCovers:newSelectedCover fromCover:selectedCoverView.number toCover:newSelectedCover];
+
+ selectedCoverView = (AFItemView *)[onscreenCovers objectForKey:[NSNumber numberWithInt:newSelectedCover]];
+}
+
+-(void)layoutSubviews
+{
+ [self centerOnSelectedCover:NO];
+ [super layoutSubviews];
+}
+
+@end
+
+#endif
37 build/iphone/Classes/AFOpenFlow/AFUIImageReflection.h
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2009 Alex Fajkowski, Apparent Logic LLC
+ *
+ * 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.
+ */
+#if defined(USE_TI_UIIOSCOVERFLOWVIEW) || defined(USE_TI_UICOVERFLOWVIEW)
+
+#import <UIKit/UIKit.h>
+
+// BeerShift modification note:
+// using categories with static libraries don't seem to work
+// right on device with iphone - probably a symbol issue
+// turn this into a static function (from what was a category to UIImage
+// originally)
+
+UIImage* AddImageReflection(UIImage *src, CGFloat reflectionFraction);
+
+#endif
102 build/iphone/Classes/AFOpenFlow/AFUIImageReflection.m
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2009 Alex Fajkowski, Apparent Logic LLC
+ *
+ * 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.
+ */
+#if defined(USE_TI_UIIOSCOVERFLOWVIEW) || defined(USE_TI_UICOVERFLOWVIEW)
+
+#import "AFUIImageReflection.h"
+
+
+// BeerShift modification note:
+// using categories with static libraries don't seem to work
+// right on device with iphone - probably a symbol issue
+// turn this into a static function (from what was a category to UIImage
+// originally)
+
+UIImage* AddImageReflection(UIImage *image, CGFloat reflectionFraction)
+{
+ int reflectionHeight = ceilf(image.size.height * reflectionFraction);
+
+ // create a 2 bit CGImage containing a gradient that will be used for masking the
+ // main view content to create the 'fade' of the reflection. The CGImageCreateWithMask
+ // function will stretch the bitmap image as required, so we can create a 1 pixel wide gradient
+ CGImageRef gradientMaskImage = NULL;
+
+ // gradient is always black-white and the mask must be in the gray colorspace
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
+
+ // create the bitmap context
+ CGContextRef gradientBitmapContext = CGBitmapContextCreate(nil, 1, reflectionHeight,
+ 8, 0, colorSpace, kCGImageAlphaNone);
+
+ // define the start and end grayscale values (with the alpha, even though
+ // our bitmap context doesn't support alpha the gradient requires it)
+ CGFloat colors[] = {0.0, 1.0, 1.0, 1.0};
+
+ // create the CGGradient and then release the gray color space
+ CGGradientRef grayScaleGradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 2);
+ CGColorSpaceRelease(colorSpace);
+
+ // create the start and end points for the gradient vector (straight down)
+ CGPoint gradientStartPoint = CGPointMake(0, reflectionHeight);
+ CGPoint gradientEndPoint = CGPointZero;
+
+ // draw the gradient into the gray bitmap context
+ CGContextDrawLinearGradient(gradientBitmapContext, grayScaleGradient, gradientStartPoint,
+ gradientEndPoint, kCGGradientDrawsAfterEndLocation);
+ CGGradientRelease(grayScaleGradient);
+
+ // add a black fill with 50% opacity
+ CGContextSetGrayFillColor(gradientBitmapContext, 0.0, 0.5);
+ CGContextFillRect(gradientBitmapContext, CGRectMake(0, 0, 1, reflectionHeight));
+
+ // convert the context into a CGImageRef and release the context
+ gradientMaskImage = CGBitmapContextCreateImage(gradientBitmapContext);
+ CGContextRelease(gradientBitmapContext);
+
+ // create an image by masking the bitmap of the mainView content with the gradient view
+ // then release the pre-masked content bitmap and the gradient bitmap
+ if((image.CGImage == NULL) || (gradientMaskImage == NULL))
+ {
+ CGImageRelease(gradientMaskImage);
+ return nil;
+ }
+ CGImageRef reflectionImage = CGImageCreateWithMask(image.CGImage, gradientMaskImage);
+ CGImageRelease(gradientMaskImage);
+
+ CGSize size = CGSizeMake(image.size.width, image.size.height + reflectionHeight);
+
+ UIGraphicsBeginImageContext(size);
+
+ [image drawAtPoint:CGPointZero];
+ CGContextRef context = UIGraphicsGetCurrentContext();
+ CGContextDrawImage(context, CGRectMake(0, image.size.height, image.size.width, reflectionHeight), reflectionImage);
+
+ UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ CGImageRelease(reflectionImage);
+
+ return result;
+}
+
+#endif
38 build/iphone/Classes/AFOpenFlow/UIImageExtras.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2009 Alex Fajkowski, Apparent Logic LLC
+ *
+ * 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.
+ */