├── .gitignore ├── README.md ├── doc └── images │ ├── android-config-build-path-add-external-jars.png │ ├── android-config-build-path-jars.png │ ├── android-config-build-path-menu.png │ ├── android-create-new-test.png │ ├── android-new-project-info.png │ ├── android-new-project-name.png │ ├── android-new-project-target.png │ ├── android-run-tutorial-tests.png │ ├── android-test-manifest-file.png │ ├── ios-choose-target-gestures.png │ ├── ios-choose-target.png │ ├── ios-instruments-create-script.png │ ├── ios-instruments-iquery-statements.png │ ├── ios-launch-instruments.png │ ├── ios-run-instruments-test.png │ ├── ios-select-automation.png │ └── ios-set-instruments-option.png ├── iOS ├── lib │ ├── Json2.js │ ├── Queue.js │ ├── README │ ├── antlr-3.3-complete.jar │ ├── antlr3-all-min.js │ ├── common.js │ ├── error.js │ ├── iQuery.g │ ├── iQueryLexer.js │ ├── iQueryParser.js │ └── iquery.js ├── sampleTest.js └── targetApp │ ├── Gestures.app │ ├── BasicUIViewController.nib │ ├── Gestures │ ├── Info.plist │ ├── PkgInfo │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ └── MainStoryboard.storyboardc │ │ │ ├── 0bv-ry-Q6E-view-c1Q-Za-qVv.nib │ │ │ ├── 2-view-3.nib │ │ │ ├── GvY-xD-dzv-view-WzY-Wj-HP3.nib │ │ │ ├── Info.plist │ │ │ ├── UIViewController-0bv-ry-Q6E.nib │ │ │ ├── UIViewController-2.nib │ │ │ ├── UIViewController-GvY-xD-dzv.nib │ │ │ ├── UIViewController-Pqc-uC-ffe.nib │ │ │ ├── UIViewController-XAG-FR-4Vz.nib │ │ │ ├── UIViewController-p1h-kp-3v1.nib │ │ │ ├── UIViewController-q3b-SD-egP.nib │ │ │ ├── XAG-FR-4Vz-view-VoF-xA-8gy.nib │ │ │ ├── p1h-kp-3v1-view-y1j-Wn-sSo.nib │ │ │ ├── q3b-SD-egP-view-rHl-MJ-SPy.nib │ │ │ └── qPw-bi-HtR-view-or6-EK-ETA.nib │ └── flower.png │ └── Gestures │ ├── Gestures.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ ├── jray.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── mahmood1.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── jray.xcuserdatad │ │ └── xcschemes │ │ │ ├── Gestures.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── mahmood1.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ │ └── xcschemes │ │ ├── Gestures.xcscheme │ │ └── xcschememanagement.plist │ └── Gestures │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── BasicGestureViewController.h │ ├── BasicGestureViewController.m │ ├── BasicUIViewController.h │ ├── BasicUIViewController.m │ ├── BasicUIViewController.xib │ ├── Gestures-Info.plist │ ├── Gestures-Prefix.pch │ ├── Images │ └── flower.png │ ├── UYLAdvancedSettingsViewController.h │ ├── UYLAdvancedSettingsViewController.m │ ├── UYLGeneralSettingsTableViewController.h │ ├── UYLGeneralSettingsTableViewController.m │ ├── UYLRotatingTableViewController.h │ ├── UYLRotatingTableViewController.m │ ├── en.lproj │ ├── InfoPlist.strings │ └── MainStoryboard.storyboard │ └── main.m ├── iQuery.g └── java ├── Test ├── iQA.Runtime.Test │ ├── .classpath │ ├── .project │ ├── res │ │ ├── button.txt │ │ ├── imagebutton.txt │ │ ├── radio.txt │ │ └── testParserMethod.txt │ └── src │ │ └── cc │ │ └── iqa │ │ └── iquery │ │ └── test │ │ ├── LayoutTreeParserTest.java │ │ ├── iQueryIdeParserTest.java │ │ ├── iQueryInvalidSyntaxParserTest.java │ │ └── iQueryParserTest.java ├── iQA.Sample.multiplatformdemoprojecttest │ ├── .classpath │ ├── .classpath.orig │ ├── .project │ ├── AndroidManifest.xml │ ├── gen │ │ └── cc │ │ │ └── iqa │ │ │ └── studio │ │ │ └── demo │ │ │ └── test │ │ │ └── R.java │ ├── lint.xml │ ├── proguard.cfg │ ├── project.properties │ ├── res │ │ ├── drawable-hdpi │ │ │ └── ic_launcher.png │ │ ├── drawable-ldpi │ │ │ └── ic_launcher.png │ │ ├── drawable-mdpi │ │ │ └── ic_launcher.png │ │ ├── layout │ │ │ └── main.xml │ │ └── values │ │ │ └── strings.xml │ └── src │ │ └── cc │ │ └── iqa │ │ └── demo │ │ └── multiplatformdemoproject │ │ └── test │ │ └── iQueryAndroidTest.java └── multiplatformdemoproject │ ├── .classpath │ ├── .project │ ├── AndroidManifest.xml │ ├── gen │ └── cc │ │ └── iqa │ │ └── studio │ │ └── demo │ │ └── R.java │ ├── lint.xml │ ├── proguard.cfg │ ├── project.properties │ ├── res │ ├── drawable-hdpi │ │ └── ic_launcher.png │ ├── drawable-ldpi │ │ └── ic_launcher.png │ ├── drawable-mdpi │ │ └── ic_launcher.png │ ├── layout │ │ ├── bookdetails.xml │ │ ├── bookeditor.xml │ │ ├── list_item.xml │ │ └── main.xml │ ├── menu │ │ └── viewdetailsmenu.xml │ └── values │ │ └── strings.xml │ └── src │ └── cc │ └── iqa │ └── studio │ └── demo │ ├── BookDetails.java │ ├── BookEditor.java │ ├── EditFlags.java │ ├── MainActivity.java │ └── TheFuckingSimpleExpandableListAdapter.java ├── iquery-monkeyrunner-plugin ├── manifest.txt └── src │ └── com │ └── vowei │ └── android │ └── monkeyrunner │ ├── By.java │ ├── Plugin.java │ └── QueryableDevice.java ├── iquery ├── iquery-core │ ├── README │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── cc │ │ └── iqa │ │ └── iquery │ │ ├── ErrorMessageHelper.java │ │ ├── IProperty.java │ │ ├── IPseudoAttribute.java │ │ ├── IPseudoClass.java │ │ ├── ITreeNode.java │ │ ├── Pair.java │ │ ├── iQuery.g │ │ ├── iQuery.java │ │ ├── iQueryIdeParser.java │ │ ├── iQueryLexer.java │ │ ├── iQueryParseException.java │ │ └── iQueryParser.java ├── iquery-instrumentation │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── cc │ │ └── iqa │ │ └── iquery │ │ └── android │ │ ├── SoloProperty.java │ │ └── SoloTreeNode.java ├── iquery-monkey │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── cc │ │ │ └── iqa │ │ │ └── iquery │ │ │ └── monkey │ │ │ ├── LayoutTree.java │ │ │ ├── LayoutTreeNode.java │ │ │ └── LayoutTreeParser.java │ │ └── test │ │ ├── java │ │ └── cc │ │ │ └── iqa │ │ │ └── iquery │ │ │ ├── LayoutTreeParserTest.java │ │ │ ├── iQueryIdeParserTest.java │ │ │ ├── iQueryInvalidSyntaxParserTest.java │ │ │ └── iQueryParserTest.java │ │ └── resources │ │ ├── button.txt │ │ ├── imagebutton.txt │ │ ├── radio.txt │ │ ├── testParseNotAfterAttribute.txt │ │ └── testParserMethod.txt ├── iquery-mr │ ├── pom.xml │ ├── sample │ │ ├── run.sh │ │ ├── sample.py │ │ └── vsdebug.java │ └── src │ │ ├── assembly.xml │ │ └── main │ │ └── java │ │ ├── cc │ │ └── iqa │ │ │ └── iquery │ │ │ └── mr │ │ │ ├── By.java │ │ │ ├── ControlHierarchy.java │ │ │ ├── Plugin.java │ │ │ └── QueryableDevice.java │ │ └── manifest.txt └── pom.xml └── sample ├── .classpath ├── .project ├── AndroidManifest.xml ├── gen └── cc │ └── iqa │ └── studio │ └── demo │ └── test │ └── R.java ├── proguard.cfg ├── project.properties ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-ldpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── layout │ └── main.xml └── values │ └── strings.xml └── src └── cc └── iqa └── studio └── demo └── test └── DemoOnlyTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *~ 3 | 4 | *.tokens 5 | 6 | ############ 7 | # Jython # 8 | ############ 9 | 10 | *.pyc 11 | *.class 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | iQuery is a ui control query library, currently supports for iOS and Android UI automation are implemented. 2 | 3 | HOW TO BUILD 4 | ------------ 5 | 6 | You need set an environment varaible `ANDROID_HOME` in order to do a successful build. For e.g. `$ export ANDROID_HOME=~/android-sdK;mvn package`. 7 | 8 | iQuery for monkeyrunner is a plugin project, it requires several jar files in android sdk directory, and which are not available in maven repo. So I point the jar files to android sdk home directory. 9 | 10 | iOS usage 11 | --------- 12 | 13 | iQuery for iOS is based on instrument, object-c version is not available yet, however, since it is based on antlr, it can be extended to object-c version quite easily. 14 | 15 | To use iquery in your instrument test cases, follow below steps: 16 | 17 | 1. import [iquery.js](https://github.com/vowei/iQuery/blob/master/iOS/lib/iquery.js) in your test case. 18 | 19 | `#import "iquery.js";` 20 | 21 | 2. And then you can use iQuery in your code. 22 | 3. iquery.js contains a simplified unit test framework with it. If you want to use iQuery with your own test framework. you can remove the test framework's code in [common.js](https://github.com/vowei/iQuery/blob/master/iOS/lib/common.js). 23 | 24 | Below is a sample usage, for detailed usage, please read the test sources: https://github.com/vowei/iQuery/blob/master/iOS/sampleTest.js : 25 | 26 | var target = UIATarget.localTarget(); 27 | var root = target.frontMostApp().mainWindow(); 28 | var assert = new Assert(); 29 | var result = root.$("UIAWindow > UIASegmentedControl > UIAButton :eq(0) + UIAButton"); 30 | assert.Equals(1, result.length); 31 | 32 | 33 | Android usage 34 | ------------- 35 | 36 | iQuery for android supports instrument test cases, and query text from hierarchyviewer output. 37 | 38 | Below are steps required for use iQuery in instrument test cases: 39 | 40 | 1. Create an android unit test project, you may include [robotium] (https://code.google.com/p/robotium/) in the project. 41 | 2. Include [antlr-runtime-3.4.jar](https://github.com/vowei/iQuery/blob/master/java/lib/antlr-runtime-3.4.jar), [iQA.Runtime.jar](https://github.com/downloads/vowei/iQuery/iQA.Runtime.jar) and [iQA.Runtime.Instrument.jar](https://github.com/downloads/vowei/iQuery/iQA.Runtime.Instrument.jar) in your project's build path. 42 | 43 | Import antlr and iQuery packages in your code: 44 | 45 | import org.antlr.runtime.*; 46 | import cc.iqa.iquery.*; 47 | import cc.iqa.iquery.android.*; 48 | 49 | And use it: 50 | 51 | List result = iQuery.query(new SoloTreeNode( 52 | _solo.getCurrentViews().get(0)), 53 | "LinearLayout >> TextView [mText = 'Down Under']"); 54 | 55 | 3. If an invalid query is given, iQuery.query will throw a iQueryParserException object, you can get details errors by calling e.getErrors() - the errors message are Chinese. :( 56 | 57 | for detailed usage, please read the test sources: https://github.com/vowei/iQuery/blob/master/java/Test/iQA.Runtime.Test/src/cc/iqa/iquery/test/iQueryParserTest.java 58 | -------------------------------------------------------------------------------- /doc/images/android-config-build-path-add-external-jars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-config-build-path-add-external-jars.png -------------------------------------------------------------------------------- /doc/images/android-config-build-path-jars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-config-build-path-jars.png -------------------------------------------------------------------------------- /doc/images/android-config-build-path-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-config-build-path-menu.png -------------------------------------------------------------------------------- /doc/images/android-create-new-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-create-new-test.png -------------------------------------------------------------------------------- /doc/images/android-new-project-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-new-project-info.png -------------------------------------------------------------------------------- /doc/images/android-new-project-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-new-project-name.png -------------------------------------------------------------------------------- /doc/images/android-new-project-target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-new-project-target.png -------------------------------------------------------------------------------- /doc/images/android-run-tutorial-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-run-tutorial-tests.png -------------------------------------------------------------------------------- /doc/images/android-test-manifest-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/android-test-manifest-file.png -------------------------------------------------------------------------------- /doc/images/ios-choose-target-gestures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/ios-choose-target-gestures.png -------------------------------------------------------------------------------- /doc/images/ios-choose-target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/ios-choose-target.png -------------------------------------------------------------------------------- /doc/images/ios-instruments-create-script.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/ios-instruments-create-script.png -------------------------------------------------------------------------------- /doc/images/ios-instruments-iquery-statements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/ios-instruments-iquery-statements.png -------------------------------------------------------------------------------- /doc/images/ios-launch-instruments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/ios-launch-instruments.png -------------------------------------------------------------------------------- /doc/images/ios-run-instruments-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/ios-run-instruments-test.png -------------------------------------------------------------------------------- /doc/images/ios-select-automation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/ios-select-automation.png -------------------------------------------------------------------------------- /doc/images/ios-set-instruments-option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/doc/images/ios-set-instruments-option.png -------------------------------------------------------------------------------- /iOS/lib/Queue.js: -------------------------------------------------------------------------------- 1 | /* 2 | Queue.js 3 | A function to represent a queue 4 | Created by Stephen Morley - http://code.stephenmorley.org/ - and released under 5 | the terms of the CC0 1.0 Universal legal code: 6 | http://creativecommons.org/publicdomain/zero/1.0/legalcode 7 | */ 8 | 9 | /* Creates a new queue. A queue is a first-in-first-out (FIFO) data structure - 10 | * items are added to the end of the queue and removed from the front. 11 | */ 12 | 13 | function Queue() { 14 | // initialise the queue and offset 15 | var queue = []; 16 | var offset = 0; 17 | 18 | /* Returns the length of the queue. 19 | */ 20 | this.getLength = function () { 21 | // return the length of the queue 22 | return (queue.length - offset); 23 | } 24 | 25 | /* Returns true if the queue is empty, and false otherwise. 26 | */ 27 | this.isEmpty = function () { 28 | // return whether the queue is empty 29 | return (queue.length == 0); 30 | } 31 | 32 | /* Enqueues the specified item. The parameter is: 33 | * 34 | * item - the item to enqueue 35 | */ 36 | this.enqueue = function (item) { 37 | // enqueue the item 38 | queue.push(item); 39 | } 40 | 41 | /* Dequeues an item and returns it. If the queue is empty then undefined is 42 | * returned. 43 | */ 44 | this.dequeue = function () { 45 | // if the queue is empty, return undefined 46 | if (queue.length == 0) return undefined; 47 | 48 | // store the item at the front of the queue 49 | var item = queue[offset]; 50 | 51 | // increment the offset and remove the free space if necessary 52 | if (++offset * 2 >= queue.length) { 53 | queue = queue.slice(offset); 54 | offset = 0; 55 | } 56 | 57 | // return the dequeued item 58 | return item; 59 | } 60 | 61 | /* Returns the item at the front of the queue (without dequeuing it). If the 62 | * queue is empty then undefined is returned. 63 | */ 64 | this.peek = function () { 65 | // return the item at the front of the queue 66 | return (queue.length > 0 ? queue[offset] : undefined); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /iOS/lib/README: -------------------------------------------------------------------------------- 1 | 编译命令: 2 | java -cp antlr-3.3-complete.jar org.antlr.Tool iQuery.g 3 | 4 | 运行命令: -------------------------------------------------------------------------------- /iOS/lib/antlr-3.3-complete.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/lib/antlr-3.3-complete.jar -------------------------------------------------------------------------------- /iOS/lib/error.js: -------------------------------------------------------------------------------- 1 | function getTokenName(type) { 2 | switch ( type ) { 3 | case iQueryLexer.ELEMENT: 4 | return "属性名"; 5 | case iQueryLexer.DIGIT: 6 | return "数字"; 7 | case iQueryLexer.QUOTED_STRING: 8 | return "字符串"; 9 | default: 10 | return type; 11 | } 12 | }; 13 | 14 | function onNoViableAltException(e, tokenNames, tokens) { 15 | if (e.token != null) { // parser 16 | var t = e.token.getText(); 17 | // 最后一个Token永远都是EOF 18 | var idx = e.index + 1; 19 | var nextToken = null; 20 | var prevToken = null; 21 | 22 | debug("[onNoViableAltException] t: " + t); 23 | debug("[onNoViableAltException] idx: " + idx); 24 | debug("[onNoViableAltException] tokens.getTokens().length: " + tokens.getTokens().length); 25 | if ( idx < tokens.getTokens().length) { 26 | nextToken = tokens.getTokens()[idx]; 27 | 28 | // 29 | // TODO: 需要写文档告诉用户,在java版和javascript版的iquery解析时,发生错误时出现的错误消息有时是不一致的。 30 | // 31 | // 不知道为什么,javascript版的antlr跟java版的antlr在NoViableAltException 32 | // 方面,获取的行号和列号有不一样的地方 33 | // 下面这段代码就是在无效的伪类后面继续跟了一个元素,出现的异常里包含的信息 34 | // 跟最后一个元素是无效的伪类出现的异常里包含的信息不一致的情形的临时解决方案 35 | // 36 | prevToken = e.index > 0 ? tokens.getTokens()[e.index - 1] : null; 37 | // 下面这个判断是为了>>操作符后面没有跟过滤条件的临时解决方案 38 | // 我不知道为什么,解析这个“TextView :first >>”语法错误时, 39 | // e.token竟然是EOF! 40 | } else { 41 | // t = tokens.getTokens()[e.index - 1].getText(); 42 | // nextToken = tokens.getTokens()[tokens.getTokens().length - 1];\ 43 | nextToken = new org.antlr.runtime.CommonToken(org.antlr.runtime.Token.EOF, "EOF"); 44 | prevToken = e.index > 0 ? tokens.getTokens()[e.index - 1] : null; 45 | } 46 | 47 | debug("[onNoViableAltException] t: " + t); 48 | debug("[onNoViableAltException] nextToken: " + nextToken.getText()); 49 | debug("[onNoViableAltException] prevToken: " + (prevToken != null ? prevToken.getText() : "null")); 50 | debug("[onNoViableAltException] nextToken.getType(): " + nextToken.getType()); 51 | debug("[onNoViableAltException] EOF: " + org.antlr.runtime.Token.EOF); 52 | if (t == ":" || (prevToken != null && prevToken.getText() == ":") ) { 53 | if (tokens.getTokens().length == 1) { 54 | return "对于伪类指示符\"" + (t == null ? prevToken.getText() : t) + "\",冒号后需要跟具体的伪类名称!"; 55 | } else if (prevToken == null) { 56 | return "未知的伪类\"" + t + nextToken.getText() + "\"!"; 57 | } else if (prevToken != null) { 58 | return "未知的伪类\"" + prevToken.getText() + t + "\"!"; 59 | } 60 | } else if (t == ">" || t == ">>") { 61 | if (prevToken == null) { 62 | return t + "操作符不能放在查询的开始,如果是要从根节点开始查询,请确保查询的集合里只有根节点一个元素,并且使用类似\"* " + t + "\"或\":first " + t + "\"的方式指定查询语句!"; 63 | } else { 64 | if (nextToken.getType() != org.antlr.runtime.Token.EOF) { 65 | return "取子控件集合\"" + t + "\"操作符后面应该跟随有合法的过滤条件,无法识别条件\"" + nextToken.getText() + "\"!"; 66 | } else { 67 | return "取子控件集合\"" + t + "\"操作符后面应该跟随有合法的过滤条件!"; 68 | } 69 | } 70 | } else if ((prevToken != null && prevToken.getText() == ">") || 71 | (prevToken != null && prevToken.getText() == ">>") ) { 72 | if (nextToken.getType() != org.antlr.runtime.Token.EOF) { 73 | return "取子控件集合\"" + prevToken.getText() + "\"操作符后面应该跟随有合法的过滤条件,无法识别条件\"" + nextToken.getText() + "\"!"; 74 | } else { 75 | return "取子控件集合\"" + prevToken.getText() + "\"操作符后面应该跟随有合法的过滤条件!"; 76 | } 77 | } else if ( t == "[" ) { 78 | if ( nextToken.getType() != iQueryLexer.ELEMENT ) { 79 | return "属性查询条件里,'['后面跟随有英文字母和数字组成的控件属性名,但是找到的是\"" + getTokenName(nextToken.getType()) + "\"-\"" + nextToken.getText() + "\"!"; 80 | } else if ( idx < (tokens.getTokens().length - 1) ) { 81 | nextToken = tokens.getTokens()[idx + 1]; 82 | return "属性查询条件里,属性后面应该跟随有'='或者']',但是找到的是\"" + nextToken.getText() + "\"!"; 83 | } 84 | } else { 85 | return "未知语法错误,有可能是'>>'操作符后面没有过滤条件!"; 86 | } 87 | } else { 88 | return "查询语句中有无法识别的关键字\"" + e.c + "\"!"; 89 | } 90 | }; 91 | 92 | function onMismatchedTokenException(mte, tokenNames, recognizer) { 93 | debug("onMismatchedTokenException"); 94 | 95 | var tokenName = ""; 96 | if (mte.expecting == org.antlr.runtime.Token.EOF) { 97 | tokenName = "EOF"; 98 | } else if (tokenNames != null) { 99 | tokenName = tokenNames[mte.expecting]; 100 | } else { 101 | debug("[onMismatchedTokenException] - mte.expecting: " + mte.expecting); 102 | tokenName = mte.expecting; 103 | } 104 | 105 | if (mte.token != null) { 106 | return "没有关闭的语句,期望" + tokenName + ",当前碰到的是'" + recognizer.getTokenErrorDisplay(mte.token) + "'!"; 107 | } else if (tokenName != undefined) { 108 | return "没有关闭的语句,期望" + tokenName + "!"; 109 | } else { 110 | return "没有关闭的语句!"; 111 | } 112 | } 113 | 114 | function onMissingTokenException(E, D, recognizer) { 115 | var tokenName = ""; 116 | if (E.expecting == org.antlr.runtime.Token.EOF) { 117 | tokenName = "EOF" 118 | } else { 119 | tokenName = D[A.expecting] 120 | } 121 | 122 | return "在" + recognizer.getTokenErrorDisplay(E.token) + "处缺少期望的" + tokenName + "!"; 123 | }; 124 | 125 | function getErrorHeader(recognizer, e) { 126 | if (recognizer.getSourceName() != null && e.charPositionInLine >= 0) { 127 | return recognizer.getSourceName() + ":第" + (e.line > 0 ? e.line : 1) + "行,第" + (e.charPositionInLine + 1) + "列"; 128 | } else if (recognizer.getSourceName() != null && e.charPositionInLine < 0) { 129 | return recognizer.getSourceName() + ":第" + (e.line > 0 ? e.line : 1) + "行"; 130 | } else if (recognizer.getSourceName() == null && e.charPositionInLine >= 0) { 131 | return "第" + (e.line > 0 ? e.line : 1) + "行,第" + (e.charPositionInLine + 1) + "列"; 132 | } else { 133 | return "第" + (e.line > 0 ? e.line : 1) + "行"; 134 | } 135 | }; 136 | 137 | function getErrorsHelper(E, tokens, D, recognizer) { 138 | var F = (E && E.getMessage) ? E.getMessage() : null, A, C; 139 | var hdr = getErrorHeader(recognizer, E); 140 | if (E instanceof org.antlr.runtime.UnwantedTokenException) { 141 | var B = E; 142 | var C = ""; 143 | if (B.expecting == org.antlr.runtime.Token.EOF) { 144 | C = "EOF" 145 | } else { 146 | C = D[B.expecting] 147 | } 148 | F = "错误的输入: " + this.getTokenErrorDisplay(B.getUnexpectedToken()) + " 期望: " + C 149 | } else { 150 | if (E instanceof org.antlr.runtime.MissingTokenException) { 151 | F = hdr + ": " + onMissingTokenException(E, D, recognizer); 152 | } else { 153 | if (E instanceof org.antlr.runtime.MismatchedTokenException) { 154 | debug("called MismatchedTokenException"); 155 | F = hdr + ": " + onMismatchedTokenException(E, D, recognizer); 156 | } else { 157 | if (E instanceof org.antlr.runtime.NoViableAltException) { 158 | F = hdr + ": " + onNoViableAltException(E, D, tokens); 159 | } else { 160 | if (E instanceof org.antlr.runtime.EarlyExitException) { 161 | F = "required (...)+ loop did not match anything at input " + this.getTokenErrorDisplay(E.token) 162 | } else { 163 | if (E instanceof org.antlr.runtime.MismatchedSetException) { 164 | F = "mismatched input " + this.getTokenErrorDisplay(E.token) + " expecting set " + E.expecting 165 | } else { 166 | if (E instanceof org.antlr.runtime.MismatchedNotSetException) { 167 | F = "mismatched input " + this.getTokenErrorDisplay(E.token) + " expecting set " + E.expecting 168 | } else { 169 | if (E instanceof org.antlr.runtime.FailedPredicateException) { 170 | F = "rule " + E.ruleName + " failed predicate: {" + E.predicateText + "}?" 171 | } 172 | } 173 | } 174 | } 175 | } 176 | } 177 | } 178 | } 179 | return F 180 | } -------------------------------------------------------------------------------- /iOS/lib/iquery.js: -------------------------------------------------------------------------------- 1 | #import "common.js"; 2 | #import "antlr3-all-min.js"; 3 | #import "iQueryLexer.js"; 4 | #import "iQueryParser.js"; 5 | #import "error.js"; 6 | 7 | function iQuery(selector, registerPseudoes) { 8 | debug("$('" + selector + "')"); 9 | var cstream = new org.antlr.runtime.ANTLRStringStream(selector); 10 | var errors = []; 11 | this.lexer = new iQueryLexer(cstream); 12 | this.lexer._errors = errors; 13 | var tstream = new org.antlr.runtime.CommonTokenStream(this.lexer); 14 | this.parser = new iQueryParser(tstream); 15 | this.parser._errors = errors; 16 | 17 | if ( registerPseudoes != undefined && registerPseudoes ) { 18 | registerPseudoAttrHandler(this.parser); 19 | registerPseudoClassHandler(this.parser); 20 | } 21 | }; 22 | 23 | function registerPseudoAttrHandler(parser) { 24 | parser.registerPseudoAttr("height", function(uiaobj) { 25 | if ( uiaobj != undefined && uiaobj.rect != undefined ) { 26 | var rect = uiaobj.rect(); 27 | debug("rect.height: " + rect.size.height); 28 | return rect.size.height; 29 | } 30 | }); 31 | parser.registerPseudoAttr("width", function(uiaobj) { 32 | if ( uiaobj != undefined && uiaobj.rect != undefined ) { 33 | var rect = uiaobj.rect(); 34 | return rect.size.width; 35 | } 36 | }); 37 | parser.registerPseudoAttr("top", function(uiaobj) { 38 | if ( uiaobj != undefined && uiaobj.rect != undefined ) { 39 | var rect = uiaobj.rect(); 40 | return rect.origin.y; 41 | } 42 | }); 43 | parser.registerPseudoAttr("left", function(uiaobj) { 44 | if ( uiaobj != undefined && uiaobj.rect != undefined ) { 45 | var rect = uiaobj.rect(); 46 | return rect.origin.x; 47 | } 48 | }); 49 | parser.registerPseudoAttr("bottom", function(uiaobj) { 50 | if ( uiaobj != undefined && uiaobj.rect != undefined ) { 51 | var rect = uiaobj.rect(); 52 | return rect.origin.y + rect.size.height; 53 | } 54 | }); 55 | parser.registerPseudoAttr("right", function(uiaobj) { 56 | if ( uiaobj != undefined && uiaobj.rect != undefined ) { 57 | var rect = uiaobj.rect(); 58 | return rect.origin.x + rect.size.width; 59 | } 60 | }); 61 | } 62 | 63 | function registerPseudoClassHandler(parser) { 64 | parser.registerPseudoClass("text", function(uiaobj) { 65 | if ( uiaobj != undefined ) { 66 | return isMatch(uiaobj, new Array("UIATextField", "UIATextView", "UIASecureTextField")); 67 | } 68 | }); 69 | parser.registerPseudoClass("radio", function(uiaobj) { 70 | if ( uiaobj != undefined ) { 71 | return isMatch(uiaobj, new Array("UIASwitch")); 72 | } 73 | }); 74 | parser.registerPseudoClass("checkbox", function(uiaobj) { 75 | if ( uiaobj != undefined ) { 76 | return isMatch(uiaobj, new Array("UIASwitch")); 77 | } 78 | }); 79 | parser.registerPseudoClass("button", function(uiaobj) { 80 | if ( uiaobj != undefined ) { 81 | return isMatch(uiaobj, new Array("UIAButton")); 82 | } 83 | }); 84 | parser.registerPseudoClass("image", function(uiaobj) { 85 | if ( uiaobj != undefined ) { 86 | return isMatch(uiaobj, new Array("UIAImage")); 87 | } 88 | }); 89 | parser.registerPseudoClass("label", function(uiaobj) { 90 | if ( uiaobj != undefined ) { 91 | return isMatch(uiaobj, new Array("UIAStaticText", "UIAStatusBar", "UIALink")); 92 | } 93 | }); 94 | } 95 | 96 | function _QueryFn(selector, context, template) { 97 | var iq = new iQuery(selector, template == undefined); 98 | 99 | if ( template != undefined && template != null ) { 100 | iq.parser.setTemplate(template.parser); 101 | } 102 | 103 | context = context ? [context] : [UIATarget.localTarget().frontMostApp().mainWindow()]; 104 | var result = iq.parser.prog(context); 105 | 106 | var errors = iq.parser.errors(); 107 | if (errors != null && errors.length > 0) { 108 | throw errors; 109 | } 110 | 111 | return result; 112 | }; 113 | 114 | $ = _QueryFn; 115 | UIAElement.prototype.$ = function(selector, template) { 116 | return _QueryFn(selector, this, template); 117 | } -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/BasicUIViewController.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/BasicUIViewController.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/Gestures: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/Gestures -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/Info.plist -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/0bv-ry-Q6E-view-c1Q-Za-qVv.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/0bv-ry-Q6E-view-c1Q-Za-qVv.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/2-view-3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/2-view-3.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/GvY-xD-dzv-view-WzY-Wj-HP3.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/GvY-xD-dzv-view-WzY-Wj-HP3.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/Info.plist -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-0bv-ry-Q6E.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-0bv-ry-Q6E.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-2.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-2.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-GvY-xD-dzv.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-GvY-xD-dzv.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-Pqc-uC-ffe.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-Pqc-uC-ffe.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-XAG-FR-4Vz.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-XAG-FR-4Vz.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-p1h-kp-3v1.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-p1h-kp-3v1.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-q3b-SD-egP.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/UIViewController-q3b-SD-egP.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/XAG-FR-4Vz-view-VoF-xA-8gy.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/XAG-FR-4Vz-view-VoF-xA-8gy.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/p1h-kp-3v1-view-y1j-Wn-sSo.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/p1h-kp-3v1-view-y1j-Wn-sSo.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/q3b-SD-egP-view-rHl-MJ-SPy.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/q3b-SD-egP-view-rHl-MJ-SPy.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/qPw-bi-HtR-view-or6-EK-ETA.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/en.lproj/MainStoryboard.storyboardc/qPw-bi-HtR-view-or6-EK-ETA.nib -------------------------------------------------------------------------------- /iOS/targetApp/Gestures.app/flower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures.app/flower.png -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures.xcodeproj/project.xcworkspace/xcuserdata/jray.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures/Gestures.xcodeproj/project.xcworkspace/xcuserdata/jray.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures.xcodeproj/project.xcworkspace/xcuserdata/mahmood1.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures/Gestures.xcodeproj/project.xcworkspace/xcuserdata/mahmood1.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures.xcodeproj/xcuserdata/jray.xcuserdatad/xcschemes/Gestures.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures.xcodeproj/xcuserdata/jray.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Gestures.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2712D9681417EAAF000B820A 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures.xcodeproj/xcuserdata/mahmood1.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures.xcodeproj/xcuserdata/mahmood1.xcuserdatad/xcschemes/Gestures.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures.xcodeproj/xcuserdata/mahmood1.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Gestures.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2712D9681417EAAF000B820A 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Gestures 4 | // 5 | // Created by John Ray on 9/7/11. 6 | // Copyright (c) 2011 John E. Ray. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define kOriginWidth 123.0 12 | #define kOriginHeight 112.0 13 | #define kOriginX 98.0 14 | #define kOriginY 328.0 15 | 16 | @interface AppDelegate : UIResponder 17 | 18 | @property (strong, nonatomic) UIWindow *window; 19 | 20 | extern NSString *kUYLSettingsSpeedKey; 21 | extern NSString *kUYLSettingsVolumeKey; 22 | extern NSString *kUYLSettingsWarpDriveKey; 23 | extern NSString *kUYLSettingsShieldsKey; 24 | extern NSString *kUYLSettingsCreditsKey; 25 | extern NSString *kUYLSettingsRetriesKey; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Gestures 4 | // 5 | // Created by John Ray on 9/7/11. 6 | // Copyright (c) 2011 John E. Ray. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | @synthesize window = _window; 14 | 15 | NSString *kUYLSettingsSpeedKey = @"speed"; 16 | NSString *kUYLSettingsVolumeKey = @"volume"; 17 | NSString *kUYLSettingsWarpDriveKey = @"warp"; 18 | NSString *kUYLSettingsShieldsKey = @"shields"; 19 | NSString *kUYLSettingsCreditsKey = @"credits"; 20 | NSString *kUYLSettingsRetriesKey = @"retries"; 21 | 22 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 23 | { 24 | NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys: 25 | [NSNumber numberWithInteger:1], kUYLSettingsSpeedKey, 26 | [NSNumber numberWithInteger:1], kUYLSettingsVolumeKey, 27 | [NSNumber numberWithBool:YES], kUYLSettingsWarpDriveKey, 28 | [NSNumber numberWithBool:YES], kUYLSettingsShieldsKey, 29 | [NSNumber numberWithDouble:3.0], kUYLSettingsCreditsKey, 30 | [NSNumber numberWithDouble:1.0], kUYLSettingsRetriesKey, 31 | nil]; 32 | [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults]; 33 | 34 | return YES; 35 | } 36 | 37 | - (void)applicationWillResignActive:(UIApplication *)application 38 | { 39 | /* 40 | Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 41 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 42 | */ 43 | } 44 | 45 | - (void)applicationDidEnterBackground:(UIApplication *)application 46 | { 47 | /* 48 | Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 49 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 50 | */ 51 | } 52 | 53 | - (void)applicationWillEnterForeground:(UIApplication *)application 54 | { 55 | /* 56 | Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 57 | */ 58 | } 59 | 60 | - (void)applicationDidBecomeActive:(UIApplication *)application 61 | { 62 | /* 63 | Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 64 | */ 65 | } 66 | 67 | - (void)applicationWillTerminate:(UIApplication *)application 68 | { 69 | /* 70 | Called when the application is about to terminate. 71 | Save data if appropriate. 72 | See also applicationDidEnterBackground:. 73 | */ 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/BasicGestureViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Gestures 4 | // 5 | // Created by John Ray on 9/7/11. 6 | // Copyright (c) 2011 John E. Ray. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BasicGestureViewController : UIViewController 12 | @property (strong, nonatomic) IBOutlet UILabel *outputLabel; 13 | @property (strong, nonatomic) IBOutlet UIImageView *imageView; 14 | 15 | - (IBAction)foundTap:(id)sender; 16 | - (IBAction)foundSwipe:(id)sender; 17 | - (IBAction)foundPinch:(id)sender; 18 | - (IBAction)foundRotation:(id)sender; 19 | 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/BasicGestureViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Gestures 4 | // 5 | // Created by John Ray on 9/7/11. 6 | // Copyright (c) 2011 John E. Ray. All rights reserved. 7 | // 8 | 9 | #import "BasicGestureViewController.h" 10 | 11 | #define kOriginWidth 125.0 12 | #define kOriginHeight 115.0 13 | #define kOriginX 100.0 14 | #define kOriginY 330.0 15 | 16 | @implementation BasicGestureViewController 17 | @synthesize outputLabel; 18 | @synthesize imageView; 19 | 20 | 21 | - (void)didReceiveMemoryWarning 22 | { 23 | [super didReceiveMemoryWarning]; 24 | // Release any cached data, images, etc that aren't in use. 25 | } 26 | 27 | #pragma mark - View lifecycle 28 | 29 | - (void)viewDidLoad 30 | { 31 | [super viewDidLoad]; 32 | // Do any additional setup after loading the view, typically from a nib. 33 | } 34 | 35 | - (void)viewDidUnload 36 | { 37 | [self setOutputLabel:nil]; 38 | [self setImageView:nil]; 39 | [super viewDidUnload]; 40 | // Release any retained subviews of the main view. 41 | // e.g. self.myOutlet = nil; 42 | } 43 | 44 | - (void)viewWillAppear:(BOOL)animated 45 | { 46 | [super viewWillAppear:animated]; 47 | } 48 | 49 | - (void)viewDidAppear:(BOOL)animated 50 | { 51 | [self becomeFirstResponder]; 52 | [super viewDidAppear:animated]; 53 | } 54 | 55 | - (void)viewWillDisappear:(BOOL)animated 56 | { 57 | [super viewWillDisappear:animated]; 58 | } 59 | 60 | - (void)viewDidDisappear:(BOOL)animated 61 | { 62 | [super viewDidDisappear:animated]; 63 | } 64 | 65 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 66 | { 67 | // Return YES for supported orientations 68 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 69 | } 70 | 71 | - (IBAction)foundTap:(id)sender { 72 | self.outputLabel.text=@"Tapped"; 73 | } 74 | 75 | - (IBAction)foundSwipe:(id)sender { 76 | self.outputLabel.text=@"Swiped"; 77 | } 78 | 79 | - (IBAction)foundPinch:(id)sender { 80 | UIPinchGestureRecognizer *recognizer; 81 | NSString *feedback; 82 | double scale; 83 | 84 | recognizer=(UIPinchGestureRecognizer *)sender; 85 | scale=recognizer.scale; 86 | self.imageView.transform = CGAffineTransformMakeRotation(0.0); 87 | feedback=[[NSString alloc] 88 | initWithFormat:@"Pinched, Scale:%1.2f, Velocity:%1.2f", 89 | recognizer.scale,recognizer.velocity]; 90 | self.outputLabel.text=feedback; 91 | self.imageView.frame=CGRectMake(kOriginX, 92 | kOriginY, 93 | kOriginWidth*scale, 94 | kOriginHeight*scale); 95 | } 96 | 97 | - (IBAction)foundRotation:(id)sender { 98 | UIRotationGestureRecognizer *recognizer; 99 | NSString *feedback; 100 | double rotation; 101 | 102 | recognizer=(UIRotationGestureRecognizer *)sender; 103 | rotation=recognizer.rotation; 104 | feedback=[[NSString alloc] 105 | initWithFormat:@"Rotated, Radians:%1.2f, Velocity:%1.2f", 106 | recognizer.rotation,recognizer.velocity]; 107 | self.outputLabel.text=feedback; 108 | self.imageView.transform = CGAffineTransformMakeRotation(rotation); 109 | } 110 | 111 | - (BOOL)canBecomeFirstResponder{ 112 | return YES; 113 | } 114 | 115 | - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { 116 | if (motion==UIEventSubtypeMotionShake) { 117 | self.outputLabel.text=@"Shaking things up!"; 118 | self.imageView.transform = CGAffineTransformMakeRotation(0.0); 119 | self.imageView.frame=CGRectMake(kOriginX, 120 | kOriginY, 121 | kOriginWidth, 122 | kOriginHeight); 123 | } 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/BasicUIViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BasicUIViewController.h 3 | // Gestures 4 | // 5 | // Created by shiyimin on 6/21/12. 6 | // Copyright (c) 2012 John E. Ray. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BasicUIViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/BasicUIViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BasicUIViewController.m 3 | // Gestures 4 | // 5 | // Created by shiyimin on 6/21/12. 6 | // Copyright (c) 2012 John E. Ray. All rights reserved. 7 | // 8 | 9 | #import "BasicUIViewController.h" 10 | 11 | @implementation BasicUIViewController 12 | 13 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 14 | { 15 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 16 | if (self) { 17 | // Custom initialization 18 | } 19 | return self; 20 | } 21 | 22 | - (void)didReceiveMemoryWarning 23 | { 24 | // Releases the view if it doesn't have a superview. 25 | [super didReceiveMemoryWarning]; 26 | 27 | // Release any cached data, images, etc that aren't in use. 28 | } 29 | 30 | #pragma mark - View lifecycle 31 | 32 | - (void)viewDidLoad 33 | { 34 | [super viewDidLoad]; 35 | // Do any additional setup after loading the view from its nib. 36 | } 37 | 38 | - (void)viewDidUnload 39 | { 40 | [super viewDidUnload]; 41 | // Release any retained subviews of the main view. 42 | // e.g. self.myOutlet = nil; 43 | } 44 | 45 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 46 | { 47 | // Return YES for supported orientations 48 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/BasicUIViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 11C25 6 | 1919 7 | 1138.11 8 | 566.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 916 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | 17 | 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | PluginDependencyRecalculationVersion 22 | 23 | 24 | 25 | 26 | IBFilesOwner 27 | IBCocoaTouchFramework 28 | 29 | 30 | IBFirstResponder 31 | IBCocoaTouchFramework 32 | 33 | 34 | 35 | 274 36 | {{0, 20}, {320, 460}} 37 | 38 | 39 | 40 | 3 41 | MQA 42 | 43 | 2 44 | 45 | 46 | 47 | IBCocoaTouchFramework 48 | 49 | 50 | 51 | 52 | 53 | 54 | view 55 | 56 | 57 | 58 | 3 59 | 60 | 61 | 62 | 63 | 64 | 0 65 | 66 | 67 | 68 | 69 | 70 | 1 71 | 72 | 73 | 74 | 75 | -1 76 | 77 | 78 | File's Owner 79 | 80 | 81 | -2 82 | 83 | 84 | 85 | 86 | 87 | 88 | BasicUIViewController 89 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 90 | UIResponder 91 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 92 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 93 | 94 | 95 | 96 | 97 | 98 | 3 99 | 100 | 101 | 102 | 103 | BasicUIViewController 104 | UIViewController 105 | 106 | IBProjectSource 107 | ./Classes/BasicUIViewController.h 108 | 109 | 110 | 111 | 112 | 0 113 | IBCocoaTouchFramework 114 | YES 115 | 3 116 | 916 117 | 118 | 119 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/Gestures-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | com.teachyourselfios.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | UIMainStoryboardFile 30 | MainStoryboard 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/Gestures-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Gestures' target in the 'Gestures' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/Images/flower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/iOS/targetApp/Gestures/Gestures/Images/flower.png -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/UYLAdvancedSettingsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // UYLAdvancedSettingsViewController.h 3 | // StaticTable 4 | // 5 | // Created by Keith Harrison http://useyourloaf.com 6 | // Copyright (c) 2012 Keith Harrison. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // 14 | // Redistributions in binary form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // Neither the name of Keith Harrison nor the names of its contributors 19 | // may be used to endorse or promote products derived from this software 20 | // without specific prior written permission. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY 23 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 26 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | 34 | #import 35 | 36 | @interface UYLAdvancedSettingsViewController : UITableViewController 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/UYLAdvancedSettingsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // UYLAdvancedSettingsViewController.m 3 | // StaticTable 4 | // 5 | // Created by Keith Harrison http://useyourloaf.com 6 | // Copyright (c) 2012 Keith Harrison. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // 14 | // Redistributions in binary form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // Neither the name of Keith Harrison nor the names of its contributors 19 | // may be used to endorse or promote products derived from this software 20 | // without specific prior written permission. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY 23 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 26 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | 34 | #import "UYLAdvancedSettingsViewController.h" 35 | #import "AppDelegate.h" 36 | 37 | @interface UYLAdvancedSettingsViewController () 38 | 39 | - (IBAction)switchToggled:(UISwitch *)sender; 40 | - (IBAction)stepperChanged:(UIStepper *)sender; 41 | 42 | @property (nonatomic, weak) IBOutlet UISwitch *warpSwitch; 43 | @property (nonatomic, weak) IBOutlet UISwitch *shieldsSwitch; 44 | @property (nonatomic, weak) IBOutlet UILabel *creditsLabel; 45 | @property (nonatomic, weak) IBOutlet UILabel *retriesLabel; 46 | @property (nonatomic, weak) IBOutlet UIStepper *creditsStepper; 47 | @property (nonatomic, weak) IBOutlet UIStepper *retriesStepper; 48 | 49 | @end 50 | 51 | @implementation UYLAdvancedSettingsViewController 52 | 53 | @synthesize warpSwitch=_warpSwitch; 54 | @synthesize shieldsSwitch=_shieldsSwitch; 55 | @synthesize creditsLabel=_creditsLabel; 56 | @synthesize retriesLabel=_retriesLabel; 57 | @synthesize creditsStepper=_creditsStepper; 58 | @synthesize retriesStepper=_retriesStepper; 59 | 60 | #define TAG_WARPSWITCH 10 61 | #define TAG_SHIELDSSWITCH 20 62 | #define TAG_CREDITSSTEPPER 30 63 | #define TAG_RETRIESSTEPPER 40 64 | 65 | #pragma mark - 66 | #pragma mark === UIViewController === 67 | #pragma mark - 68 | 69 | - (void)viewDidLoad 70 | { 71 | [super viewDidLoad]; 72 | 73 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 74 | 75 | self.warpSwitch.on = [defaults boolForKey:kUYLSettingsWarpDriveKey]; 76 | self.shieldsSwitch.on = [defaults boolForKey:kUYLSettingsShieldsKey]; 77 | 78 | self.creditsStepper.value = [defaults doubleForKey:kUYLSettingsCreditsKey]; 79 | self.creditsLabel.text = [NSString stringWithFormat:@"%1.0f", self.creditsStepper.value]; 80 | 81 | self.retriesStepper.value = [defaults doubleForKey:kUYLSettingsRetriesKey]; 82 | self.retriesLabel.text = [NSString stringWithFormat:@"%1.0f", self.retriesStepper.value]; 83 | } 84 | 85 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 86 | { 87 | return YES; 88 | } 89 | 90 | #pragma mark - 91 | #pragma mark === Actions === 92 | #pragma mark - 93 | 94 | - (IBAction)switchToggled:(UISwitch *)sender 95 | { 96 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 97 | 98 | switch (sender.tag) 99 | { 100 | case TAG_WARPSWITCH: 101 | [defaults setBool:sender.on forKey:kUYLSettingsWarpDriveKey]; 102 | break; 103 | 104 | case TAG_SHIELDSSWITCH: 105 | [defaults setBool:sender.on forKey:kUYLSettingsShieldsKey]; 106 | break; 107 | } 108 | } 109 | 110 | - (IBAction)stepperChanged:(UIStepper *)sender 111 | { 112 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 113 | 114 | switch (sender.tag) 115 | { 116 | case TAG_CREDITSSTEPPER: 117 | [defaults setDouble:sender.value forKey:kUYLSettingsCreditsKey]; 118 | self.creditsLabel.text = [NSString stringWithFormat:@"%1.0f", sender.value]; 119 | break; 120 | 121 | case TAG_RETRIESSTEPPER: 122 | [defaults setDouble:sender.value forKey:kUYLSettingsRetriesKey]; 123 | self.retriesLabel.text = [NSString stringWithFormat:@"%1.0f", sender.value]; 124 | break; 125 | } 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/UYLGeneralSettingsTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // UYLGeneralSettingsTableViewController.h 3 | // StaticTable 4 | // 5 | // Created by Keith Harrison http://useyourloaf.com 6 | // Copyright (c) 2012 Keith Harrison. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // 14 | // Redistributions in binary form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // Neither the name of Keith Harrison nor the names of its contributors 19 | // may be used to endorse or promote products derived from this software 20 | // without specific prior written permission. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY 23 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 26 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | 34 | #import 35 | 36 | @interface UYLGeneralSettingsTableViewController : UITableViewController 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/UYLGeneralSettingsTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // UYLGeneralSettingsTableViewController.m 3 | // StaticTable 4 | // 5 | // Created by Keith Harrison http://useyourloaf.com 6 | // Copyright (c) 2012 Keith Harrison. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // 14 | // Redistributions in binary form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // Neither the name of Keith Harrison nor the names of its contributors 19 | // may be used to endorse or promote products derived from this software 20 | // without specific prior written permission. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY 23 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 26 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | 34 | #import "UYLGeneralSettingsTableViewController.h" 35 | #import "AppDelegate.h" 36 | 37 | @interface UYLGeneralSettingsTableViewController () 38 | 39 | @property (nonatomic) NSUInteger speed; 40 | @property (nonatomic) NSUInteger volume; 41 | 42 | @end 43 | 44 | @implementation UYLGeneralSettingsTableViewController 45 | 46 | @synthesize speed=_speed; 47 | @synthesize volume=_volume; 48 | 49 | #define SECTION_SPEED 0 50 | #define SECTION_VOLUME 1 51 | 52 | #pragma mark - 53 | #pragma mark === UIViewController === 54 | #pragma mark - 55 | 56 | - (void)viewDidLoad 57 | { 58 | [super viewDidLoad]; 59 | 60 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 61 | self.speed = [defaults integerForKey:kUYLSettingsSpeedKey]; 62 | self.volume = [defaults integerForKey:kUYLSettingsVolumeKey]; 63 | } 64 | 65 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 66 | { 67 | return YES; 68 | } 69 | 70 | #pragma mark - 71 | #pragma mark === UITableViewDataSource === 72 | #pragma mark - 73 | 74 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 75 | { 76 | UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 77 | cell.accessoryType = UITableViewCellAccessoryNone; 78 | 79 | NSUInteger section = [indexPath section]; 80 | NSUInteger row = [indexPath row]; 81 | 82 | switch (section) 83 | { 84 | case SECTION_SPEED: 85 | if (row == self.speed) 86 | { 87 | cell.accessoryType = UITableViewCellAccessoryCheckmark; 88 | } 89 | break; 90 | 91 | case SECTION_VOLUME: 92 | if (row == self.volume) 93 | { 94 | cell.accessoryType = UITableViewCellAccessoryCheckmark; 95 | } 96 | break; 97 | } 98 | return cell; 99 | } 100 | 101 | #pragma mark - 102 | #pragma mark === UITableViewDelegate === 103 | #pragma mark - 104 | 105 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 106 | { 107 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 108 | NSUInteger section = [indexPath section]; 109 | NSUInteger row = [indexPath row]; 110 | 111 | switch (section) 112 | { 113 | case SECTION_SPEED: 114 | self.speed = row; 115 | [defaults setInteger:row forKey:kUYLSettingsSpeedKey]; 116 | break; 117 | 118 | case SECTION_VOLUME: 119 | self.volume = row; 120 | [defaults setInteger:row forKey:kUYLSettingsVolumeKey]; 121 | break; 122 | } 123 | 124 | [self.tableView reloadData]; 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/UYLRotatingTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // UYLRotatingTableViewController.h 3 | // StaticTable 4 | // 5 | // Created by Keith Harrison http://useyourloaf.com 6 | // Copyright (c) 2012 Keith Harrison. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // 14 | // Redistributions in binary form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // Neither the name of Keith Harrison nor the names of its contributors 19 | // may be used to endorse or promote products derived from this software 20 | // without specific prior written permission. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY 23 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 26 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | #import 34 | 35 | @interface UYLRotatingTableViewController : UITableViewController 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/UYLRotatingTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // UYLRotatingTableViewController.m 3 | // StaticTable 4 | // 5 | // Created by Keith Harrison http://useyourloaf.com 6 | // Copyright (c) 2012 Keith Harrison. All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // 11 | // Redistributions of source code must retain the above copyright 12 | // notice, this list of conditions and the following disclaimer. 13 | // 14 | // Redistributions in binary form must reproduce the above copyright 15 | // notice, this list of conditions and the following disclaimer in the 16 | // documentation and/or other materials provided with the distribution. 17 | // 18 | // Neither the name of Keith Harrison nor the names of its contributors 19 | // may be used to endorse or promote products derived from this software 20 | // without specific prior written permission. 21 | // 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY 23 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 26 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | #import "UYLRotatingTableViewController.h" 34 | 35 | @interface UYLRotatingTableViewController () 36 | 37 | @end 38 | 39 | @implementation UYLRotatingTableViewController 40 | 41 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 42 | { 43 | return YES; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /iOS/targetApp/Gestures/Gestures/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Gestures 4 | // 5 | // Created by John Ray on 9/7/11. 6 | // Copyright (c) 2011 John E. Ray. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /iQuery.g: -------------------------------------------------------------------------------- 1 | grammar iQuery; 2 | 3 | query 4 | : selectors NEWLINE* EOF 5 | | NEWLINE* EOF 6 | ; 7 | 8 | selectors 9 | : multi_selectors multi_selectors* 10 | ; 11 | 12 | multi_selectors 13 | : selector 14 | | '>' selector 15 | | DESCENDANT INTEGER selector 16 | | DESCENDANT selector 17 | ; 18 | 19 | selector 20 | : selector_expression 21 | ( 22 | ('+' selector_expression) 23 | | 24 | ('~' selector_expression) 25 | )? 26 | | multi_attributes 27 | ; 28 | 29 | num_comp_op 30 | : '>' 31 | | '<' 32 | | '>=' 33 | | '<=' 34 | | '=' 35 | ; 36 | 37 | multi_attributes 38 | : '[' ELEMENT op QUOTED_STRING ']' 39 | | '[' ':' ELEMENT op QUOTED_STRING ']' 40 | | '[' ELEMENT num_comp_op (INTEGER | FLOAT | PERCENTAGE) ']' 41 | | '[' ':' ELEMENT num_comp_op (INTEGER | FLOAT | PERCENTAGE) ']' 42 | | '[' ELEMENT ']' 43 | ; 44 | 45 | op 46 | : '=' 47 | | '!=' 48 | | '$=' 49 | | '^=' 50 | | '*=' 51 | ; 52 | 53 | indexop 54 | : EQ 55 | | GT 56 | | LT 57 | | NTH_CHILD 58 | ; 59 | 60 | selector_expression 61 | : atom 62 | | ':' indexop '(' INTEGER ')' 63 | | ':' NOT '(' selectors ')' 64 | | ':' HAS '(' selectors ')' 65 | | ':' CONTAINS '(' QUOTED_STRING ')' 66 | | ':' LAST_CHILD 67 | | ':' FIRST_CHILD 68 | | ':' FIRST 69 | | ':' LAST 70 | | ':' EMPTY 71 | | ':' PARENT 72 | | ':' ELEMENT 73 | { 74 | $survival = filterPseudo($candidates, $ELEMENT.text); 75 | } 76 | | '#' ELEMENT 77 | ; 78 | 79 | atom 80 | : ASTERISK 81 | | ELEMENT 82 | ; 83 | 84 | DESCENDANT: '>>'; 85 | EQ: 'eq'; 86 | GT: 'gt'; 87 | LT: 'lt'; 88 | NOT: 'not'; 89 | CONTAINS: 'contains'; 90 | EMPTY: 'empty'; 91 | HAS: 'has'; 92 | PREV: 'prev'; 93 | NEXT: 'next'; 94 | SIBLINGS: 'siblings'; 95 | NTH_CHILD: 'nth-child'; 96 | PARENT: 'parent'; 97 | LAST_CHILD: 'last-child'; 98 | FIRST_CHILD: 'first-child'; 99 | FIRST: 'first'; 100 | LAST: 'last'; 101 | INTEGER: DIGIT+; 102 | PERCENTAGE: ('+' | '-')? DIGIT+ ('.' DIGIT+)? '%'; 103 | FLOAT: ('+' | '-')? DIGIT+ ('.' DIGIT+)?; 104 | fragment DIGIT: ('0' .. '9'); 105 | ELEMENT: ('a'..'z'|'A'..'Z'|'_')('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'.')*; 106 | ASTERISK: '*'; 107 | QUOTED_STRING: '\'' .+ '\''; 108 | NEWLINE: '\r'? '\n'; 109 | WS: (' ' | '\t') { skip(); }; 110 | -------------------------------------------------------------------------------- /java/Test/iQA.Runtime.Test/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /java/Test/iQA.Runtime.Test/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | iQA.Runtime.Test 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /java/Test/iQA.Runtime.Test/src/cc/iqa/iquery/test/LayoutTreeParserTest.java: -------------------------------------------------------------------------------- 1 | package cc.iqa.iquery.test; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | 9 | import cc.iqa.iquery.monkey.*; 10 | 11 | public class LayoutTreeParserTest { 12 | @Test public void testParserMethod() throws Exception { 13 | BufferedReader in = new BufferedReader(new FileReader("/media/work/workspace/iqa/java/iQA.Runtime.Test/res/testParserMethod.txt")); 14 | List lines = new ArrayList(); 15 | String line = null; 16 | 17 | while ( (line = in.readLine()) != null ) { 18 | lines.add(line); 19 | } 20 | 21 | String[] strs = new String[lines.size()]; 22 | 23 | // 因为解析代码是从google android里拷贝出来的,因为在测试方面就偷懒了 24 | // 加回归测试用例吧。 25 | LayoutTree tree = LayoutTreeParser.parse(lines.toArray(strs)); 26 | Assert.assertNotNull(tree); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /java/Test/iQA.Runtime.Test/src/cc/iqa/iquery/test/iQueryIdeParserTest.java: -------------------------------------------------------------------------------- 1 | package cc.iqa.iquery.test; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.FileReader; 5 | import java.io.IOException; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | import junit.framework.Assert; 10 | 11 | import org.antlr.runtime.RecognitionException; 12 | import org.junit.Test; 13 | 14 | import cc.iqa.iquery.ITreeNode; 15 | import cc.iqa.iquery.iQuery; 16 | import cc.iqa.iquery.iQueryParser; 17 | import cc.iqa.iquery.monkey.LayoutTree; 18 | import cc.iqa.iquery.monkey.LayoutTreeParser; 19 | 20 | public class iQueryIdeParserTest { 21 | private void helper(String iquery) throws Exception { 22 | iQueryParser parser = iQuery.createParser(iquery); 23 | Assert.assertNotNull(parser); 24 | Assert.assertEquals(0, parser.getErrors().size()); 25 | } 26 | 27 | private void nhelper(String iquery) throws Exception { 28 | iQueryParser parser = iQuery.createParser(iquery); 29 | Assert.assertNotNull(parser); 30 | Assert.assertFalse(0 == parser.getErrors().size()); 31 | } 32 | 33 | private LayoutTree constructTree(String path) throws IOException { 34 | BufferedReader in = 35 | new BufferedReader(new FileReader(path)); 36 | List lines = new ArrayList(); 37 | String line = null; 38 | 39 | while ( (line = in.readLine()) != null ) { 40 | lines.add(line); 41 | } 42 | 43 | String[] strs = new String[lines.size()]; 44 | return LayoutTreeParser.parse(lines.toArray(strs)); 45 | } 46 | 47 | @Test 48 | public void test测试iQueryIdeParser类的用法() throws Exception { 49 | helper("TextView"); 50 | helper("AllApps2D > GridView"); 51 | helper(":last"); 52 | helper("TextView :last"); 53 | helper("AllApps2D > GridView :last"); 54 | helper("DragLayer > ImageView :last"); 55 | helper(":first"); 56 | helper("TextView [mText!='鑫财通手机炒股']"); 57 | helper("TextView [mText='鑫财通手机炒股']"); 58 | helper("TextView [getEllipsize='MARQUEE'] [getVisibility='VISIBLE'] [mTop='528'] [mBottom = '660'] [mLeft = '236']"); 59 | helper(":not(TextView)"); 60 | helper("TextView :gt(3)"); 61 | helper("CellLayout :last-child"); 62 | helper("RelativeLayout > RelativeLayout > :text"); 63 | helper("RelativeLayout :first >> :text"); 64 | helper("PhoneWindow.DecorView >2 DragLayer"); 65 | helper("LinearLayout :first >> :radio"); 66 | helper("Workspace :nth-child(0) :parent"); 67 | 68 | // nhelper(":tex"); 69 | nhelper("LinearLayout > :te"); 70 | nhelper(":"); 71 | nhelper("LinearLayout > :te :first"); 72 | nhelper("TextView ['mText' = '测试文本'"); 73 | nhelper("TextView [mText = '测试文本'"); 74 | nhelper("TextView [mText( = '测试文本']"); 75 | nhelper("TextView [mText() = '测试文本']"); 76 | nhelper("TextView [mText = '测试文本]"); 77 | nhelper("TextView [mText = 测试文本]"); 78 | nhelper("TextView >"); 79 | nhelper("TextView :first >>"); 80 | /* 81 | nhelper(">> :label [mText='Title']"); 82 | nhelper("中文"); 83 | nhelper("LinearLayout > 中文"); 84 | nhelper("LinearLayout > :中文"); 85 | nhelper("LinearLayout > 中文 :first"); 86 | nhelper("LinearLayout > :中文 :first-child"); 87 | nhelper("LinearLayout > :中文 first"); 88 | */ 89 | } 90 | 91 | @Test 92 | public void test测试给HierarchyViewer4iOS的API调用() throws IOException, RecognitionException { 93 | iQueryParser parser = iQuery.createParser("AllApps2D > GridView"); 94 | List nodes = parser.query(constructTree( 95 | "/media/work/workspace/iqa/java/iQA.Runtime.Test/res/testParserMethod.txt").getAllNodesCopy()); 96 | 97 | Assert.assertEquals(0, parser.getErrors().size()); 98 | Assert.assertEquals(1, nodes.size()); 99 | Assert.assertTrue(nodes.get(0).getName().compareTo("android.widget.GridView@44ed4c18") == 0); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /java/Test/iQA.Runtime.Test/src/cc/iqa/iquery/test/iQueryInvalidSyntaxParserTest.java: -------------------------------------------------------------------------------- 1 | package cc.iqa.iquery.test; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import org.antlr.runtime.*; 7 | import org.junit.*; 8 | 9 | import cc.iqa.iquery.*; 10 | import cc.iqa.iquery.monkey.*; 11 | 12 | public class iQueryInvalidSyntaxParserTest { 13 | 14 | private LayoutTree constructTree(String path) throws IOException { 15 | BufferedReader in = new BufferedReader(new FileReader(path)); 16 | List lines = new ArrayList(); 17 | String line = null; 18 | 19 | while ((line = in.readLine()) != null) { 20 | lines.add(line); 21 | } 22 | 23 | String[] strs = new String[lines.size()]; 24 | return LayoutTreeParser.parse(lines.toArray(strs)); 25 | } 26 | 27 | private LayoutTree constructTree() throws IOException { 28 | String path = "/media/work/workspace/iqa/java/iQA.Runtime.Test/res/testParserMethod.txt"; 29 | return constructTree(path); 30 | } 31 | 32 | private Pair, List> parseQueryAgainst( 33 | List candidates, String iquery, List errors) 34 | throws IOException, RecognitionException { 35 | /* 36 | InputStream query = new ByteArrayInputStream(iquery.getBytes("utf8")); 37 | ANTLRInputStream input = new ANTLRInputStream(query); 38 | iQueryLexer lexer = new iQueryLexer(input, errors); 39 | CommonTokenStream tokens = new CommonTokenStream(lexer); 40 | iQueryParser parser = new iQueryParser(tokens, errors, true); 41 | */ 42 | iQueryParser parser = iQuery.createParser(iquery); 43 | List result = parser.query(candidates); 44 | return new Pair, List>(result, 45 | parser.getErrors()); 46 | } 47 | 48 | @Test 49 | public void testParseInvalidSeudoClassMethod() throws Exception { 50 | List errors = new ArrayList(); 51 | // errors.add("第1行,第1列: 未知的伪类\":tex\"!"); 52 | errors.add("无法处理的伪类:[tex]"); 53 | 54 | helper(":tex", errors); 55 | 56 | errors.clear(); 57 | errors.add("第1行,第1列: 对于伪类指示符\":\",冒号后需要跟具体的伪类名称!"); 58 | helper(":", errors); 59 | 60 | errors.clear(); 61 | // errors.add("第1行,第16列: 未知的伪类\":te\"!"); 62 | errors.add("无法处理的伪类:[te]"); 63 | helper("LinearLayout > :te", errors); 64 | } 65 | 66 | @Test 67 | public void testParseInvalidSingleElementMethod() throws Exception { 68 | List errors = new ArrayList(); 69 | errors.add("第1行,第1列: 查询语句中有无法识别的关键字\"中\"!"); 70 | errors.add("第1行,第2列: 查询语句中有无法识别的关键字\"文\"!"); 71 | 72 | helper("中文", errors); 73 | 74 | errors.clear(); 75 | errors.add("第1行,第16列: 查询语句中有无法识别的关键字\"中\"!"); 76 | errors.add("第1行,第17列: 查询语句中有无法识别的关键字\"文\"!"); 77 | errors.add("第1行,第14列: 取子控件集合\">\"操作符后面应该跟随有合法的过滤条件!"); 78 | helper("LinearLayout > 中文", errors); 79 | 80 | errors.clear(); 81 | errors.add("第1行,第17列: 查询语句中有无法识别的关键字\"中\"!"); 82 | errors.add("第1行,第18列: 查询语句中有无法识别的关键字\"文\"!"); 83 | errors.add("第1行,第16列: 对于伪类指示符\":\",冒号后需要跟具体的伪类名称!"); 84 | helper("LinearLayout > :中文", errors); 85 | } 86 | 87 | @Test 88 | public void testParseStopOnErrorMethod() throws Exception { 89 | List errors = new ArrayList(); 90 | // errors.add("第1行,第16列: 未知的伪类\":te\"!"); 91 | errors.add("无法处理的伪类:[te]"); 92 | helper("LinearLayout > :te :first", errors); 93 | 94 | errors.clear(); 95 | errors.add("第1行,第16列: 查询语句中有无法识别的关键字\"中\"!"); 96 | errors.add("第1行,第17列: 查询语句中有无法识别的关键字\"文\"!"); 97 | helper("LinearLayout > 中文 :first", errors); 98 | 99 | errors.clear(); 100 | errors.add("第1行,第17列: 查询语句中有无法识别的关键字\"中\"!"); 101 | errors.add("第1行,第18列: 查询语句中有无法识别的关键字\"文\"!"); 102 | errors.add("第1行,第16列: 未知的伪类\"::\"!"); 103 | helper("LinearLayout > :中文 :first-child", errors); 104 | 105 | errors.clear(); 106 | errors.add("第1行,第17列: 查询语句中有无法识别的关键字\"中\"!"); 107 | errors.add("第1行,第18列: 查询语句中有无法识别的关键字\"文\"!"); 108 | // 晕死,在词法解析时,中文因为无法识别,在生成错误消息时就把: first连在一起当作是伪类了 109 | // 这是因为在ErrorMessageHelper里是根据token来组合错误消息的。 110 | // 但好像也无伤大雅。 111 | helper("LinearLayout > :中文 first", errors); 112 | } 113 | 114 | @Test 115 | public void testParseParentheseNotMatchMethod() throws Exception { 116 | List errors = new ArrayList(); 117 | 118 | errors.add("第1行,第10列: 属性查询条件里,'['后面跟随有英文字母和数字组成的控件属性名,但是找到的是\"字符串\"-\"'mText'\"!"); 119 | helper("TextView ['mText' = '测试文本'", errors); 120 | 121 | errors.clear(); 122 | errors.add("第1行,第25列: 没有关闭的语句,期望']',当前碰到的是''''!"); 123 | helper("TextView [mText = '测试文本'", errors); 124 | 125 | errors.clear(); 126 | errors.add("第1行,第10列: 属性查询条件里,属性后面应该跟随有'='或者']',但是找到的是\"(\"!"); 127 | errors.add("第1行,第16列: 在'('处缺少期望的EOF!"); 128 | helper("TextView [mText( = '测试文本']", errors); 129 | 130 | errors.clear(); 131 | errors.add("第1行,第10列: 属性查询条件里,属性后面应该跟随有'='或者']',但是找到的是\"(\"!"); 132 | errors.add("第1行,第16列: 在'('处缺少期望的EOF!"); 133 | helper("TextView [mText() = '测试文本']", errors); 134 | } 135 | 136 | @Test 137 | public void testParseStringNotEndMethod() throws Exception { 138 | List errors = new ArrayList(); 139 | errors.add("第1行,第25列: 没有关闭的语句,期望'!"); 140 | // 下面的QUOTED_STRING已经被antlr直接变成字符串了,再重新研究翻译的手段比较麻烦,就只好这样了! 141 | errors.add("第1行,第25列: 没有关闭的语句,期望QUOTED_STRING,当前碰到的是''''!"); 142 | helper("TextView [mText = '测试文本]", errors); 143 | 144 | errors.clear(); 145 | errors.add("第1行,第19列: 查询语句中有无法识别的关键字\"测\"!"); 146 | errors.add("第1行,第20列: 查询语句中有无法识别的关键字\"试\"!"); 147 | errors.add("第1行,第21列: 查询语句中有无法识别的关键字\"文\"!"); 148 | errors.add("第1行,第22列: 查询语句中有无法识别的关键字\"本\"!"); 149 | errors.add("第1行,第23列: 在']'处缺少期望的QUOTED_STRING!"); 150 | helper("TextView [mText = 测试文本]", errors); 151 | } 152 | 153 | @Test 154 | public void test子孙操作符后面没有跟条件() throws Exception { 155 | List errors = new ArrayList(); 156 | errors.add("第1行,第10列: 取子控件集合\">\"操作符后面应该跟随有合法的过滤条件!"); 157 | helper("TextView >", errors); 158 | 159 | errors.clear(); 160 | errors.add("第1行,第19列: 取子控件集合\">>\"操作符后面应该跟随有合法的过滤条件!"); 161 | helper("TextView :first >>", errors); 162 | } 163 | 164 | /* 已经无效了。现在可以支持>>等操作符放在开头的情形里。 165 | @Test 166 | public void test回归测试1() throws Exception { 167 | List errors = new ArrayList(); 168 | errors.add("第1行,第1列: \">>\"操作符不能放在查询的开始,如果是要从根节点开始查询,请确保查询的集合里只有根节点一个元素,并且使用类似\"* >>\"或\":first >>\"的方式指定查询语句!"); 169 | helper(">> :label [mText='Title']", errors); 170 | } 171 | */ 172 | 173 | List _candidates = null; 174 | 175 | private void helper(String iquery, List expectedErrors) 176 | throws Exception { 177 | if (_candidates == null) { 178 | LayoutTree tree = constructTree(); 179 | _candidates = tree.getAllNodesCopy(); 180 | } 181 | 182 | List errors = new ArrayList(); 183 | Pair, List> result = null; 184 | try { 185 | result = parseQueryAgainst(_candidates, iquery, errors); 186 | } catch ( Exception e ) { 187 | errors.add(e.getMessage()); 188 | } 189 | 190 | if ( result == null ) { 191 | result = new Pair, List>(); 192 | result.second = errors; 193 | } 194 | 195 | if (result != null && result.first != null) { 196 | Assert.assertTrue( 197 | String.format("针对\"%1$s\"的查询语法错误,不应该返回任何结果!", iquery), 198 | result.first.size() == 0); 199 | } 200 | Assert.assertEquals(String.format("错误的查询语法是\"%1$s\"", iquery), 201 | expectedErrors.size(), result.second.size()); 202 | 203 | for (int i = 0; i < expectedErrors.size(); ++i) { 204 | Assert.assertEquals(String.format("错误的查询语法是\"%1$s\"", iquery), 205 | expectedErrors.get(i), result.second.get(i)); 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/.classpath.orig: -------------------------------------------------------------------------------- 1 | 2 | 3 | <<<<<<< local 4 | 5 | ======= 6 | 7 | >>>>>>> other 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | cc.iqa.demo.multiplatformdemoproject.test 4 | 5 | 6 | multiplatformdemoproject 7 | 8 | 9 | 10 | com.android.ide.eclipse.adt.ResourceManagerBuilder 11 | 12 | 13 | 14 | 15 | com.android.ide.eclipse.adt.PreCompilerBuilder 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javabuilder 21 | 22 | 23 | 24 | 25 | com.android.ide.eclipse.adt.ApkBuilder 26 | 27 | 28 | 29 | 30 | 31 | com.android.ide.eclipse.adt.AndroidNature 32 | org.eclipse.jdt.core.javanature 33 | 34 | 35 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/gen/cc/iqa/studio/demo/test/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package cc.iqa.studio.demo.test; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class drawable { 14 | public static final int ic_launcher=0x7f020000; 15 | } 16 | public static final class layout { 17 | public static final int main=0x7f030000; 18 | } 19 | public static final class string { 20 | public static final int app_name=0x7f040001; 21 | public static final int hello=0x7f040000; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/proguard.cfg: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 7 | 8 | -keep public class * extends android.app.Activity 9 | -keep public class * extends android.app.Application 10 | -keep public class * extends android.app.Service 11 | -keep public class * extends android.content.BroadcastReceiver 12 | -keep public class * extends android.content.ContentProvider 13 | -keep public class * extends android.app.backup.BackupAgentHelper 14 | -keep public class * extends android.preference.Preference 15 | -keep public class com.android.vending.licensing.ILicensingService 16 | 17 | -keepclasseswithmembernames class * { 18 | native ; 19 | } 20 | 21 | -keepclasseswithmembers class * { 22 | public (android.content.Context, android.util.AttributeSet); 23 | } 24 | 25 | -keepclasseswithmembers class * { 26 | public (android.content.Context, android.util.AttributeSet, int); 27 | } 28 | 29 | -keepclassmembers class * extends android.app.Activity { 30 | public void *(android.view.View); 31 | } 32 | 33 | -keepclassmembers enum * { 34 | public static **[] values(); 35 | public static ** valueOf(java.lang.String); 36 | } 37 | 38 | -keep class * implements android.os.Parcelable { 39 | public static final android.os.Parcelable$Creator *; 40 | } 41 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-8 12 | emma.enabled=true -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/java/Test/iQA.Sample.multiplatformdemoprojecttest/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/java/Test/iQA.Sample.multiplatformdemoprojecttest/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/java/Test/iQA.Sample.multiplatformdemoprojecttest/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello World! 5 | IQA.Sample.multiplatformdemoprojecttestTest 6 | 7 | -------------------------------------------------------------------------------- /java/Test/iQA.Sample.multiplatformdemoprojecttest/src/cc/iqa/demo/multiplatformdemoproject/test/iQueryAndroidTest.java: -------------------------------------------------------------------------------- 1 | package cc.iqa.demo.multiplatformdemoproject.test; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | import org.antlr.runtime.*; 6 | 7 | import junit.framework.Assert; 8 | import cc.iqa.iquery.*; 9 | import cc.iqa.iquery.android.*; 10 | 11 | import com.jayway.android.robotium.solo.*; 12 | 13 | import android.test.ActivityInstrumentationTestCase2; 14 | import android.view.*; 15 | 16 | @SuppressWarnings("rawtypes") 17 | public class iQueryAndroidTest extends ActivityInstrumentationTestCase2 { 18 | private static String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "cc.iqa.studio.demo.MainActivity"; 19 | private static String TARGET_PACKAGE_ID = "cc.iqa.studio.demo"; 20 | 21 | private Solo _solo; 22 | 23 | @SuppressWarnings("unchecked") 24 | public iQueryAndroidTest() throws Exception { 25 | super(TARGET_PACKAGE_ID, Class 26 | .forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME)); 27 | } 28 | 29 | public void setUp() throws Exception { 30 | this._solo = new Solo(this.getInstrumentation(), this.getActivity()); 31 | } 32 | 33 | public void testParseElement() throws Exception { 34 | List actual = parseQueryAgainst( 35 | _solo.getCurrentViews().get(0), "LinearLayout >> TextView"); 36 | Assert.assertEquals(12, actual.size()); 37 | 38 | for (int i = 0; i < actual.size(); ++i) { 39 | Assert.assertTrue(actual.get(i).getName().endsWith("TextView")); 40 | } 41 | } 42 | 43 | public void testParseAttribute() throws Exception { 44 | List actual = parseQueryAgainst( 45 | _solo.getCurrentViews().get(0), 46 | "LinearLayout >> TextView [mText = 'Down Under']"); 47 | Assert.assertEquals(2, actual.size()); 48 | 49 | for (int i = 0; i < actual.size(); ++i) { 50 | Assert.assertTrue(actual.get(i).getName().endsWith("TextView")); 51 | Assert.assertEquals("Down Under", actual.get(i) 52 | .getProperty("mText").getValue()); 53 | } 54 | } 55 | 56 | public void testParseAttributeNegative() throws Exception { 57 | // 已经不支持属性名为中文的情况了! 58 | List actual = parseQueryAgainst( 59 | _solo.getCurrentViews().get(0), 60 | "LinearLayout >> TextView [mText = 'Down Under']"); 61 | Assert.assertEquals(2, actual.size()); 62 | } 63 | 64 | public void testSimpleCreatingParserMethod() throws Exception { 65 | iQueryParser parser = iQuery.createParser("LinearLayout >> TextView [mText = 'Down Under']"); 66 | List candidates = new ArrayList(); 67 | candidates.add(new SoloTreeNode(_solo.getCurrentViews().get(0))); 68 | List result = parser.query(candidates); 69 | 70 | Assert.assertEquals(0, parser.getErrors().size()); 71 | Assert.assertEquals(2, result.size()); 72 | } 73 | 74 | public void test简化后的API() throws Exception { 75 | List r1 = iQuery.query( 76 | new SoloTreeNode(_solo.getCurrentViews().get(0)), 77 | "LinearLayout >> TextView [mText = 'Down Under']"); 78 | Assert.assertEquals(2, r1.size()); 79 | } 80 | 81 | private List parseQueryAgainst(View root, String iquery) 82 | throws IOException, RecognitionException { 83 | InputStream query = new ByteArrayInputStream(iquery.getBytes("utf8")); 84 | ANTLRInputStream input = new ANTLRInputStream(query); 85 | iQueryLexer lexer = new iQueryLexer(input); 86 | CommonTokenStream tokens = new CommonTokenStream(lexer); 87 | iQueryParser parser = new iQueryParser(tokens); 88 | 89 | List candidates = new ArrayList(); 90 | candidates.add(new SoloTreeNode(root)); 91 | List result = parser.query(candidates); 92 | return result; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | cc.iqa.demo.multiplatformdemoproject 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 30 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/gen/cc/iqa/studio/demo/R.java: -------------------------------------------------------------------------------- 1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. 2 | * 3 | * This class was automatically generated by the 4 | * aapt tool from the resource data it found. It 5 | * should not be modified by hand. 6 | */ 7 | 8 | package cc.iqa.studio.demo; 9 | 10 | public final class R { 11 | public static final class attr { 12 | } 13 | public static final class drawable { 14 | public static final int ic_launcher=0x7f020000; 15 | } 16 | public static final class id { 17 | public static final int author=0x7f060005; 18 | public static final int author_label=0x7f060004; 19 | public static final int back=0x7f06000b; 20 | public static final int btnAdd=0x7f06000a; 21 | public static final int btnBack=0x7f060000; 22 | public static final int btnDelete=0x7f060009; 23 | public static final int btnEdit=0x7f060001; 24 | public static final int btnOk=0x7f060008; 25 | public static final int copyright=0x7f060007; 26 | public static final int copyright_label=0x7f060006; 27 | public static final int edit=0x7f06000c; 28 | public static final int title=0x7f060003; 29 | public static final int title_label=0x7f060002; 30 | } 31 | public static final class layout { 32 | public static final int bookdetails=0x7f030000; 33 | public static final int bookeditor=0x7f030001; 34 | public static final int list_item=0x7f030002; 35 | public static final int main=0x7f030003; 36 | } 37 | public static final class menu { 38 | public static final int viewdetailsmenu=0x7f050000; 39 | } 40 | public static final class string { 41 | public static final int app_name=0x7f040001; 42 | public static final int hello=0x7f040000; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/proguard.cfg: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 7 | 8 | -keep public class * extends android.app.Activity 9 | -keep public class * extends android.app.Application 10 | -keep public class * extends android.app.Service 11 | -keep public class * extends android.content.BroadcastReceiver 12 | -keep public class * extends android.content.ContentProvider 13 | -keep public class * extends android.app.backup.BackupAgentHelper 14 | -keep public class * extends android.preference.Preference 15 | -keep public class com.android.vending.licensing.ILicensingService 16 | 17 | -keepclasseswithmembernames class * { 18 | native ; 19 | } 20 | 21 | -keepclasseswithmembers class * { 22 | public (android.content.Context, android.util.AttributeSet); 23 | } 24 | 25 | -keepclasseswithmembers class * { 26 | public (android.content.Context, android.util.AttributeSet, int); 27 | } 28 | 29 | -keepclassmembers class * extends android.app.Activity { 30 | public void *(android.view.View); 31 | } 32 | 33 | -keepclassmembers enum * { 34 | public static **[] values(); 35 | public static ** valueOf(java.lang.String); 36 | } 37 | 38 | -keep class * implements android.os.Parcelable { 39 | public static final android.os.Parcelable$Creator *; 40 | } 41 | -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-8 12 | emma.enabled=true -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/java/Test/multiplatformdemoproject/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/java/Test/multiplatformdemoproject/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vowei/iQuery/acbd13223c119c91a129debdcb3a18c57e9ff39d/java/Test/multiplatformdemoproject/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /java/Test/multiplatformdemoproject/res/layout/bookdetails.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 |