Browse files

Initial commit

  • Loading branch information...
0 parents commit 33dc2ec997a7f2173facd74753fbe27c4cad1245 @Mindelusions committed Aug 17, 2011
Showing with 27,592 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +23 −0 .project
  3. +3 −0 .settings/com.appcelerator.titanium.mobile.prefs
  4. +1 −0 CHANGELOG.txt
  5. +219 −0 LICENSE
  6. +1 −0 LICENSE.txt
  7. +18 −0 README
  8. BIN Resources/KS_nav_ui.png
  9. BIN Resources/KS_nav_views.png
  10. BIN Resources/android/appicon.png
  11. BIN Resources/android/default.png
  12. BIN Resources/android/images/res-long-land-hdpi/default.png
  13. BIN Resources/android/images/res-long-land-ldpi/default.png
  14. BIN Resources/android/images/res-long-port-hdpi/default.png
  15. BIN Resources/android/images/res-long-port-ldpi/default.png
  16. BIN Resources/android/images/res-notlong-land-hdpi/default.png
  17. BIN Resources/android/images/res-notlong-land-ldpi/default.png
  18. BIN Resources/android/images/res-notlong-land-mdpi/default.png
  19. BIN Resources/android/images/res-notlong-port-hdpi/default.png
  20. BIN Resources/android/images/res-notlong-port-ldpi/default.png
  21. BIN Resources/android/images/res-notlong-port-mdpi/default.png
  22. +82 −0 Resources/app.js
  23. BIN Resources/iphone/Default-Landscape.png
  24. BIN Resources/iphone/Default-Portrait.png
  25. BIN Resources/iphone/Default.png
  26. BIN Resources/iphone/Default@2x.png
  27. BIN Resources/iphone/appicon.png
  28. +307 −0 Resources/jspdf.js
  29. +143 −0 Resources/libs/base64.js
  30. +152 −0 Resources/libs/sprintf.js
  31. +8 −0 build/android/.classpath
  32. +6 −0 build/android/.gitignore
  33. +33 −0 build/android/.project
  34. +22 −0 build/android/default.properties
  35. +48 −0 build/iphone/Classes/AFOpenFlow/AFItemView.h
  36. +93 −0 build/iphone/Classes/AFOpenFlow/AFItemView.m
  37. +33 −0 build/iphone/Classes/AFOpenFlow/AFOpenFlowConstants.h
  38. +87 −0 build/iphone/Classes/AFOpenFlow/AFOpenFlowView.h
  39. +475 −0 build/iphone/Classes/AFOpenFlow/AFOpenFlowView.m
  40. +37 −0 build/iphone/Classes/AFOpenFlow/AFUIImageReflection.h
  41. +102 −0 build/iphone/Classes/AFOpenFlow/AFUIImageReflection.m
  42. +38 −0 build/iphone/Classes/AFOpenFlow/UIImageExtras.h
  43. +80 −0 build/iphone/Classes/AFOpenFlow/UIImageExtras.m
  44. +19 −0 build/iphone/Classes/APIModule.h
  45. +117 −0 build/iphone/Classes/APIModule.m
  46. +104 −0 build/iphone/Classes/AQRecorder.h
  47. +361 −0 build/iphone/Classes/AQRecorder.mm
  48. +28 −0 build/iphone/Classes/ASI/ASIAuthenticationDialog.h
  49. +236 −0 build/iphone/Classes/ASI/ASIAuthenticationDialog.m
  50. +76 −0 build/iphone/Classes/ASI/ASIFormDataRequest.h
  51. +363 −0 build/iphone/Classes/ASI/ASIFormDataRequest.m
  52. +787 −0 build/iphone/Classes/ASI/ASIHTTPRequest.h
  53. +3,908 −0 build/iphone/Classes/ASI/ASIHTTPRequest.m
  54. +68 −0 build/iphone/Classes/ASI/ASIHTTPRequestConfig.h
  55. +33 −0 build/iphone/Classes/ASI/ASIHTTPRequestDelegate.h
  56. +26 −0 build/iphone/Classes/ASI/ASIInputStream.h
  57. +136 −0 build/iphone/Classes/ASI/ASIInputStream.m
  58. +16 −0 build/iphone/Classes/ASI/ASINSStringAdditions.h
  59. +28 −0 build/iphone/Classes/ASI/ASINSStringAdditions.m
  60. +112 −0 build/iphone/Classes/ASI/ASINetworkQueue.h
  61. +341 −0 build/iphone/Classes/ASI/ASINetworkQueue.m
  62. +38 −0 build/iphone/Classes/ASI/ASIProgressDelegate.h
  63. +88 −0 build/iphone/Classes/ASI/Reachability.h
  64. +274 −0 build/iphone/Classes/ASI/Reachability.m
  65. +19 −0 build/iphone/Classes/AccelerometerModule.h
  66. +48 −0 build/iphone/Classes/AccelerometerModule.m
  67. +22 −0 build/iphone/Classes/AnalyticsModule.h
  68. +705 −0 build/iphone/Classes/AnalyticsModule.m
  69. +53 −0 build/iphone/Classes/AppModule.h
  70. +423 −0 build/iphone/Classes/AppModule.m
  71. +11 −0 build/iphone/Classes/ApplicationMods.h
  72. +15 −0 build/iphone/Classes/ApplicationMods.m
  73. +10 −0 build/iphone/Classes/ApplicationRouting.h
  74. +15 −0 build/iphone/Classes/ApplicationRouting.m
  75. +690 −0 build/iphone/Classes/AsyncSocket.h
  76. +4,368 −0 build/iphone/Classes/AsyncSocket.m
  77. +366 −0 build/iphone/Classes/AsyncUdpSocket.h
  78. +2,343 −0 build/iphone/Classes/AsyncUdpSocket.m
  79. +138 −0 build/iphone/Classes/AudioStreamer/AudioStreamer.h
  80. +186 −0 build/iphone/Classes/AudioStreamer/AudioStreamer.m
  81. +87 −0 build/iphone/Classes/AudioStreamer/AudioStreamerBC.h
  82. +1,535 −0 build/iphone/Classes/AudioStreamer/AudioStreamerBC.m
  83. +108 −0 build/iphone/Classes/AudioStreamer/AudioStreamerCUR.h
  84. +1,806 −0 build/iphone/Classes/AudioStreamer/AudioStreamerCUR.m
  85. +232 −0 build/iphone/Classes/Base64Transcoder.c
  86. +36 −0 build/iphone/Classes/Base64Transcoder.h
  87. +36 −0 build/iphone/Classes/Bridge.h
  88. +84 −0 build/iphone/Classes/Bridge.m
  89. +94 −0 build/iphone/Classes/CADebugMacros.cpp
  90. +443 −0 build/iphone/Classes/CADebugMacros.h
  91. +74 −0 build/iphone/Classes/CAMath.h
  92. +554 −0 build/iphone/Classes/CAStreamBasicDescription.cpp
  93. +312 −0 build/iphone/Classes/CAStreamBasicDescription.h
  94. +56 −0 build/iphone/Classes/CAXException.cpp
  95. +218 −0 build/iphone/Classes/CAXException.h
  96. +42 −0 build/iphone/Classes/CodecModule.h
  97. +351 −0 build/iphone/Classes/CodecModule.m
  98. +54 −0 build/iphone/Classes/ContactsModule.h
  99. +438 −0 build/iphone/Classes/ContactsModule.m
  100. +26 −0 build/iphone/Classes/DatabaseModule.h
  101. +52 −0 build/iphone/Classes/DatabaseModule.m
  102. +22 −0 build/iphone/Classes/FBConnect/FBConnect.h
  103. +165 −0 build/iphone/Classes/FBConnect/FBDialog.h
  104. +650 −0 build/iphone/Classes/FBConnect/FBDialog.m
  105. +41 −0 build/iphone/Classes/FBConnect/FBLoginButton.h
  106. +92 −0 build/iphone/Classes/FBConnect/FBLoginButton.m
  107. +47 −0 build/iphone/Classes/FBConnect/FBLoginDialog.h
  108. +115 −0 build/iphone/Classes/FBConnect/FBLoginDialog.m
  109. +121 −0 build/iphone/Classes/FBConnect/FBRequest.h
  110. +358 −0 build/iphone/Classes/FBConnect/FBRequest.m
  111. +115 −0 build/iphone/Classes/FBConnect/Facebook.h
  112. +603 −0 build/iphone/Classes/FBConnect/Facebook.m
  113. +42 −0 build/iphone/Classes/FacebookModule.h
Sorry, we could not display the entire diff because too many files (916) changed.
1 .gitignore
@@ -0,0 +1 @@
+tmp
23 .project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>JSPDF</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.appcelerator.titanium.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.aptana.ide.core.unifiedBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.appcelerator.titanium.mobile.nature</nature>
+ <nature>com.aptana.projects.webnature</nature>
+ </natures>
+</projectDescription>
3 .settings/com.appcelerator.titanium.mobile.prefs
@@ -0,0 +1,3 @@
+#Wed Aug 17 09:52:37 PDT 2011
+MOBILE_PROJECT_SDK_VERSION=1.7.2
+eclipse.preferences.version=1
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/android/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/android/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/android/images/res-long-land-hdpi/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/android/images/res-long-land-ldpi/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/android/images/res-long-port-hdpi/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/android/images/res-long-port-ldpi/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/android/images/res-notlong-land-hdpi/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/android/images/res-notlong-land-ldpi/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/android/images/res-notlong-land-mdpi/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/android/images/res-notlong-port-hdpi/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/android/images/res-notlong-port-ldpi/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/android/images/res-notlong-port-mdpi/default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 Resources/app.js
@@ -0,0 +1,82 @@
+// this sets the background color of the master UIView (when there are no windows/tab groups on it)
+Titanium.UI.setBackgroundColor('#000');
+
+// create tab group
+var tabGroup = Titanium.UI.createTabGroup();
+
+
+//
+// create base UI tab and root window
+//
+var win1 = Titanium.UI.createWindow({
+ title:'Tab 1',
+ backgroundColor:'#fff'
+});
+var tab1 = Titanium.UI.createTab({
+ icon:'KS_nav_views.png',
+ title:'Tab 1',
+ window:win1
+});
+
+var label1 = Titanium.UI.createLabel({
+ color:'#999',
+ text:'I am Window 1',
+ font:{fontSize:20,fontFamily:'Helvetica Neue'},
+ textAlign:'center',
+ width:'auto'
+});
+
+win1.add(label1);
+
+//
+// create controls tab and root window
+//
+var win2 = Titanium.UI.createWindow({
+ title:'Tab 2',
+ backgroundColor:'#fff'
+});
+var tab2 = Titanium.UI.createTab({
+ icon:'KS_nav_ui.png',
+ title:'Tab 2',
+ window:win2
+});
+
+var label2 = Titanium.UI.createLabel({
+ color:'#999',
+ text:'I am Window 2',
+ font:{fontSize:20,fontFamily:'Helvetica Neue'},
+ textAlign:'center',
+ width:'auto'
+});
+
+win2.add(label2);
+
+
+
+//
+// add tabs
+//
+tabGroup.addTab(tab1);
+tabGroup.addTab(tab2);
+
+
+// open tab group
+tabGroup.open();
+
+
+// JSPDF
+Ti.include('jspdf.js');
+
+var doc = new jsPDF();
+doc.text(20, 20, 'Hello world!');
+doc.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');
+doc.addPage();
+doc.text(20, 20, 'Do you like that?');
+
+var res = doc.output();
+var file = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory, 'test.pdf');
+file.write(res);
+var pdfview = Ti.UI.createWebView({width:'100%',height:'100%',data:file});
+var win = Ti.UI.createWindow();
+win.add(pdfview);
+win.open({modal:true});
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.
307 Resources/jspdf.js
@@ -0,0 +1,307 @@
+/**
+ * jsPDF
+ * (c) 2009 James Hall
+ *
+ * Some parts based on FPDF.
+ */
+
+Ti.include(
+ '/libs/sprintf.js',
+ '/libs/base64.js'
+);
+var jsPDF = function(){
+
+ // Private properties
+ var version = '20090504';
+ var buffer = '';
+
+ var pdfVersion = '1.3'; // PDF Version
+ var defaultPageFormat = 'a4';
+ var pageFormats = { // Size in mm of various paper formats
+ 'a3': [841.89, 1190.55],
+ 'a4': [595.28, 841.89],
+ 'a5': [420.94, 595.28],
+ 'letter': [612, 792],
+ 'legal': [612, 1008]
+ };
+ var textColor = '0 g';
+ var page = 0;
+ var objectNumber = 2; // 'n' Current object number
+ var state = 0; // Current document state
+ var pages = new Array();
+ var offsets = new Array(); // List of offsets
+ var lineWidth = 0.200025; // 2mm
+ var pageHeight;
+ var k; // Scale factor
+ var unit = 'mm'; // Default to mm for units
+ var fontNumber; // TODO: This is temp, replace with real font handling
+ var documentProperties = {};
+ var fontSize = 16; // Default font size
+ var pageFontSize = 16;
+
+ // Initilisation
+ if (unit == 'pt') {
+ k = 1;
+ } else if(unit == 'mm') {
+ k = 72/25.4;
+ } else if(unit == 'cm') {
+ k = 72/2.54;
+ } else if(unit == 'in') {
+ k = 72;
+ }
+
+ // Private functions
+ var newObject = function() {
+ //Begin a new object
+ objectNumber ++;
+ offsets[objectNumber] = buffer.length;
+ out(objectNumber + ' 0 obj');
+ }
+
+
+ var putHeader = function() {
+ out('%PDF-' + pdfVersion);
+ }
+
+ var putPages = function() {
+
+ // TODO: Fix, hardcoded to a4 portrait
+ var wPt = pageWidth * k;
+ var hPt = pageHeight * k;
+
+ for(n=1; n <= page; n++) {
+ newObject();
+ out('<</Type /Page');
+ out('/Parent 1 0 R');
+ out('/Resources 2 0 R');
+ out('/Contents ' + (objectNumber + 1) + ' 0 R>>');
+ out('endobj');
+
+ //Page content
+ p = pages[n];
+ newObject();
+ out('<</Length ' + p.length + '>>');
+ putStream(p);
+ out('endobj');
+ }
+ offsets[1] = buffer.length;
+ out('1 0 obj');
+ out('<</Type /Pages');
+ var kids='/Kids [';
+ for (i = 0; i < page; i++) {
+ kids += (3 + 2 * i) + ' 0 R ';
+ }
+ out(kids + ']');
+ out('/Count ' + page);
+ out(sprintf('/MediaBox [0 0 %.2f %.2f]', wPt, hPt));
+ out('>>');
+ out('endobj');
+ }
+
+ var putStream = function(str) {
+ out('stream');
+ out(str);
+ out('endstream');
+ }
+
+ var putResources = function() {
+ putFonts();
+ putImages();
+
+ //Resource dictionary
+ offsets[2] = buffer.length;
+ out('2 0 obj');
+ out('<<');
+ putResourceDictionary();
+ out('>>');
+ out('endobj');
+ }
+
+ var putFonts = function() {
+ // TODO: Only supports core font hardcoded to Helvetica
+ newObject();
+ fontNumber = objectNumber;
+ name = 'Helvetica';
+ out('<</Type /Font');
+ out('/BaseFont /' + name);
+ out('/Subtype /Type1');
+ out('/Encoding /WinAnsiEncoding');
+ out('>>');
+ out('endobj');
+ }
+
+ var putImages = function() {
+ // TODO
+ }
+
+ var putResourceDictionary = function() {
+ out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
+ out('/Font <<');
+ // Do this for each font, the '1' bit is the index of the font
+ // fontNumber is currently the object number related to 'putFonts'
+ out('/F1 ' + fontNumber + ' 0 R');
+ out('>>');
+ out('/XObject <<');
+ putXobjectDict();
+ out('>>');
+ }
+
+ var putXobjectDict = function() {
+ // TODO
+ // Loop through images
+ }
+
+
+ var putInfo = function() {
+ out('/Producer (jsPDF ' + version + ')');
+ if(documentProperties.title != undefined) {
+ out('/Title (' + pdfEscape(documentProperties.title) + ')');
+ }
+ if(documentProperties.subject != undefined) {
+ out('/Subject (' + pdfEscape(documentProperties.subject) + ')');
+ }
+ if(documentProperties.author != undefined) {
+ out('/Author (' + pdfEscape(documentProperties.author) + ')');
+ }
+ if(documentProperties.keywords != undefined) {
+ out('/Keywords (' + pdfEscape(documentProperties.keywords) + ')');
+ }
+ if(documentProperties.creator != undefined) {
+ out('/Creator (' + pdfEscape(documentProperties.creator) + ')');
+ }
+ var created = new Date();
+ var year = created.getFullYear();
+ var month = (created.getMonth() + 1);
+ var day = created.getDate();
+ var hour = created.getHours();
+ var minute = created.getMinutes();
+ var second = created.getSeconds();
+ out('/CreationDate (D:' + sprintf('%02d%02d%02d%02d%02d%02d', year, month, day, hour, minute, second) + ')');
+ }
+
+ var putCatalog = function () {
+ out('/Type /Catalog');
+ out('/Pages 1 0 R');
+ // TODO: Add zoom and layout modes
+ out('/OpenAction [3 0 R /FitH null]');
+ out('/PageLayout /OneColumn');
+ }
+
+ function putTrailer() {
+ out('/Size ' + (objectNumber + 1));
+ out('/Root ' + objectNumber + ' 0 R');
+ out('/Info ' + (objectNumber - 1) + ' 0 R');
+ }
+
+ var endDocument = function() {
+ state = 1;
+ putHeader();
+ putPages();
+
+ putResources();
+ //Info
+ newObject();
+ out('<<');
+ putInfo();
+ out('>>');
+ out('endobj');
+
+ //Catalog
+ newObject();
+ out('<<');
+ putCatalog();
+ out('>>');
+ out('endobj');
+
+ //Cross-ref
+ var o = buffer.length;
+ out('xref');
+ out('0 ' + (objectNumber + 1));
+ out('0000000000 65535 f ');
+ for (var i=1; i <= objectNumber; i++) {
+ out(sprintf('%010d 00000 n ', offsets[i]));
+ }
+ //Trailer
+ out('trailer');
+ out('<<');
+ putTrailer();
+ out('>>');
+ out('startxref');
+ out(o);
+ out('%%EOF');
+ state = 3;
+ }
+
+ var beginPage = function() {
+ page ++;
+ // Do dimension stuff
+ state = 2;
+ pages[page] = '';
+
+ // TODO: Hardcoded at A4 and portrait
+ pageHeight = pageFormats['a4'][1] / k;
+ pageWidth = pageFormats['a4'][0] / k;
+ }
+
+ var out = function(string) {
+ if(state == 2) {
+ pages[page] += string + '\n';
+ } else {
+ buffer += string + '\n';
+ }
+ }
+
+ var _addPage = function() {
+ beginPage();
+ // Set line width
+ out(sprintf('%.2f w', (lineWidth * k)));
+
+ // Set font - TODO
+ // 16 is the font size
+ pageFontSize = fontSize;
+ out('BT /F1 ' + parseInt(fontSize) + '.00 Tf ET');
+ }
+
+ // Add the first page automatically
+ _addPage();
+
+ // Escape text
+ var pdfEscape = function(text) {
+ return text.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
+ }
+
+ return {
+ addPage: function() {
+ _addPage();
+ },
+ text: function(x, y, text) {
+ // need page height
+ if(pageFontSize != fontSize) {
+ out('BT /F1 ' + parseInt(fontSize) + '.00 Tf ET');
+ pageFontSize = fontSize;
+ }
+ var str = sprintf('BT %.2f %.2f Td (%s) Tj ET', x * k, (pageHeight - y) * k, pdfEscape(text));
+ out(str);
+ },
+ setProperties: function(properties) {
+ documentProperties = properties;
+ },
+ addImage: function(imageData, format, x, y, w, h) {
+
+ },
+ output: function(type, options) {
+ endDocument();
+ if(type == undefined) {
+ return buffer;
+ }
+ if(type == 'datauri') {
+ return 'data:application/pdf;base64,' + Base64.encode(buffer);
+ }
+ // @TODO: Add different output options
+ },
+ setFontSize: function(size) {
+ fontSize = size;
+ }
+ }
+
+};
143 Resources/libs/base64.js
@@ -0,0 +1,143 @@
+
+/**
+*
+* Base64 encode / decode
+* http://www.webtoolkit.info/
+*
+**/
+
+var Base64 = {
+
+ // private property
+ _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+
+ // public method for encoding
+ encode : function (input) {
+ var output = "";
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = Base64._utf8_encode(input);
+
+ while (i < input.length) {
+
+ chr1 = input.charCodeAt(i++);
+ chr2 = input.charCodeAt(i++);
+ chr3 = input.charCodeAt(i++);
+
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+
+ output = output +
+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
+
+ }
+
+ return output;
+ },
+
+ // public method for decoding
+ decode : function (input) {
+ var output = "";
+ var chr1, chr2, chr3;
+ var enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+ while (i < input.length) {
+
+ enc1 = this._keyStr.indexOf(input.charAt(i++));
+ enc2 = this._keyStr.indexOf(input.charAt(i++));
+ enc3 = this._keyStr.indexOf(input.charAt(i++));
+ enc4 = this._keyStr.indexOf(input.charAt(i++));
+
+ chr1 = (enc1 << 2) | (enc2 >> 4);
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+ chr3 = ((enc3 & 3) << 6) | enc4;
+
+ output = output + String.fromCharCode(chr1);
+
+ if (enc3 != 64) {
+ output = output + String.fromCharCode(chr2);
+ }
+ if (enc4 != 64) {
+ output = output + String.fromCharCode(chr3);
+ }
+
+ }
+
+ output = Base64._utf8_decode(output);
+
+ return output;
+
+ },
+
+ // private method for UTF-8 encoding
+ _utf8_encode : function (string) {
+ string = string.replace(/\r\n/g,"\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++) {
+
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+
+ }
+
+ return utftext;
+ },
+
+ // private method for UTF-8 decoding
+ _utf8_decode : function (utftext) {
+ var string = "";
+ var i = 0;
+ var c = c1 = c2 = 0;
+
+ while ( i < utftext.length ) {
+
+ c = utftext.charCodeAt(i);
+
+ if (c < 128) {
+ string += String.fromCharCode(c);
+ i++;
+ }
+ else if((c > 191) && (c < 224)) {
+ c2 = utftext.charCodeAt(i+1);
+ string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+ i += 2;
+ }
+ else {
+ c2 = utftext.charCodeAt(i+1);
+ c3 = utftext.charCodeAt(i+2);
+ string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+ i += 3;
+ }
+
+ }
+
+ return string;
+ }
+
+}
152 Resources/libs/sprintf.js
@@ -0,0 +1,152 @@
+
+
+function sprintf( ) {
+ // Return a formatted string
+ //
+ // version: 903.3016
+ // discuss at: http://phpjs.org/functions/sprintf
+ // + original by: Ash Searle (http://hexmen.com/blog/)
+ // + namespaced by: Michael White (http://getsprink.com)
+ // + tweaked by: Jack
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + input by: Paulo Ricardo F. Santos
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + input by: Brett Zamir (http://brettz9.blogspot.com)
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // * example 1: sprintf("%01.2f", 123.1);
+ // * returns 1: 123.10
+ // * example 2: sprintf("[%10s]", 'monkey');
+ // * returns 2: '[ monkey]'
+ // * example 3: sprintf("[%'#10s]", 'monkey');
+ // * returns 3: '[####monkey]'
+ var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
+ var a = arguments, i = 0, format = a[i++];
+
+ // pad()
+ var pad = function(str, len, chr, leftJustify) {
+ if (!chr) chr = ' ';
+ var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
+ return leftJustify ? str + padding : padding + str;
+ };
+
+ // justify()
+ var justify = function(value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
+ var diff = minWidth - value.length;
+ if (diff > 0) {
+ if (leftJustify || !zeroPad) {
+ value = pad(value, minWidth, customPadChar, leftJustify);
+ } else {
+ value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
+ }
+ }
+ return value;
+ };
+
+ // formatBaseX()
+ var formatBaseX = function(value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
+ // Note: casts negative numbers to positive ones
+ var number = value >>> 0;
+ prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || '';
+ value = prefix + pad(number.toString(base), precision || 0, '0', false);
+ return justify(value, prefix, leftJustify, minWidth, zeroPad);
+ };
+
+ // formatString()
+ var formatString = function(value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
+ if (precision != null) {
+ value = value.slice(0, precision);
+ }
+ return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
+ };
+
+ // doFormat()
+ var doFormat = function(substring, valueIndex, flags, minWidth, _, precision, type) {
+ var number;
+ var prefix;
+ var method;
+ var textTransform;
+ var value;
+
+ if (substring == '%%') return '%';
+
+ // parse flags
+ var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, customPadChar = ' ';
+ var flagsl = flags.length;
+ for (var j = 0; flags && j < flagsl; j++) switch (flags.charAt(j)) {
+ case ' ': positivePrefix = ' '; break;
+ case '+': positivePrefix = '+'; break;
+ case '-': leftJustify = true; break;
+ case "'": customPadChar = flags.charAt(j+1); break;
+ case '0': zeroPad = true; break;
+ case '#': prefixBaseX = true; break;
+ }
+
+ // parameters may be null, undefined, empty-string or real valued
+ // we want to ignore null, undefined and empty-string values
+ if (!minWidth) {
+ minWidth = 0;
+ } else if (minWidth == '*') {
+ minWidth = +a[i++];
+ } else if (minWidth.charAt(0) == '*') {
+ minWidth = +a[minWidth.slice(1, -1)];
+ } else {
+ minWidth = +minWidth;
+ }
+
+ // Note: undocumented perl feature:
+ if (minWidth < 0) {
+ minWidth = -minWidth;
+ leftJustify = true;
+ }
+
+ if (!isFinite(minWidth)) {
+ throw new Error('sprintf: (minimum-)width must be finite');
+ }
+
+ if (!precision) {
+ precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0);
+ } else if (precision == '*') {
+ precision = +a[i++];
+ } else if (precision.charAt(0) == '*') {
+ precision = +a[precision.slice(1, -1)];
+ } else {
+ precision = +precision;
+ }
+
+ // grab value using valueIndex if required?
+ value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];
+
+ switch (type) {
+ case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
+ case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
+ case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
+ case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
+ case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
+ case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
+ case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
+ case 'i':
+ case 'd': {
+ number = parseInt(+value);
+ prefix = number < 0 ? '-' : positivePrefix;
+ value = prefix + pad(String(Math.abs(number)), precision, '0', false);
+ return justify(value, prefix, leftJustify, minWidth, zeroPad);
+ }
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G': {
+ number = +value;
+ prefix = number < 0 ? '-' : positivePrefix;
+ method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
+ textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
+ value = prefix + Math.abs(number)[method](precision);
+ return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
+ }
+ default: return substring;
+ }
+ };
+
+ return format.replace(regex, doFormat);
+}
8 build/android/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="lib" path="lib/titanium.jar"/>
+ <classpathentry kind="output" path="bin"/>
+ <classpathentry kind="src" path="gen"/>
+</classpath>
6 build/android/.gitignore
@@ -0,0 +1,6 @@
+src
+lib
+bin
+res
+gen
+AndroidManifest.xml
33 build/android/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>JSPDF</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
22 build/android/default.properties
@@ -0,0 +1,22 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# apk configurations. This property allows creation of APK files with limited
+# resources. For example, if your application contains many locales and
+# you wish to release multiple smaller apks instead of a large one, you can
+# define configuration to create apks with limited language sets.
+# Format is a comma separated list of configuration names. For each
+# configuration, a property will declare the resource configurations to
+# include. Example:
+# apk-configurations=european,northamerica
+# apk-config-european=en,fr,it,de,es
+# apk-config-northamerica=en,es
+apk-configurations=
+# Project target.
+target=android-7
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.
+ */
+#ifdef 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
93 build/iphone/Classes/AFOpenFlow/AFItemView.m
@@ -0,0 +1,93 @@
+/**
+ * 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.
+ */
+#ifdef USE_TI_UICOVERFLOWVIEW
+
+#import "AFItemView.h"
+#import <QuartzCore/QuartzCore.h>
+#import "AFOpenFlowConstants.h"
+
+
+@implementation AFItemView
+@synthesize number, 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);
+}
+
+- (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.
+ */
+#ifdef 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.
+ */
+#ifdef 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 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
475 build/iphone/Classes/AFOpenFlow/AFOpenFlowView.m
@@ -0,0 +1,475 @@
+/**
+ * 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.
+ */
+#ifdef 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 = CATransform3DIdentity;
+ leftTransform = CATransform3DRotate(leftTransform, SIDE_COVER_ANGLE, 0.0f, 1.0f, 0.0f);
+ rightTransform = CATransform3DIdentity;
+ 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;
+ CGFloat newZPosition = SIDE_COVER_ZPOSITION;
+ 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 {
+ newZPosition = 0;
+ newTransform = CATransform3DIdentity;
+ }
+
+ if (animated) {
+ [UIView beginAnimations:nil context:nil];
+ [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
+ [UIView setAnimationBeginsFromCurrentState:YES];
+ }
+
+ aCover.layer.transform = newTransform;
+ aCover.layer.zPosition = newZPosition;
+ 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.
+ */
+#ifdef USE_TI_UICOVERFLOWVIEW
+
+#import <UIKit/UIKit.h>
+
+// JSPDF 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.
+ */
+#ifdef USE_TI_UICOVERFLOWVIEW
+
+#import "AFUIImageReflection.h"
+
+
+// JSPDF 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.
+ */
+#import <UIKit/UIKit.h>
+
+/**
+ * Convenience methods to help with resizing images retrieved from the
+ * ObjectiveFlickr library.
+ */
+@interface UIImage (OpenFlowExtras)
+
+- (UIImage *)rescaleImageToSize:(CGSize)size;
+- (UIImage *)cropImageToRect:(CGRect)cropRect;
+- (CGSize)calculateNewSizeForCroppingBox:(CGSize)croppingBox;
+- (UIImage *)cropCenterAndScaleImageToSize:(CGSize)cropSize;
+
+@end
80 build/iphone/Classes/AFOpenFlow/UIImageExtras.m
@@ -0,0 +1,80 @@
+/**
+ * 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.
+ */
+#import "UIImageExtras.h"
+
+
+@implementation UIImage (OpenFlowExtras)
+
+- (UIImage *)rescaleImageToSize:(CGSize)size {
+ CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height);
+ UIGraphicsBeginImageContext(rect.size);
+ [self drawInRect:rect]; // scales image to rect
+ UIImage *resImage = UIGraphicsGetImageFromCurrentImageContext();
+ UIGraphicsEndImageContext();
+ return resImage;
+}
+
+- (UIImage *)cropImageToRect:(CGRect)cropRect {
+ // Begin the drawing (again)
+ UIGraphicsBeginImageContext(cropRect.size);
+ CGContextRef ctx = UIGraphicsGetCurrentContext();
+
+ // Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
+ CGContextTranslateCTM(ctx, 0.0, cropRect.size.height);
+ CGContextScaleCTM(ctx, 1.0, -1.0);
+
+ // Draw view into context
+ CGRect drawRect = CGRectMake(-cropRect.origin.x, cropRect.origin.y - (self.size.height - cropRect.size.height) , self.size.width, self.size.height);
+ CGContextDrawImage(ctx, drawRect, self.CGImage);
+
+ // Create the new UIImage from the context
+ UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
+
+ // End the drawing
+ UIGraphicsEndImageContext();
+
+ return newImage;
+}
+
+- (CGSize)calculateNewSizeForCroppingBox:(CGSize)croppingBox {
+ // Make the shortest side be equivalent to the cropping box.
+ CGFloat newHeight, newWidth;
+ if (self.size.width < self.size.height) {