├── .gitignore
├── LICENSE
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
├── gradle-mvn-push.gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── images
├── card.gif
├── complexcard.png
├── customer.png
├── demo.png
├── example.gif
└── logo.jpg
├── kratos-annotation
├── build.gradle
├── gradle.properties
└── src
│ └── main
│ └── java
│ └── kratos
│ ├── Bind.java
│ ├── BindLayout.java
│ ├── BindText.java
│ ├── Binds.java
│ ├── LBindLayout.java
│ ├── LBindText.java
│ ├── OnKBooleanChanged.java
│ ├── OnKStringChanged.java
│ ├── PackageName.java
│ └── WithBind.java
├── kratos-compiler
├── build.gradle
├── gradle.properties
└── src
│ └── main
│ └── java
│ └── kratos
│ └── compiler
│ ├── BindingClass.java
│ ├── FieldViewBinding.java
│ ├── KBinding.java
│ ├── KBindings.java
│ ├── KratosProcessor.java
│ ├── UpdateKStringBinding.java
│ └── binding
│ ├── KBindingGeneric.java
│ ├── KBooleanBinding.java
│ └── KStringBinding.java
├── kratos-sample
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── me
│ │ └── ele
│ │ └── kratos_sample
│ │ ├── CardSampleActivity.java
│ │ ├── SimpleActivity.java
│ │ ├── TextCard.java
│ │ ├── entity
│ │ ├── Customer.java
│ │ └── KText.java
│ │ └── package-info.java
│ └── res
│ ├── layout
│ ├── activity_simple.xml
│ └── kcard_text.xml
│ ├── raw
│ └── sample.json
│ └── values
│ ├── colors.xml
│ └── strings.xml
├── kratos
├── .gitignore
├── build.gradle
├── gradle.properties
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── kratos
│ │ ├── Kratos.java
│ │ ├── card
│ │ ├── KCard.kt
│ │ ├── KCardActivity.kt
│ │ ├── RenderExt.kt
│ │ ├── entity
│ │ │ └── KData.kt
│ │ ├── event
│ │ │ ├── ExceptionEvent.java
│ │ │ ├── FailEvent.java
│ │ │ ├── KMenuClickEvent.java
│ │ │ ├── KOnClickEvent.java
│ │ │ └── SuccessEvent.java
│ │ ├── render
│ │ │ ├── Header.kt
│ │ │ ├── Menu.kt
│ │ │ ├── SearchMenu.kt
│ │ │ ├── SearchStyle.kt
│ │ │ ├── Style.kt
│ │ │ └── Template.kt
│ │ └── utils
│ │ │ ├── ActivityUtils.java
│ │ │ ├── DelegateExt.kt
│ │ │ ├── DrawableUtils.java
│ │ │ ├── FixSwipeRefreshLayout.kt
│ │ │ ├── GsonUtils.java
│ │ │ ├── GsonUtilsCreator.java
│ │ │ ├── JsonVerify.java
│ │ │ ├── NotNullCardRenderListenter.kt
│ │ │ ├── OnCardRenderListener.kt
│ │ │ ├── Skip.java
│ │ │ └── StringUtils.java
│ │ ├── internal
│ │ ├── Binding.java
│ │ ├── KBase.kt
│ │ ├── KBinder.java
│ │ ├── KBoolean.kt
│ │ ├── KFinder.java
│ │ ├── KString.kt
│ │ ├── KStringDeserializer.java
│ │ └── ViewExt.kt
│ │ └── package-info.java
│ └── res
│ ├── layout
│ ├── inc_toolbar.xml
│ └── kcard_main.xml
│ ├── menu
│ └── empty.xml
│ └── values
│ └── style.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | /kratos/build
9 | /kratos-annotation/build
10 | /kratos-compiler/build
11 | /kratos-sample/build
12 | *.hprof
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
167 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Kratos
2 | =============
3 |
4 | 本项目旨在用来展示一个学习的样本,而不是用于生产环境,如果要用于生产的话,我建议使用React Native。Kratos展示了如何利用Annotation Processor和Javapoet在编译时期生成代码,达到类似Lisp宏一样的基础效果(实际差得远),实现Annotation free;还展示了利用Kolin语言的Delegate,实现检测变量的变化;最重要的是,展示了一套利用Json来渲染View的思路,并在Json中做配置,利用反射实现数据的View的绑定。这些代码,有助于帮助你理解React Native,比如Kotlin对应着Js,Json配置文件作为外部DSL对应着Jsx。
5 |
6 | 其实本想着实现一个用Lisp在Android上开发的框架,无奈本人太菜,算了,以后再说,先研究React Native好了 ╮(╯▽╰)╭
7 |
8 | 
9 |
10 | Provide basic __Double Binding(Data Binding)__ feature on Android.
11 |
12 | * Using annotation to generate boilerplate code.
13 | * Bind view and data to help you clean your code.
14 |
15 |
16 | Example
17 | ----------------
18 |
19 | ### Data Binding
20 |
21 | The following code demostrate that two views(EditText and TextView) bound to one single data(which in the code `boundData` holds the data. you can later access or change the data by using `boundData.get()` and `boundData.set("some string")`)
22 |
23 | ```java
24 | public class SimpleActivity extends Activity {
25 |
26 | @BindText({R.id.test_doublebinding_input, R.id.test_doublebinding_presenter})
27 | KString boundData = new KString();
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_simple);
33 | Kratos.bind(this);
34 | }
35 | }
36 | ```
37 | The presenter(TextView) will behave exactly the same as input(EditText) since they were bound to the same data:
38 |
39 | 
40 |
41 | What if you want yourself a custom update behavior than the default update method when data changes? You can add custom update function to update view:
42 |
43 | ```java
44 | @BindText(R.id.some_edittext_id)
45 | KString boundData = new KString(new KString.Update() {
46 | @Override
47 | public void update(@NotNull View view, @NotNull String s) {
48 | EditText et = (EditText)view; //Add custom update function here.
49 | int start = et.getSelectionStart(); // This code is the same as: public KString boundData1 = new KString(),
50 | et.setText(s); // since this custom function is the same as the default function.
51 | et.setSelection(start);
52 | }
53 | });
54 | ```
55 | If you are using Kotlin, the code is more simple:
56 |
57 | ```java
58 | @KBindText("some_edittext_id")
59 | public var boundData = KString {
60 | it, new ->
61 | it as EditText
62 | val position = this.selectionStart
63 | this.setText(new)
64 | this.setSelection(position)
65 | }
66 | ```
67 |
68 | ### Card
69 |
70 | __The concept of Card is very important in Kratos.__
71 |
72 | Basically, every view is a card, each activity is generated by one single json file, a little bit like html.
73 |
74 | The goal is to implement each view as a card,
75 | and then easily reuse them by manipulating json file.
76 |
77 | For example, the following activity is generated from [`sample.json`][4] file.
78 |
79 | 
80 |
81 | You can easily handle click event by override `onEventMainThread` method.
82 |
83 | #### Notice that
84 |
85 | * Kratos uses toolbar by default, so you need a `NoActionBar` theme in your style file, or you can just use `KratosTheme`.
86 | * When you run into non-final id problem in your library project, just use annotation start with "L", for example `LBindText`. But remember that you should never use both kind of annotation in the same file!
87 |
88 | #### What's the benefit
89 |
90 | * No more fear of the changing requirements. Since activities are generated from json file, you can manipulate the layout on the fly(imagine put the json file on a server, like html on website).
91 | * No more redundant code. Since each view is a card, you can reuse views easily by manipulate the json file.
92 | * Easily create and compose custom views. All you need to do is to extend KCard, create you own KData and bind the data to the card(must write full package name, so that kratos can find your card). You can implement rather complex card using kratos depending on your skills. For example, all the view in the following activity are card:
93 |
94 | 
95 |
96 | For more code see kratos-sample.
97 |
98 | How To
99 | -----------------
100 |
101 | ### Create custom card
102 |
103 | To Create a card consists of two TextView that can also handle click even2
104 |
105 | 1. Create a class that extends KData, for example:
106 |
107 | ```java
108 | public class KText extends KData {
109 | public KString text1;
110 | public KString text2;
111 | }
112 | ```
113 | 2. Create a class that extends KCard, use KData as its Generic, for example:
114 |
115 | ```java
116 | @BindLayout(R.layout.kcard_text) //@LBindLayout("kcard_text")
117 | @Binds({@Bind(id = R.id.kcard_text_text1, data = "text1"),
118 | @Bind(id = R.id.kcard_text_text2, data = "text2")})
119 | public class TextCard extends KCard {
120 | public TextCard(@NotNull Context context) {
121 | super(context);
122 | }
123 |
124 | @Override
125 | public void init() {
126 | setOnLinkListener();
127 | }
128 | }
129 | ```
130 |
131 | You should initailize your stuff inside `init` function, not constructor;
132 |
133 | Notice that it uses `BindLayout` to specify its layout:
134 |
135 | ```xml
136 |
137 |
144 |
145 |
152 |
159 |
160 | ```
161 |
162 | 3. Create a Activity that extends KCardActivity:
163 |
164 | ```java
165 | public class CardSampleActivity extends KCardActivity {
166 |
167 | private void showToast(String text) {
168 | Toast.makeText(CardSampleActivity.this, text, Toast.LENGTH_SHORT).show();
169 | }
170 |
171 | @Override
172 | public void onEventMainThread(@NotNull KOnClickEvent event) {
173 | super.onEventMainThread(event);
174 | switch (event.id) {
175 | case "textCard1":
176 | showToast("Handle click on textCard1!");
177 | break;
178 | }
179 | }
180 | }
181 | ```
182 | Notice that it handles click event by overriding o`nEventMainThread` method.
183 |
184 | 4. Pass your json layout to your activity:
185 |
186 | ```json
187 | {
188 | "header": {
189 | "title": "Card Sample"
190 | },
191 | "body": [
192 | {
193 | "data": {
194 | "text": "this is text1",
195 | "text": "this is text2"
196 | },
197 | "type": "me.ele.kratos_sample.TextCard",
198 | "id": "textCard1",
199 | "style": {
200 | "margin_top": 20,
201 | "margin_left": 20,
202 | "margin_right": 20
203 | }
204 | }
205 | ]
206 | }
207 | ```
208 | Notice that it uses full package name in `type` property.
209 |
210 | You can use kratos' util function to pass json file to your next activity:
211 |
212 | ```java
213 | ActivityUtils.jump(SimpleActivity.this, CardSampleActivity.class, CODE_CARD_SAMPLE, R.raw.sample);
214 | ```
215 |
216 | 5. Create a package-info.java file in your source folder like this:
217 |
218 | ```java
219 | @PackageName package me.ele.kratos_sample;
220 |
221 | import kratos.PackageName;
222 | ```
223 |
224 | You will get something like this:
225 |
226 | 
227 |
228 | ### Add Custom updater:
229 |
230 | If you want a custom update behavior when data been changed, add a function annotated with `OnKStringChanged` to your card, like this:
231 |
232 | ```java
233 | @OnKStringChanged("text1")
234 | public void updateText1(@NotNull TextView v, @NotNull String s) {
235 | v.setText(s);
236 | Log.d("TextCard", "custom updater!");
237 | }
238 | ```
239 |
240 | ### Wait
241 |
242 | *You may say:"That's no big deal. what's the point?"*
243 |
244 | *But*
245 |
246 | This is where the magic happens!
247 | -----------------
248 |
249 | Assume you have this data object which implements `Parcelable`:
250 |
251 | ```java
252 | public class Customer implements Parcelable {
253 |
254 | public KString name = new KString();
255 |
256 | @Override
257 | public int describeContents() {
258 | return 0;
259 | }
260 |
261 | @Override
262 | public void writeToParcel(Parcel dest, int flags) {
263 | dest.writeParcelable(this.name, flags);
264 | }
265 |
266 | public Customer() {
267 | }
268 |
269 | protected Customer(Parcel in) {
270 | this.name = in.readParcelable(KString.class.getClassLoader());
271 | }
272 |
273 | public static final Creator CREATOR = new Creator() {
274 | public Customer createFromParcel(Parcel source) {
275 | return new Customer(source);
276 | }
277 |
278 | public Customer[] newArray(int size) {
279 | return new Customer[size];
280 | }
281 | };
282 | }
283 | ```
284 | This Customer has a property -- name, and this is what you do.
285 |
286 | 1. Change the `text1` element in the json file above to this:
287 |
288 | ```json
289 | "text1": "{Customer.name}",
290 | ```
291 |
292 | 2. Add this code to your activity:
293 |
294 | ```java
295 | Customer customer;
296 | @Override
297 | public void onFinishRender() {
298 | bind(this, customer);
299 | }
300 | ```
301 | Tada!!From now on, if you want to change the view that has Customer's name in it, all you need to do is change the value of `customer.name`, say you do this:
302 |
303 | ```java
304 | customer.name.set("Merlin");
305 | ```
306 | This is what you get:
307 |
308 | 
309 |
310 | Dude, Holy ****, This is Magic..
311 |
312 |
313 | Download
314 | -----------------
315 | __Kratos is still under development and a lot of features haven't been added to it yet.__ But the basic idea is here. If you are interested in this project, feel free to fork.
316 |
317 | Kratos is available from maven central:
318 |
319 | ```groovy
320 | apply plugin: 'com.neenbedankt.android-apt'
321 | buildscript {
322 | ext.kratos_version = '0.2.4'
323 | repositories {
324 | mavenCentral()
325 | }
326 | dependencies {
327 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
328 | }
329 | }
330 |
331 | dependencies {
332 | compile "com.github.acemerlin:kratos:$kratos_version"
333 | apt "com.github.acemerlin:kratos-compiler:$kratos_version"
334 | }
335 | ```
336 |
337 | How It Works
338 | ----------------
339 | * Use Kotlin's [Observable Delegate][1] to listen to changes made to certain property.
340 | * Use Kotlin's [Extension][2] feature to add functions to View.
341 | * Use Annotation Processor to generate code which binds the data and the view(or views).
342 |
343 |
344 | Lisence
345 | ----------------
346 | [GNU GENERAL PUBLIC LICENSE Version 3][3]
347 |
348 | [1]: https://kotlinlang.org/docs/reference/delegated-properties.html#observable
349 | [2]: https://kotlinlang.org/docs/reference/extensions.html
350 | [3]: http://www.gnu.org/licenses/gpl-3.0.en.html
351 | [4]: https://github.com/ACEMerlin/Kratos/blob/feature/card/kratos-sample/src/main/res/raw/sample.json
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | subprojects { project ->
3 | group = GROUP
4 | version = VERSION_NAME
5 | buildscript {
6 | repositories {
7 | jcenter()
8 | mavenCentral()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:1.5.0'
12 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
13 | }
14 | }
15 | }
16 |
17 | ext {
18 | minSdkVersion = 15
19 | targetSdkVersion = 23
20 | compileSdkVersion = 23
21 | buildToolsVersion = '23.0.1'
22 | sourceCompatibilityVersion = JavaVersion.VERSION_1_7
23 | targetCompatibilityVersion = JavaVersion.VERSION_1_7
24 | }
25 |
26 | allprojects {
27 | repositories {
28 | jcenter()
29 | mavenCentral()
30 | }
31 | }
32 |
33 | task clean(type: Delete) {
34 | delete rootProject.buildDir
35 | }
36 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-XX:MaxPermSize=1024m
2 |
3 | GROUP=com.github.acemerlin
4 | VERSION_NAME=0.2.4
5 |
6 | POM_DESCRIPTION=Add basic double binding support to android.
7 |
8 | POM_URL=https://github.com/ACEMerlin/Kratos
9 | POM_SCM_URL=https://github.com/ACEMerlin/Kratos
10 | POM_SCM_CONNECTION=scm:git:git://github.com/ACEMerlin/Kratos.git
11 | POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/ACEMerlin/Kratos.git
12 |
13 | POM_LICENCE_NAME=GNU GENERAL PUBLIC LICENSE, Version 3.0
14 | POM_LICENCE_URL=http://www.gnu.org/licenses/gpl-3.0.en.html
15 | POM_LICENCE_DIST=repo
16 |
17 | POM_DEVELOPER_ID=merlin
18 | POM_DEVELOPER_NAME=Ge Chen
19 |
--------------------------------------------------------------------------------
/gradle/gradle-mvn-push.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Chris Banes
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: 'maven'
18 | apply plugin: 'signing'
19 |
20 | version = VERSION_NAME
21 | group = GROUP
22 |
23 | repositories {
24 | mavenCentral()
25 | }
26 |
27 | def isReleaseBuild() {
28 | return VERSION_NAME.contains("SNAPSHOT") == false
29 | }
30 |
31 | def getReleaseRepositoryUrl() {
32 | return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
33 | : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
34 | }
35 |
36 | def getSnapshotRepositoryUrl() {
37 | return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
38 | : "https://oss.sonatype.org/content/repositories/snapshots/"
39 | }
40 |
41 | def getRepositoryUsername() {
42 | return hasProperty('SONATYPE_NEXUS_USERNAME') ? SONATYPE_NEXUS_USERNAME : ""
43 | }
44 |
45 | def getRepositoryPassword() {
46 | return hasProperty('SONATYPE_NEXUS_PASSWORD') ? SONATYPE_NEXUS_PASSWORD : ""
47 | }
48 |
49 | afterEvaluate { project ->
50 | uploadArchives {
51 | repositories {
52 | mavenDeployer {
53 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
54 |
55 | pom.groupId = GROUP
56 | pom.artifactId = POM_ARTIFACT_ID
57 | pom.version = VERSION_NAME
58 |
59 | repository(url: getReleaseRepositoryUrl()) {
60 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
61 | }
62 | snapshotRepository(url: getSnapshotRepositoryUrl()) {
63 | authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
64 | }
65 |
66 | pom.project {
67 | name POM_NAME
68 | packaging POM_PACKAGING
69 | description POM_DESCRIPTION
70 | url POM_URL
71 |
72 | scm {
73 | url POM_SCM_URL
74 | connection POM_SCM_CONNECTION
75 | developerConnection POM_SCM_DEV_CONNECTION
76 | }
77 |
78 | licenses {
79 | license {
80 | name POM_LICENCE_NAME
81 | url POM_LICENCE_URL
82 | distribution POM_LICENCE_DIST
83 | }
84 | }
85 |
86 | developers {
87 | developer {
88 | id POM_DEVELOPER_ID
89 | name POM_DEVELOPER_NAME
90 | }
91 | }
92 | }
93 | }
94 | }
95 | }
96 |
97 | signing {
98 | required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
99 | sign configurations.archives
100 | }
101 |
102 | if (project.getPlugins().hasPlugin('com.android.application') ||
103 | project.getPlugins().hasPlugin('com.android.library')) {
104 | task install(type: Upload, dependsOn: assemble) {
105 | repositories.mavenInstaller {
106 | configuration = configurations.archives
107 |
108 | pom.groupId = GROUP
109 | pom.artifactId = POM_ARTIFACT_ID
110 | pom.version = VERSION_NAME
111 |
112 | pom.project {
113 | name POM_NAME
114 | packaging POM_PACKAGING
115 | description POM_DESCRIPTION
116 | url POM_URL
117 |
118 | scm {
119 | url POM_SCM_URL
120 | connection POM_SCM_CONNECTION
121 | developerConnection POM_SCM_DEV_CONNECTION
122 | }
123 |
124 | licenses {
125 | license {
126 | name POM_LICENCE_NAME
127 | url POM_LICENCE_URL
128 | distribution POM_LICENCE_DIST
129 | }
130 | }
131 |
132 | developers {
133 | developer {
134 | id POM_DEVELOPER_ID
135 | name POM_DEVELOPER_NAME
136 | }
137 | }
138 | }
139 | }
140 | }
141 |
142 | task androidJavadocs(type: Javadoc) {
143 | if (!project.plugins.hasPlugin('kotlin-android')) {
144 | source = android.sourceSets.main.java.srcDirs
145 | }
146 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
147 | exclude '**/internal/*'
148 |
149 | if (JavaVersion.current().isJava8Compatible()) {
150 | options.addStringOption('Xdoclint:none', '-quiet')
151 | }
152 | }
153 |
154 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
155 | classifier = 'javadoc'
156 | from androidJavadocs.destinationDir
157 | }
158 |
159 | task androidSourcesJar(type: Jar) {
160 | classifier = 'sources'
161 | from android.sourceSets.main.java.source
162 | }
163 |
164 | } else {
165 | install {
166 | repositories.mavenInstaller {
167 | pom.groupId = GROUP
168 | pom.artifactId = POM_ARTIFACT_ID
169 | pom.version = VERSION_NAME
170 |
171 | pom.project {
172 | name POM_NAME
173 | packaging POM_PACKAGING
174 | description POM_DESCRIPTION
175 | url POM_URL
176 |
177 | scm {
178 | url POM_SCM_URL
179 | connection POM_SCM_CONNECTION
180 | developerConnection POM_SCM_DEV_CONNECTION
181 | }
182 |
183 | licenses {
184 | license {
185 | name POM_LICENCE_NAME
186 | url POM_LICENCE_URL
187 | distribution POM_LICENCE_DIST
188 | }
189 | }
190 |
191 | developers {
192 | developer {
193 | id POM_DEVELOPER_ID
194 | name POM_DEVELOPER_NAME
195 | }
196 | }
197 | }
198 | }
199 | }
200 |
201 | task sourcesJar(type: Jar, dependsOn:classes) {
202 | classifier = 'sources'
203 | from sourceSets.main.allSource
204 | }
205 |
206 | task javadocJar(type: Jar, dependsOn:javadoc) {
207 | classifier = 'javadoc'
208 | from javadoc.destinationDir
209 | }
210 | }
211 |
212 | artifacts {
213 | if (project.getPlugins().hasPlugin('com.android.application') ||
214 | project.getPlugins().hasPlugin('com.android.library')) {
215 | archives androidSourcesJar
216 | archives androidJavadocsJar
217 | } else {
218 | archives sourcesJar
219 | archives javadocJar
220 | }
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACEMerlin/Kratos/c11bb855940c063e7adb775ae366dfd3dd534a0a/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/images/card.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACEMerlin/Kratos/c11bb855940c063e7adb775ae366dfd3dd534a0a/images/card.gif
--------------------------------------------------------------------------------
/images/complexcard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACEMerlin/Kratos/c11bb855940c063e7adb775ae366dfd3dd534a0a/images/complexcard.png
--------------------------------------------------------------------------------
/images/customer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACEMerlin/Kratos/c11bb855940c063e7adb775ae366dfd3dd534a0a/images/customer.png
--------------------------------------------------------------------------------
/images/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACEMerlin/Kratos/c11bb855940c063e7adb775ae366dfd3dd534a0a/images/demo.png
--------------------------------------------------------------------------------
/images/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACEMerlin/Kratos/c11bb855940c063e7adb775ae366dfd3dd534a0a/images/example.gif
--------------------------------------------------------------------------------
/images/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ACEMerlin/Kratos/c11bb855940c063e7adb775ae366dfd3dd534a0a/images/logo.jpg
--------------------------------------------------------------------------------
/kratos-annotation/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | sourceCompatibility = rootProject.ext.sourceCompatibilityVersion
4 | targetCompatibility = rootProject.ext.targetCompatibilityVersion
5 |
6 | def logger = new com.android.build.gradle.internal.LoggerWrapper(project.logger)
7 | def sdkHandler = new com.android.build.gradle.internal.SdkHandler(project, logger)
8 | for (File file : sdkHandler.sdkLoader.repositories) {
9 | repositories.maven {
10 | url = file.toURI()
11 | }
12 | }
13 |
14 | dependencies {
15 | compile 'com.android.support:support-annotations:23.1.1'
16 | }
17 |
18 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/kratos-annotation/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Kratos Annotations
2 | POM_ARTIFACT_ID=kratos-annotations
3 | POM_PACKAGING=jar
4 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/Bind.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import android.support.annotation.IdRes;
4 |
5 | import java.lang.annotation.ElementType;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | /**
11 | * Created by merlin on 15/12/22.
12 | */
13 | @Retention(RetentionPolicy.CLASS)
14 | @Target(ElementType.TYPE)
15 | public @interface Bind {
16 | String data();
17 |
18 | @IdRes int id();
19 | }
20 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/BindLayout.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import android.support.annotation.LayoutRes;
4 |
5 | import java.lang.annotation.ElementType;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | /**
11 | * Created by merlin on 15/12/21.
12 | */
13 | @Retention(RetentionPolicy.CLASS)
14 | @Target(ElementType.TYPE)
15 | public @interface BindLayout {
16 | @LayoutRes int value();
17 | }
18 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/BindText.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import android.support.annotation.IdRes;
4 |
5 | import java.lang.annotation.ElementType;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | /**
11 | * Created by merlin on 15/12/7.
12 | */
13 | @Retention(RetentionPolicy.CLASS)
14 | @Target(ElementType.FIELD)
15 | public @interface BindText {
16 | @IdRes int[] value();
17 | }
18 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/Binds.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by merlin on 15/12/22.
10 | */
11 | @Retention(RetentionPolicy.CLASS)
12 | @Target(ElementType.TYPE)
13 | public @interface Binds {
14 | Bind[] value();
15 | }
16 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/LBindLayout.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by merlin on 15/12/21.
10 | */
11 | @Retention(RetentionPolicy.CLASS)
12 | @Target(ElementType.TYPE)
13 | public @interface LBindLayout {
14 | String value();
15 | }
16 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/LBindText.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by merlin on 15/12/4.
10 | */
11 | @Retention(RetentionPolicy.CLASS)
12 | @Target(ElementType.FIELD)
13 | public @interface LBindText {
14 | String[] value();
15 | }
16 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/OnKBooleanChanged.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by merlin on 15/12/24.
10 | */
11 | @Retention(RetentionPolicy.CLASS)
12 | @Target(ElementType.METHOD)
13 | public @interface OnKBooleanChanged {
14 | String value();
15 | }
16 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/OnKStringChanged.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by merlin on 15/12/24.
10 | */
11 | @Retention(RetentionPolicy.CLASS)
12 | @Target(ElementType.METHOD)
13 | public @interface OnKStringChanged {
14 | String value();
15 | }
16 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/PackageName.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by merlin on 15/12/21.
10 | */
11 | @Retention(RetentionPolicy.CLASS)
12 | @Target(ElementType.PACKAGE)
13 | public @interface PackageName {
14 | }
15 |
--------------------------------------------------------------------------------
/kratos-annotation/src/main/java/kratos/WithBind.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by merlin on 16/1/28.
10 | */
11 | @Retention(RetentionPolicy.CLASS)
12 | @Target(ElementType.TYPE)
13 | public @interface WithBind {
14 | }
15 |
--------------------------------------------------------------------------------
/kratos-compiler/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | sourceCompatibility = rootProject.ext.sourceCompatibilityVersion
4 | targetCompatibility = rootProject.ext.targetCompatibilityVersion
5 |
6 | def logger = new com.android.build.gradle.internal.LoggerWrapper(project.logger)
7 | def sdkHandler = new com.android.build.gradle.internal.SdkHandler(project, logger)
8 | for (File file : sdkHandler.sdkLoader.repositories) {
9 | repositories.maven {
10 | url = file.toURI()
11 | }
12 | }
13 |
14 | dependencies {
15 | compile project (':kratos-annotation')
16 | compile 'com.google.auto.service:auto-service:1.0-rc2'
17 | compile 'com.squareup:javapoet:1.4.0'
18 | }
19 |
20 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/kratos-compiler/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=Kratos Compiler
2 | POM_ARTIFACT_ID=kratos-compiler
3 | POM_PACKAGING=jar
4 |
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/BindingClass.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler;
2 |
3 | import com.squareup.javapoet.ClassName;
4 | import com.squareup.javapoet.JavaFile;
5 | import com.squareup.javapoet.MethodSpec;
6 | import com.squareup.javapoet.ParameterizedTypeName;
7 | import com.squareup.javapoet.TypeSpec;
8 | import com.squareup.javapoet.TypeVariableName;
9 |
10 | import java.util.Collection;
11 | import java.util.LinkedHashMap;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | import javax.lang.model.element.Modifier;
16 |
17 | import kratos.compiler.binding.KBindingGeneric;
18 |
19 | import static javax.lang.model.element.Modifier.FINAL;
20 | import static javax.lang.model.element.Modifier.PUBLIC;
21 |
22 | /**
23 | * Created by merlin on 15/12/7.
24 | */
25 | public class BindingClass {
26 |
27 | private final String classPackage;
28 | private final String className;
29 | private final String targetClass;
30 | private final ClassName resClass;
31 | private String parentViewBinder;
32 | private static final ClassName KBINDER = ClassName.get("kratos.internal", "KBinder");
33 | private static final ClassName KFINDER = ClassName.get("kratos.internal", "KFinder");
34 | private static final ClassName VIEW = ClassName.get("android.view", "View");
35 | static final int NO_ID = -1;
36 | private final boolean isLibrary;
37 | private final boolean isKotlin;
38 |
39 | private final Map viewIdMap = new LinkedHashMap<>();
40 | private final Map updateKStringBindingMap = new LinkedHashMap<>();
41 | private String layoutId;
42 |
43 | public void setLayoutId(String layoutId) {
44 | this.layoutId = layoutId;
45 | }
46 |
47 | BindingClass(String classPackage, String className, String targetClass, String resPackage, Boolean isLibrary, Boolean isKotlin) {
48 | this.classPackage = classPackage;
49 | this.className = className;
50 | this.targetClass = targetClass;
51 | this.resClass = ClassName.get(resPackage, "R");
52 | this.isLibrary = isLibrary;
53 | this.isKotlin = isKotlin;
54 | }
55 |
56 | void setParentViewBinder(String parentViewBinder) {
57 | this.parentViewBinder = parentViewBinder;
58 | }
59 |
60 | JavaFile brewJava() {
61 | TypeSpec.Builder result = TypeSpec.classBuilder(className)
62 | .addModifiers(PUBLIC)
63 | .addTypeVariable(TypeVariableName.get("T", ClassName.bestGuess(targetClass)));
64 |
65 | if (parentViewBinder != null) {
66 | result.superclass(ParameterizedTypeName.get(ClassName.bestGuess(parentViewBinder),
67 | TypeVariableName.get("T")));
68 | } else {
69 | result.addSuperinterface(ParameterizedTypeName.get(KBINDER, TypeVariableName.get("T")));
70 | }
71 |
72 | result.addMethod(createBindMethod());
73 |
74 | return JavaFile.builder(classPackage, result.build())
75 | .addFileComment("Generated code from Kratos. Do not modify!")
76 | .build();
77 | }
78 |
79 | private MethodSpec createBindMethod() {
80 | MethodSpec.Builder result = MethodSpec.methodBuilder("bind")
81 | .addAnnotation(Override.class)
82 | .addModifiers(PUBLIC)
83 | .addParameter(TypeVariableName.get("T"), "target", FINAL)
84 | .addParameter(KFINDER, "finder", FINAL);
85 | if (parentViewBinder != null) {
86 | result.addStatement("super.bind(target, finder)");
87 | }
88 | if (layoutId != null) {
89 | if (!isLibrary)
90 | result.addStatement("target.setLayoutId($L)", Integer.parseInt(layoutId));
91 | else
92 | result.addStatement("target.setLayoutId($T.layout.$L)", resClass, layoutId);
93 | result.addStatement("target.init()");
94 | }
95 | //if (!updateKStringBindingMap.isEmpty()) {
96 | // for (Map.Entry entry : updateKStringBindingMap.entrySet()) {
97 | // addKStringUpdateBindings(result, entry);
98 | // }
99 | //}
100 | if (!map.isEmpty()) {
101 | for (Map generics : map.values()) {
102 | for (Map.Entry entry : generics.entrySet()) {
103 | entry.getValue().addGenericCode(result, entry.getKey());
104 | }
105 | }
106 | }
107 | if (!viewIdMap.isEmpty()) {
108 | result.addStatement("$T view", VIEW);
109 | // Loop over each view bindings and emit it.
110 | for (KBindings bindings : viewIdMap.values()) {
111 | addKBindings(result, bindings);
112 | }
113 | }
114 | if (!doubleBindingMap.isEmpty()) {
115 | if (viewIdMap.isEmpty()) {
116 | result.addStatement("$T view", VIEW);
117 | }
118 | for (Map.Entry entry : doubleBindingMap.entrySet()) {
119 | addDoubleBindings(result, entry);
120 | }
121 | }
122 | return result.build();
123 | }
124 |
125 | private void addDoubleBindings(MethodSpec.Builder result, Map.Entry entry) {
126 | result.addStatement("view = finder.findRequiredView(target, $L)", entry.getKey());
127 | result.addStatement("target.getData().$L.bind(view)", entry.getValue());
128 | result.addStatement("target.getData().$L.set(target.getData().$L.getInitData())", entry.getValue(), entry.getValue());
129 | }
130 |
131 | private void addKBindings(MethodSpec.Builder result, KBindings bindings) {
132 | List requiredViewBindings = bindings.getRequiredBindings();
133 | if (!isLibrary) {
134 | if (requiredViewBindings.isEmpty()) {
135 | result.addStatement("view = finder.findOptionalView(target, $L)", bindings.getId());
136 | } else {
137 | int id = Integer.parseInt(bindings.getId());
138 | if (id == NO_ID) {
139 | result.addStatement("view = target");
140 | } else {
141 | result.addStatement("view = finder.findRequiredView(target, $L)", id);
142 | }
143 | }
144 | } else {
145 | if (requiredViewBindings.isEmpty()) {
146 | result.addStatement("view = finder.findOptionalView(target, $T.id.$L)", resClass, bindings.getId());
147 | } else {
148 | if (bindings.getId() == null) {
149 | result.addStatement("view = target");
150 | } else {
151 | result.addStatement("view = finder.findRequiredView(target, $T.id.$L)", resClass, bindings.getId());
152 | }
153 | }
154 | }
155 | addFieldBindings(result, bindings);
156 | }
157 |
158 | private void addFieldBindings(MethodSpec.Builder result, KBindings bindings) {
159 | Collection fieldBindings = bindings.getFieldBindings();
160 | for (FieldViewBinding fieldBinding : fieldBindings) {
161 | if (fieldBinding.requiresCast()) {
162 | result.addStatement("$T $L = finder.castView(view)", VIEW, fieldBinding.getName() + bindings.getId());
163 | } else {
164 | result.addStatement("$T $L = view", VIEW, fieldBinding.getName() + bindings.getId());
165 | }
166 | if (isKotlin) {
167 | String name = fieldBinding.getName();
168 | result.addStatement("target.get$L().bind($L)", name.substring(0, 1).toUpperCase() + name.substring(1, name.length()), name + bindings.getId());
169 | } else {
170 | result.addStatement("target.$L.bind($L)", fieldBinding.getName(), fieldBinding.getName() + bindings.getId());
171 | }
172 | }
173 | }
174 |
175 | public KBindings getKBindings(String id) {
176 | return viewIdMap.get(id);
177 | }
178 |
179 | void addField(String id, FieldViewBinding binding) {
180 | getOrCreateViewBindings(id).addFieldBinding(binding);
181 | }
182 |
183 | private KBindings getOrCreateViewBindings(String id) {
184 | KBindings viewId = viewIdMap.get(id);
185 | if (viewId == null) {
186 | viewId = new KBindings(id);
187 | viewIdMap.put(id, viewId);
188 | }
189 | return viewId;
190 | }
191 |
192 | private Map doubleBindingMap = new LinkedHashMap<>();
193 |
194 | public void addDoubleBinding(int id, String data) {
195 | String mData = doubleBindingMap.get(id);
196 | if (mData == null) {
197 | doubleBindingMap.put(id, data);
198 | }
199 | }
200 |
201 | public void addKStringUpdateBinding(String kstring, UpdateKStringBinding binding) {
202 | UpdateKStringBinding mData = updateKStringBindingMap.get(kstring);
203 | if (mData == null) {
204 | updateKStringBindingMap.put(kstring, binding);
205 | }
206 | }
207 |
208 | private final Map> map = new LinkedHashMap<>();
209 |
210 | public void putGeneric(String kstring, KBindingGeneric binding) {
211 | String key = binding.getClass().getSimpleName();
212 | Map result = map.get(key);
213 | if (result == null) {
214 | result = new LinkedHashMap<>();
215 | }
216 | KBindingGeneric mData = result.get(kstring);
217 | if (mData == null) {
218 | result.put(kstring, binding);
219 | }
220 | map.put(key, result);
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/FieldViewBinding.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler;
2 |
3 | import com.squareup.javapoet.TypeName;
4 |
5 | import static kratos.compiler.KratosProcessor.VIEW_TYPE;
6 |
7 | /**
8 | * Created by merlin on 15/12/7.
9 | */
10 | public final class FieldViewBinding implements KBinding {
11 | private final String name;
12 | private final TypeName type;
13 | private final boolean required;
14 |
15 | FieldViewBinding(String name, TypeName type, boolean required) {
16 | this.name = name;
17 | this.type = type;
18 | this.required = required;
19 | }
20 |
21 | public String getName() {
22 | return name;
23 | }
24 |
25 | public TypeName getType() {
26 | return type;
27 | }
28 |
29 | public boolean isRequired() {
30 | return required;
31 | }
32 |
33 | public boolean requiresCast() {
34 | return !VIEW_TYPE.equals(type.toString());
35 | }
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/KBinding.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler;
2 |
3 | /**
4 | * Created by merlin on 15/12/7.
5 | */
6 | public interface KBinding {
7 | }
8 |
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/KBindings.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.LinkedHashSet;
6 | import java.util.List;
7 | import java.util.Set;
8 |
9 | /**
10 | * Created by merlin on 15/12/7.
11 | */
12 | public class KBindings {
13 | private final Set fieldBindings = new LinkedHashSet<>();
14 | private final String id;
15 |
16 | KBindings(String id) {
17 | this.id = id;
18 | }
19 |
20 | public String getId() {
21 | return id;
22 | }
23 |
24 | public void addFieldBinding(FieldViewBinding fieldBinding) {
25 | fieldBindings.add(fieldBinding);
26 | }
27 |
28 | public Collection getFieldBindings() {
29 | return fieldBindings;
30 | }
31 |
32 | public List getRequiredBindings() {
33 | List requiredViewBindings = new ArrayList<>();
34 | for (FieldViewBinding fieldBinding : fieldBindings) {
35 | if (fieldBinding.isRequired()) {
36 | requiredViewBindings.add(fieldBinding);
37 | }
38 | }
39 | return requiredViewBindings;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/KratosProcessor.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler;
2 |
3 | import com.google.auto.common.SuperficialValidation;
4 | import com.google.auto.service.AutoService;
5 | import com.squareup.javapoet.TypeName;
6 |
7 | import java.io.IOException;
8 | import java.io.PrintWriter;
9 | import java.io.StringWriter;
10 | import java.lang.annotation.Annotation;
11 | import java.util.Iterator;
12 | import java.util.LinkedHashMap;
13 | import java.util.LinkedHashSet;
14 | import java.util.Map;
15 | import java.util.Set;
16 | import java.util.regex.Matcher;
17 | import java.util.regex.Pattern;
18 |
19 | import javax.annotation.processing.AbstractProcessor;
20 | import javax.annotation.processing.Filer;
21 | import javax.annotation.processing.ProcessingEnvironment;
22 | import javax.annotation.processing.Processor;
23 | import javax.annotation.processing.RoundEnvironment;
24 | import javax.lang.model.SourceVersion;
25 | import javax.lang.model.element.AnnotationMirror;
26 | import javax.lang.model.element.Element;
27 | import javax.lang.model.element.PackageElement;
28 | import javax.lang.model.element.TypeElement;
29 | import javax.lang.model.type.DeclaredType;
30 | import javax.lang.model.type.TypeKind;
31 | import javax.lang.model.type.TypeMirror;
32 | import javax.lang.model.type.TypeVariable;
33 | import javax.lang.model.util.Elements;
34 | import javax.lang.model.util.Types;
35 |
36 | import kratos.Bind;
37 | import kratos.BindLayout;
38 | import kratos.BindText;
39 | import kratos.Binds;
40 | import kratos.LBindLayout;
41 | import kratos.LBindText;
42 | import kratos.OnKBooleanChanged;
43 | import kratos.OnKStringChanged;
44 | import kratos.PackageName;
45 | import kratos.compiler.binding.KBooleanBinding;
46 | import kratos.compiler.binding.KStringBinding;
47 |
48 | import static javax.lang.model.SourceVersion.latestSupported;
49 | import static javax.tools.Diagnostic.Kind.ERROR;
50 |
51 | @AutoService(Processor.class)
52 | public class KratosProcessor extends AbstractProcessor {
53 |
54 | private Elements elementUtils;
55 | private Types typeUtils;
56 | private Filer filer;
57 | private static final String BINDING_CLASS_SUFFIX = "$$KBinder";
58 | private static final String NULLABLE_ANNOTATION_NAME = "Nullable";
59 | static final String VIEW_TYPE = "android.view.View";
60 | private static String packageName = null;
61 |
62 | @Override
63 | public Set getSupportedAnnotationTypes() {
64 | Set types = new LinkedHashSet<>();
65 | //支持的annotation类型
66 | types.add(BindText.class.getCanonicalName());
67 | types.add(LBindText.class.getCanonicalName());
68 | types.add(BindLayout.class.getCanonicalName());
69 | types.add(LBindLayout.class.getCanonicalName());
70 | types.add(Binds.class.getCanonicalName());
71 | types.add(Bind.class.getCanonicalName());
72 | types.add(OnKStringChanged.class.getCanonicalName());
73 | types.add(OnKBooleanChanged.class.getCanonicalName());
74 | return types;
75 | }
76 |
77 | @Override
78 | public synchronized void init(ProcessingEnvironment env) {
79 | super.init(env);
80 | elementUtils = env.getElementUtils();
81 | typeUtils = env.getTypeUtils();
82 | filer = env.getFiler();
83 | }
84 |
85 | @Override
86 | public SourceVersion getSupportedSourceVersion() {
87 | return latestSupported();
88 | }
89 |
90 | @Override
91 | public boolean process(Set extends TypeElement> annotations, RoundEnvironment env) {
92 | Map targetClassMap = findAndParseTargets(env);
93 |
94 | for (Map.Entry entry : targetClassMap.entrySet()) {
95 | TypeElement typeElement = entry.getKey();
96 | BindingClass BindingClass = entry.getValue();
97 |
98 | try {
99 | BindingClass.brewJava().writeTo(filer);
100 | } catch (IOException e) {
101 | error(typeElement, "Unable to write view binder for type %s: %s", typeElement,
102 | e.getMessage());
103 | }
104 | }
105 |
106 | return true;
107 | }
108 |
109 | private Map findAndParseTargets(RoundEnvironment env) {
110 | Map targetClassMap = new LinkedHashMap<>();
111 | Set erasedTargetNames = new LinkedHashSet<>();
112 |
113 | // Process each @Bind element.
114 | for (Element element : env.getElementsAnnotatedWith(PackageName.class)) {
115 | if (!SuperficialValidation.validateElement(element)) continue;
116 | try {
117 | parsePackageName(element, targetClassMap, erasedTargetNames);
118 | } catch (Exception e) {
119 | logParsingError(element, PackageName.class, e);
120 | }
121 | }
122 |
123 | for (Element element : env.getElementsAnnotatedWith(Binds.class)) {
124 | if (!SuperficialValidation.validateElement(element)) continue;
125 | try {
126 | parseBinds(element, targetClassMap, erasedTargetNames);
127 | } catch (Exception e) {
128 | logParsingError(element, Binds.class, e);
129 | }
130 | }
131 |
132 | for (Element element : env.getElementsAnnotatedWith(Bind.class)) {
133 | if (!SuperficialValidation.validateElement(element)) continue;
134 | try {
135 | parseBind(element, targetClassMap, erasedTargetNames);
136 | } catch (Exception e) {
137 | logParsingError(element, Bind.class, e);
138 | }
139 | }
140 |
141 | for (Element element : env.getElementsAnnotatedWith(BindLayout.class)) {
142 | if (!SuperficialValidation.validateElement(element)) continue;
143 | try {
144 | parseBindLayout(element, targetClassMap, erasedTargetNames);
145 | } catch (Exception e) {
146 | logParsingError(element, BindLayout.class, e);
147 | }
148 | }
149 |
150 | for (Element element : env.getElementsAnnotatedWith(LBindLayout.class)) {
151 | if (!SuperficialValidation.validateElement(element)) continue;
152 | try {
153 | parseLBindLayout(element, targetClassMap, erasedTargetNames);
154 | } catch (Exception e) {
155 | logParsingError(element, LBindLayout.class, e);
156 | }
157 | }
158 |
159 | parseOnChangedTarget(env, targetClassMap, erasedTargetNames,
160 | OnKStringChanged.class, OnKBooleanChanged.class);
161 |
162 | for (Element element : env.getElementsAnnotatedWith(BindText.class)) {
163 | if (!SuperficialValidation.validateElement(element)) continue;
164 | try {
165 | parseBindText(element, targetClassMap, erasedTargetNames);
166 | } catch (Exception e) {
167 | logParsingError(element, BindText.class, e);
168 | }
169 | }
170 |
171 | for (Element element : env.getElementsAnnotatedWith(LBindText.class)) {
172 | if (!SuperficialValidation.validateElement(element)) continue;
173 | try {
174 | parseLBindText(element, targetClassMap, erasedTargetNames);
175 | } catch (Exception e) {
176 | logParsingError(element, LBindText.class, e);
177 | }
178 | }
179 |
180 | // Try to find a parent binder for each.
181 | for (Map.Entry entry : targetClassMap.entrySet()) {
182 | String parentClassFqcn = findParentFqcn(entry.getKey(), erasedTargetNames);
183 | if (parentClassFqcn != null) {
184 | entry.getValue().setParentViewBinder(parentClassFqcn + BINDING_CLASS_SUFFIX);
185 | }
186 | }
187 |
188 | return targetClassMap;
189 | }
190 |
191 | private void parseOnChangedTarget(RoundEnvironment env, Map targetClassMap, Set erasedTargetNames, Class... annotationClasses) {
192 | for (Class clazz : annotationClasses) {
193 | for (Element element : env.getElementsAnnotatedWith(clazz)) {
194 | if (!SuperficialValidation.validateElement(element)) continue;
195 | try {
196 | parseOnChanged(element, targetClassMap, erasedTargetNames, clazz);
197 | } catch (Exception e) {
198 | logParsingError(element, clazz, e);
199 | }
200 | }
201 | }
202 | }
203 |
204 | private void parseOnChanged(Element element, Map targetClassMap,
205 | Set erasedTargetNames, Class annotationClass) {
206 | TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
207 | BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, enclosingElement, false, false);
208 | TypeMirror mirror = element.asType();
209 | if (!(mirror.getKind() == TypeKind.EXECUTABLE))
210 | return;
211 | String method = element.toString().trim();
212 | String methodName = method.substring(0, method.indexOf("("));
213 | Matcher m = Pattern.compile("\\(([^)]+)\\)").matcher(method);
214 | if (m.find()) {
215 | String[] methodTypes = m.group(1).split(",");
216 | String key = null;
217 | if (annotationClass.equals(OnKStringChanged.class)) {
218 | KStringBinding binding = new KStringBinding(methodName, methodTypes);
219 | key = element.getAnnotation(OnKStringChanged.class).value();
220 | bindingClass.putGeneric(key, binding);
221 | } else if (annotationClass.equals(OnKBooleanChanged.class)) {
222 | KBooleanBinding binding = new KBooleanBinding(methodName, methodTypes);
223 | key = element.getAnnotation(OnKBooleanChanged.class).value();
224 | bindingClass.putGeneric(key, binding);
225 | } else {
226 | error(element, "unknow annotation class type @%s",
227 | annotationClass.getSimpleName());
228 | }
229 | }
230 | erasedTargetNames.add(enclosingElement.toString());
231 | }
232 |
233 | private void parseOnKStringUpdate(Element element, Map targetClassMap,
234 | Set erasedTargetNames) {
235 | TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
236 | BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, enclosingElement, false, false);
237 | TypeMirror mirror = element.asType();
238 | if (!(mirror.getKind() == TypeKind.EXECUTABLE))
239 | return;
240 | String method = element.toString().trim();
241 | String methodName = method.substring(0, method.indexOf("("));
242 | Matcher m = Pattern.compile("\\(([^)]+)\\)").matcher(method);
243 | if (m.find()) {
244 | String[] methodTypes = m.group(1).split(",");
245 | UpdateKStringBinding binding = new UpdateKStringBinding(methodName, methodTypes);
246 | String kstring = element.getAnnotation(OnKStringChanged.class).value();
247 | bindingClass.addKStringUpdateBinding(kstring, binding);
248 | }
249 | erasedTargetNames.add(enclosingElement.toString());
250 | }
251 |
252 | private void parseBinds(Element element, Map targetClassMap,
253 | Set erasedTargetNames) {
254 | Bind[] binds = element.getAnnotation(Binds.class).value();
255 | for (Bind bind : binds) {
256 | String data = bind.data();
257 | int id = bind.id();
258 | BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, (TypeElement) element, false, false);
259 | bindingClass.addDoubleBinding(id, data);
260 | }
261 | }
262 |
263 | private void parseBind(Element element, Map targetClassMap,
264 | Set erasedTargetNames) {
265 | String data = element.getAnnotation(Bind.class).data();
266 | int id = element.getAnnotation(Bind.class).id();
267 | BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, (TypeElement) element, false, false);
268 | bindingClass.addDoubleBinding(id, data);
269 | }
270 |
271 | private void parsePackageName(Element element, Map targetClassMap,
272 | Set erasedTargetNames) {
273 | packageName = ((PackageElement) element).getQualifiedName().toString();
274 | }
275 |
276 | private void parseBindLayout(Element element, Map targetClassMap,
277 | Set erasedTargetNames) {
278 | int id = element.getAnnotation(BindLayout.class).value();
279 | BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, (TypeElement) element, false, false);
280 | bindingClass.setLayoutId(String.valueOf(id));
281 | }
282 |
283 | private void parseLBindLayout(Element element, Map targetClassMap,
284 | Set erasedTargetNames) {
285 | String id = element.getAnnotation(LBindLayout.class).value();
286 | BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, (TypeElement) element, true, false);
287 | bindingClass.setLayoutId(id);
288 | }
289 |
290 | private void parseLBindText(Element element, Map targetClassMap,
291 | Set erasedTargetNames) {
292 | TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
293 |
294 | TypeMirror elementType = element.asType();
295 | if (elementType.getKind() == TypeKind.TYPEVAR) {
296 | TypeVariable typeVariable = (TypeVariable) elementType;
297 | elementType = typeVariable.getUpperBound();
298 | }
299 | // Assemble information on the field.
300 | String[] ids = element.getAnnotation(LBindText.class).value();
301 | BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, enclosingElement, true, false);
302 | for (String id : ids) {
303 | if (bindingClass != null) {
304 | KBindings bindings = bindingClass.getKBindings(id);
305 | if (bindings != null) {
306 | Iterator iterator = bindings.getFieldBindings().iterator();
307 | if (iterator.hasNext()) {
308 | FieldViewBinding existingBinding = iterator.next();
309 | error(element, "Attempt to use @%s for an already bound ID %s on '%s'. (%s.%s)",
310 | LBindText.class.getSimpleName(), id, existingBinding.getName(),
311 | enclosingElement.getQualifiedName(), element.getSimpleName());
312 | return;
313 | }
314 | }
315 | } else {
316 | bindingClass = getOrCreateTargetClass(targetClassMap, enclosingElement, true, false);
317 | }
318 | String name = element.getSimpleName().toString();
319 | TypeName type = TypeName.get(elementType);
320 | boolean required = isRequiredBinding(element);
321 |
322 | FieldViewBinding binding = new FieldViewBinding(name, type, required);
323 | bindingClass.addField(String.valueOf(id), binding);
324 | }
325 |
326 | // Add the type-erased version to the valid binding targets set.
327 | erasedTargetNames.add(enclosingElement.toString());
328 | }
329 |
330 | private void parseBindText(Element element, Map targetClassMap,
331 | Set erasedTargetNames) {
332 | TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
333 |
334 | TypeMirror elementType = element.asType();
335 | if (elementType.getKind() == TypeKind.TYPEVAR) {
336 | TypeVariable typeVariable = (TypeVariable) elementType;
337 | elementType = typeVariable.getUpperBound();
338 | }
339 | // Assemble information on the field.
340 | int[] ids = element.getAnnotation(BindText.class).value();
341 | BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, enclosingElement, false, false);
342 | for (int id : ids) {
343 | if (bindingClass != null) {
344 | KBindings bindings = bindingClass.getKBindings(String.valueOf(id));
345 | if (bindings != null) {
346 | Iterator iterator = bindings.getFieldBindings().iterator();
347 | if (iterator.hasNext()) {
348 | FieldViewBinding existingBinding = iterator.next();
349 | error(element, "Attempt to use @%s for an already bound ID %s on '%s'. (%s.%s)",
350 | BindText.class.getSimpleName(), id, existingBinding.getName(),
351 | enclosingElement.getQualifiedName(), element.getSimpleName());
352 | return;
353 | }
354 | }
355 | } else {
356 | bindingClass = getOrCreateTargetClass(targetClassMap, enclosingElement, false, false);
357 | }
358 | String name = element.getSimpleName().toString();
359 | TypeName type = TypeName.get(elementType);
360 | boolean required = isRequiredBinding(element);
361 |
362 | FieldViewBinding binding = new FieldViewBinding(name, type, required);
363 | bindingClass.addField(String.valueOf(id), binding);
364 | }
365 |
366 | // Add the type-erased version to the valid binding targets set.
367 | erasedTargetNames.add(enclosingElement.toString());
368 | }
369 |
370 | private static boolean isRequiredBinding(Element element) {
371 | return !hasAnnotationWithName(element, NULLABLE_ANNOTATION_NAME);
372 | }
373 |
374 | private static boolean hasAnnotationWithName(Element element, String simpleName) {
375 | for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
376 | String annotationName = mirror.getAnnotationType().asElement().getSimpleName().toString();
377 | if (simpleName.equals(annotationName)) {
378 | return true;
379 | }
380 | }
381 | return false;
382 | }
383 |
384 | private String findParentFqcn(TypeElement typeElement, Set parents) {
385 | TypeMirror type;
386 | while (true) {
387 | type = typeElement.getSuperclass();
388 | if (type.getKind() == TypeKind.NONE) {
389 | return null;
390 | }
391 | typeElement = (TypeElement) ((DeclaredType) type).asElement();
392 | if (parents.contains(typeElement.toString())) {
393 | String packageName = getPackageName(typeElement);
394 | return packageName + "." + getClassName(typeElement, packageName);
395 | }
396 | }
397 | }
398 |
399 | private BindingClass getOrCreateTargetClass(Map targetClassMap,
400 | TypeElement enclosingElement, Boolean isLibrary, Boolean isKotlin) {
401 | BindingClass bindingClass = targetClassMap.get(enclosingElement);
402 | if (bindingClass == null) {
403 | String targetType = enclosingElement.getQualifiedName().toString();
404 | String classPackage = getPackageName(enclosingElement);
405 | String className = getClassName(enclosingElement, classPackage) + BINDING_CLASS_SUFFIX;
406 | bindingClass = new BindingClass(classPackage, className, targetType, packageName, isLibrary, isKotlin);
407 | targetClassMap.put(enclosingElement, bindingClass);
408 | }
409 | return bindingClass;
410 | }
411 |
412 | private String getPackageName(TypeElement type) {
413 | return elementUtils.getPackageOf(type).getQualifiedName().toString();
414 | }
415 |
416 | private static String getClassName(TypeElement type, String packageName) {
417 | int packageLen = packageName.length() + 1;
418 | return type.getQualifiedName().toString().substring(packageLen).replace('.', '$');
419 | }
420 |
421 | private void error(Element element, String message, Object... args) {
422 | if (args.length > 0) {
423 | message = String.format(message, args);
424 | }
425 | processingEnv.getMessager().printMessage(ERROR, message, element);
426 | }
427 |
428 | private void logParsingError(Element element, Class extends Annotation> annotation,
429 | Exception e) {
430 | StringWriter stackTrace = new StringWriter();
431 | e.printStackTrace(new PrintWriter(stackTrace));
432 | error(element, "Unable to parse @%s binding.\n\n%s", annotation.getSimpleName(), stackTrace);
433 | }
434 |
435 | }
436 |
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/UpdateKStringBinding.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler;
2 |
3 | /**
4 | * Created by merlin on 15/12/24.
5 | */
6 | public class UpdateKStringBinding {
7 |
8 | private String methodName;
9 | private String[] parameterTypes;
10 |
11 | public UpdateKStringBinding(String methodName, String[] parameterTypes) {
12 | this.methodName = methodName;
13 | this.parameterTypes = parameterTypes;
14 | }
15 |
16 | public String getMethodName() {
17 | return methodName;
18 | }
19 |
20 | public String[] getParameterTypes() {
21 | return parameterTypes;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/binding/KBindingGeneric.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler.binding;
2 |
3 | import com.squareup.javapoet.MethodSpec;
4 |
5 | /**
6 | * Created by sanvi on 1/8/16.
7 | */
8 | public interface KBindingGeneric {
9 | public void addGenericCode(MethodSpec.Builder result, String key);
10 |
11 | public String getMethodName();
12 |
13 | public String[] getParameterTypes();
14 | }
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/binding/KBooleanBinding.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler.binding;
2 |
3 | import com.squareup.javapoet.ClassName;
4 | import com.squareup.javapoet.MethodSpec;
5 | import com.squareup.javapoet.TypeSpec;
6 |
7 | import javax.lang.model.element.Modifier;
8 |
9 | /**
10 | * Created by merlin on 15/12/24.
11 | */
12 | public class KBooleanBinding implements KBindingGeneric {
13 |
14 | private String methodName;
15 | private String[] parameterTypes;
16 | private static final ClassName ONUPDATELISTENER_KBOOLEAN = ClassName.get("kratos.internal.KBoolean", "OnUpdateListener");
17 | private static final ClassName VIEW = ClassName.get("android.view", "View");
18 |
19 | public KBooleanBinding(String methodName, String[] parameterTypes) {
20 | this.methodName = methodName;
21 | this.parameterTypes = parameterTypes;
22 | }
23 |
24 | @Override
25 | public String getMethodName() {
26 | return methodName;
27 | }
28 |
29 | @Override
30 | public String[] getParameterTypes() {
31 | return parameterTypes;
32 | }
33 |
34 | @Override
35 | public void addGenericCode(MethodSpec.Builder result, String key) {
36 | TypeSpec update = TypeSpec.anonymousClassBuilder("")
37 | .addSuperinterface(ONUPDATELISTENER_KBOOLEAN)
38 | .addMethod(MethodSpec.methodBuilder("update")
39 | .addAnnotation(Override.class)
40 | .addModifiers(Modifier.PUBLIC)
41 | .addParameter(VIEW, "v")
42 | .addParameter(boolean.class, "s")
43 | .returns(void.class)
44 | .addStatement("target.$L(($L)$N, $N)", getMethodName(), getParameterTypes()[0], "v", "s")
45 | .build())
46 | .build();
47 | result.addStatement("target.getData().$L.setOnUpdateListener($L)", key, update);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/kratos-compiler/src/main/java/kratos/compiler/binding/KStringBinding.java:
--------------------------------------------------------------------------------
1 | package kratos.compiler.binding;
2 |
3 | import com.squareup.javapoet.ClassName;
4 | import com.squareup.javapoet.MethodSpec;
5 | import com.squareup.javapoet.TypeSpec;
6 |
7 | import javax.lang.model.element.Modifier;
8 |
9 | /**
10 | * Created by merlin on 15/12/24.
11 | */
12 | public class KStringBinding implements KBindingGeneric {
13 |
14 | private String methodName;
15 | private String[] parameterTypes;
16 | private static final ClassName ONUPDATELISTENER_KSTRING = ClassName.get("kratos.internal.KString", "OnUpdateListener");
17 | private static final ClassName VIEW = ClassName.get("android.view", "View");
18 |
19 | public KStringBinding(String methodName, String[] parameterTypes) {
20 | this.methodName = methodName;
21 | this.parameterTypes = parameterTypes;
22 | }
23 |
24 | @Override
25 | public void addGenericCode(MethodSpec.Builder result, String key) {
26 | TypeSpec update = TypeSpec.anonymousClassBuilder("")
27 | .addSuperinterface(ONUPDATELISTENER_KSTRING)
28 | .addMethod(MethodSpec.methodBuilder("update")
29 | .addAnnotation(Override.class)
30 | .addModifiers(Modifier.PUBLIC)
31 | .addParameter(VIEW, "v")
32 | .addParameter(String.class, "s")
33 | .returns(void.class)
34 | .addStatement("target.$L(($L)$N, $N)", getMethodName(), getParameterTypes()[0], "v", "s")
35 | .build())
36 | .build();
37 | result.addStatement("target.getData().$L.setOnUpdateListener($L)", key, update);
38 |
39 | }
40 |
41 | @Override
42 | public String getMethodName() {
43 | return methodName;
44 | }
45 |
46 | @Override
47 | public String[] getParameterTypes() {
48 | return parameterTypes;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/kratos-sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/kratos-sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'com.neenbedankt.android-apt'
3 |
4 | android {
5 | compileSdkVersion rootProject.ext.compileSdkVersion
6 | buildToolsVersion rootProject.ext.buildToolsVersion
7 |
8 | defaultConfig {
9 | applicationId 'me.ele.kratos'
10 | minSdkVersion rootProject.ext.minSdkVersion
11 | targetSdkVersion rootProject.ext.targetSdkVersion
12 | versionCode 1
13 | versionName "1.0"
14 | }
15 | }
16 |
17 | dependencies {
18 | compile project(':kratos')
19 | apt project(':kratos-compiler')
20 | compile 'com.android.support:appcompat-v7:23.1.1'
21 | }
22 |
--------------------------------------------------------------------------------
/kratos-sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/merlin/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/java/me/ele/kratos_sample/CardSampleActivity.java:
--------------------------------------------------------------------------------
1 | package me.ele.kratos_sample;
2 |
3 | import android.widget.Toast;
4 |
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | import kratos.card.KCardActivity;
8 | import kratos.card.entity.KData;
9 | import kratos.card.event.KOnClickEvent;
10 | import me.ele.kratos_sample.entity.Customer;
11 |
12 | /**
13 | * Created by merlin on 15/12/14.
14 | */
15 | public class CardSampleActivity extends KCardActivity {
16 |
17 | Customer customer = new Customer();
18 |
19 | private void showToast(String text) {
20 | Toast.makeText(CardSampleActivity.this, text, Toast.LENGTH_SHORT).show();
21 | }
22 |
23 | @Override
24 | public void onEventMainThread(@NotNull KOnClickEvent event) {
25 | super.onEventMainThread(event);
26 | switch (event.id) {
27 | case "textCard1":
28 | showToast("Handle click on textCard1!");
29 | break;
30 | }
31 | }
32 |
33 | @Override
34 | public void onFinishRender() {
35 | bind(this, customer);
36 | customer.name.set("Merlin");
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/java/me/ele/kratos_sample/SimpleActivity.java:
--------------------------------------------------------------------------------
1 | package me.ele.kratos_sample;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 |
7 | import kratos.BindText;
8 | import kratos.Kratos;
9 | import kratos.card.utils.ActivityUtils;
10 | import kratos.internal.KString;
11 |
12 | /**
13 | * Created by merlin on 15/12/10.
14 | */
15 | public class SimpleActivity extends Activity {
16 |
17 | private final int CODE_CARD_SAMPLE = 123;
18 |
19 | @BindText({R.id.test_doublebinding_input, R.id.test_doublebinding_presenter})
20 | KString boundData1 = new KString();
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_simple);
26 | Kratos.bind(this);
27 | findViewById(R.id.card_sample).setOnClickListener(new View.OnClickListener() {
28 | @Override
29 | public void onClick(View v) {
30 | ActivityUtils.jump(SimpleActivity.this, CardSampleActivity.class, CODE_CARD_SAMPLE, R.raw.sample);
31 | }
32 | });
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/java/me/ele/kratos_sample/TextCard.java:
--------------------------------------------------------------------------------
1 | package me.ele.kratos_sample;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 | import android.widget.TextView;
6 |
7 | import org.jetbrains.annotations.NotNull;
8 |
9 | import kratos.Bind;
10 | import kratos.BindLayout;
11 | import kratos.Binds;
12 | import kratos.OnKStringChanged;
13 | import kratos.card.KCard;
14 | import me.ele.kratos_sample.entity.KText;
15 |
16 | /**
17 | * Created by merlin on 15/12/17.
18 | */
19 | @BindLayout(R.layout.kcard_text) //@LBindLayout("kcard_text")
20 | @Binds({@Bind(id = R.id.kcard_text_text1, data = "text1"),
21 | @Bind(id = R.id.kcard_text_text2, data = "text2")})
22 | public class TextCard extends KCard {
23 | public TextCard(Context context) {
24 | super(context);
25 | }
26 |
27 | @Override
28 | public void init() {
29 | setOnLinkListener();
30 | }
31 |
32 | @OnKStringChanged("text1")
33 | public void updateText1(@NotNull TextView v, @NotNull String s) {
34 | v.setText(s);
35 | Log.d("TextCard", "custom updater!");
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/java/me/ele/kratos_sample/entity/Customer.java:
--------------------------------------------------------------------------------
1 | package me.ele.kratos_sample.entity;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | import kratos.internal.KString;
7 |
8 | /**
9 | * Created by merlin on 16/2/18.
10 | */
11 | public class Customer implements Parcelable {
12 |
13 | public KString name = new KString();
14 |
15 | @Override
16 | public int describeContents() {
17 | return 0;
18 | }
19 |
20 | @Override
21 | public void writeToParcel(Parcel dest, int flags) {
22 | dest.writeParcelable(this.name, flags);
23 | }
24 |
25 | public Customer() {
26 | }
27 |
28 | protected Customer(Parcel in) {
29 | this.name = in.readParcelable(KString.class.getClassLoader());
30 | }
31 |
32 | public static final Creator CREATOR = new Creator() {
33 | public Customer createFromParcel(Parcel source) {
34 | return new Customer(source);
35 | }
36 |
37 | public Customer[] newArray(int size) {
38 | return new Customer[size];
39 | }
40 | };
41 | }
42 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/java/me/ele/kratos_sample/entity/KText.java:
--------------------------------------------------------------------------------
1 | package me.ele.kratos_sample.entity;
2 |
3 | import kratos.card.entity.KData;
4 | import kratos.internal.KString;
5 |
6 | /**
7 | * Created by merlin on 15/12/17.
8 | */
9 | public class KText extends KData {
10 | public KString text1;
11 | public KString text2;
12 | }
13 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/java/me/ele/kratos_sample/package-info.java:
--------------------------------------------------------------------------------
1 | @PackageName package me.ele.kratos_sample;
2 |
3 | import kratos.PackageName;
--------------------------------------------------------------------------------
/kratos-sample/src/main/res/layout/activity_simple.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
28 |
29 |
38 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/res/layout/kcard_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
25 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/res/raw/sample.json:
--------------------------------------------------------------------------------
1 | {
2 | "header": {
3 | "title": "Card Sample"
4 | },
5 | "body": [
6 | {
7 | "data": {
8 | "text1": "{Customer.name}",
9 | "text2": "this is text2"
10 | },
11 | "type": "me.ele.kratos_sample.TextCard",
12 | "id": "textCard1",
13 | "style": {
14 | "margin_top": 20,
15 | "margin_left": 20,
16 | "margin_right": 20
17 | }
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/kratos-sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ffffff
4 | #0086ff
5 | #444444
6 | #888888
7 |
--------------------------------------------------------------------------------
/kratos-sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Kratos-sample
3 | Jump to Card Sample Activity
4 |
5 |
--------------------------------------------------------------------------------
/kratos/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/kratos/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 |
4 | android {
5 | compileSdkVersion rootProject.ext.compileSdkVersion
6 | buildToolsVersion rootProject.ext.buildToolsVersion
7 |
8 | defaultConfig {
9 | minSdkVersion rootProject.ext.minSdkVersion
10 | }
11 | }
12 |
13 | dependencies {
14 | compile project(':kratos-annotation')
15 | compile 'com.android.support:appcompat-v7:23.1.1'
16 | compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
17 | compile 'de.greenrobot:eventbus:2.4.0'
18 | compile 'com.google.code.gson:gson:2.5'
19 | }
20 | buildscript {
21 | ext.kotlin_version = '1.0.0'
22 | repositories {
23 | mavenCentral()
24 | }
25 | dependencies {
26 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
27 | }
28 | }
29 |
30 |
31 | apply from: rootProject.file('gradle/gradle-mvn-push.gradle')
--------------------------------------------------------------------------------
/kratos/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_ARTIFACT_ID=kratos
2 | POM_NAME=Kratos
3 | POM_PACKAGING=aar
4 |
--------------------------------------------------------------------------------
/kratos/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/merlin/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/kratos/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/kratos/src/main/java/kratos/Kratos.java:
--------------------------------------------------------------------------------
1 | package kratos;
2 |
3 | import android.app.Activity;
4 | import android.support.annotation.NonNull;
5 | import android.util.Log;
6 |
7 | import java.util.LinkedHashMap;
8 | import java.util.Map;
9 |
10 | import kratos.card.KCard;
11 | import kratos.internal.KBinder;
12 | import kratos.internal.KFinder;
13 |
14 | /**
15 | * Created by merlin on 15/12/7.
16 | */
17 | public final class Kratos {
18 | private Kratos() {
19 | }
20 |
21 | private static final String TAG = "Kratos";
22 |
23 | static final Map, KBinder