) data.getParentNode().value.data);
60 | //
61 | //
62 | //
63 | // // Bind the adapter to the Spinner
64 | // spinner.setAdapter(adapter);
65 | //
66 | // // Set a listener to handle item selection
67 | // spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
68 | // @Override
69 | // public void onItemSelected(AdapterView> parent, View view, int position, long id) {
70 | // String selectedItem = parent.getItemAtPosition(position).toString();
71 | // binding.title.setText(selectedItem);
72 | // MainActivity.treeViewStatic.getEditor().setWantEdit(false);
73 | // }
74 | //
75 | // @Override
76 | // public void onNothingSelected(AdapterView> parent) {
77 | // // Handle the case where no item is selected
78 | // }
79 | // });
80 | // }
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/dark/androidbox/types/NodeTypes.java:
--------------------------------------------------------------------------------
1 | package com.dark.androidbox.types;
2 |
3 | public enum NodeTypes {
4 |
5 | CLASS,
6 | METHOD,
7 | VARIABLE,
8 | CONSTRUCTOR;
9 |
10 | NodeTypes() {
11 |
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_node_list_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_node_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_node_view_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_node_view_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/drop_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/drawable/drop_down.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/drawable/settings.png
--------------------------------------------------------------------------------
/app/src/main/res/font/jaldi.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/base_node.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/class_node.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_editor.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
20 |
21 |
28 |
29 |
36 |
37 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/method_node.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/methods_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/node.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nodeview.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
29 |
30 |
31 |
38 |
39 |
40 |
41 |
48 |
49 |
57 |
58 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/terminal_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF000000
4 | #FFFFFFFF
5 | #9C32821B
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 12dp
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/font_certs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - @array/com_google_android_gms_fonts_certs_dev
5 | - @array/com_google_android_gms_fonts_certs_prod
6 |
7 |
8 | -
9 | MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
10 |
11 |
12 |
13 | -
14 | MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1000
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/preloaded_fonts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - @font/jaldi
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | AndroidBox
3 | Node Title
4 | Node ID : 001
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
21 |
22 |
23 |
24 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/data_extraction_rules.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/app/src/test/java/com/dark/androidbox/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.dark.androidbox;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Test;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | alias(libs.plugins.android.application) apply false
4 | }
--------------------------------------------------------------------------------
/codeview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/codeview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdk 34
5 |
6 | defaultConfig {
7 | minSdkVersion 27
8 | targetSdk 34
9 |
10 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
11 | }
12 |
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | compileOptions {
20 | sourceCompatibility JavaVersion.VERSION_1_8
21 | targetCompatibility JavaVersion.VERSION_1_8
22 | }
23 | namespace 'com.amrdeveloper.codeview'
24 | }
25 |
26 | dependencies {
27 | implementation fileTree(dir: "libs", include: ["*.jar"])
28 | implementation libs.appcompat.v161
29 | testImplementation libs.junit
30 | androidTestImplementation libs.ext.junit
31 | androidTestImplementation libs.espresso.core.v351
32 | }
--------------------------------------------------------------------------------
/codeview/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/codeview/consumer-rules.pro
--------------------------------------------------------------------------------
/codeview/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/codeview/src/androidTest/java/com/amrdeveloper/codeview/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.amrdeveloper.codeview;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import android.content.Context;
6 |
7 | import androidx.test.ext.junit.runners.AndroidJUnit4;
8 | import androidx.test.platform.app.InstrumentationRegistry;
9 |
10 | import org.junit.Test;
11 | import org.junit.runner.RunWith;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.amrdeveloper.codeview.test", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/codeview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/codeview/src/main/java/com/amrdeveloper/codeview/Code.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.amrdeveloper.codeview;
26 |
27 | /**
28 | * Interface to represent a different types of code such as keywords or snippets
29 | *
30 | * @since 1.1.0
31 | */
32 | public interface Code {
33 |
34 | /**
35 | * @return The title of code
36 | */
37 | String getCodeTitle();
38 |
39 | /**
40 | * @return The prefix value of the code
41 | */
42 | String getCodePrefix();
43 |
44 | /**
45 | * @return The body of the code to insert it
46 | */
47 | String getCodeBody();
48 | }
49 |
--------------------------------------------------------------------------------
/codeview/src/main/java/com/amrdeveloper/codeview/CodeViewAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.amrdeveloper.codeview;
26 |
27 | import android.content.Context;
28 | import android.view.LayoutInflater;
29 | import android.view.View;
30 | import android.view.ViewGroup;
31 | import android.widget.BaseAdapter;
32 | import android.widget.Filter;
33 | import android.widget.Filterable;
34 | import android.widget.TextView;
35 |
36 | import androidx.annotation.NonNull;
37 |
38 | import java.util.ArrayList;
39 | import java.util.List;
40 |
41 | /**
42 | * Custom base adapter that to use it in CodeView auto complete and snippets feature
43 | *
44 | * CodeViewAdapter supports to take a list of code which can include Keywords and snippets
45 | *
46 | * @since 1.1.0
47 | */
48 | public class CodeViewAdapter extends BaseAdapter implements Filterable {
49 |
50 | private final LayoutInflater layoutInflater;
51 | private final int codeViewLayoutId;
52 | private final int codeViewTextViewId;
53 | private List codeList;
54 | private List originalCodes;
55 | private final Filter codeFilter = new Filter() {
56 | @Override
57 | protected FilterResults performFiltering(CharSequence constraint) {
58 | FilterResults results = new FilterResults();
59 | List suggestions = new ArrayList<>();
60 |
61 | if (originalCodes == null) {
62 | originalCodes = new ArrayList<>(codeList);
63 | }
64 |
65 |
66 | if (constraint == null || constraint.length() == 0) {
67 | results.values = originalCodes;
68 | results.count = originalCodes.size();
69 | } else {
70 | String filterPattern = constraint.toString().toLowerCase().trim();
71 |
72 | for (Code item : originalCodes) {
73 | if (item.getCodePrefix().toLowerCase().contains(filterPattern)) {
74 | suggestions.add(item);
75 | }
76 | }
77 | results.values = suggestions;
78 | results.count = suggestions.size();
79 | }
80 |
81 | return results;
82 | }
83 |
84 | @Override
85 | protected void publishResults(CharSequence constraint, FilterResults results) {
86 | codeList = (List) results.values;
87 | notifyDataSetChanged();
88 | }
89 |
90 | @Override
91 | public CharSequence convertResultToString(Object resultValue) {
92 | return ((Code) resultValue).getCodeBody();
93 | }
94 | };
95 |
96 | public CodeViewAdapter(@NonNull Context context, int resource, int textViewResourceId, @NonNull List codes) {
97 | this.codeList = codes;
98 | this.layoutInflater = LayoutInflater.from(context);
99 | this.codeViewLayoutId = resource;
100 | this.codeViewTextViewId = textViewResourceId;
101 | }
102 |
103 | @Override
104 | public View getView(int position, View convertView, ViewGroup parent) {
105 | if (convertView == null) {
106 | convertView = layoutInflater.inflate(codeViewLayoutId, parent, false);
107 | }
108 |
109 | TextView textViewName = convertView.findViewById(codeViewTextViewId);
110 |
111 | Code currentCode = codeList.get(position);
112 | if (currentCode != null) {
113 | textViewName.setText(currentCode.getCodeTitle());
114 | }
115 |
116 | return convertView;
117 | }
118 |
119 | @Override
120 | public int getCount() {
121 | return codeList.size();
122 | }
123 |
124 | @Override
125 | public Object getItem(int position) {
126 | return codeList.get(position);
127 | }
128 |
129 | @Override
130 | public long getItemId(int position) {
131 | return position;
132 | }
133 |
134 | /**
135 | * Update the current code list with new list
136 | *
137 | * @param newCodeList The new code list
138 | */
139 | public void updateCodes(List newCodeList) {
140 | codeList.clear();
141 | codeList.addAll(newCodeList);
142 | notifyDataSetChanged();
143 | }
144 |
145 | /**
146 | * Clear the current code list and notify data set changed
147 | */
148 | public void clearCodes() {
149 | codeList.clear();
150 | notifyDataSetChanged();
151 | }
152 |
153 | @Override
154 | public Filter getFilter() {
155 | return codeFilter;
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/codeview/src/main/java/com/amrdeveloper/codeview/Findable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.amrdeveloper.codeview;
26 |
27 | import java.util.List;
28 |
29 | /**
30 | * Interface used to support find and match features
31 | *
32 | * @since 1.2.1
33 | */
34 | public interface Findable {
35 |
36 | /**
37 | * Find all the the tokens that matches the regex string and save them on a list
38 | *
39 | * @param regex The regex used to find tokens
40 | * @return List of the matches Tokens
41 | */
42 | List findMatches(String regex);
43 |
44 | /**
45 | * Highlight and return the next token
46 | *
47 | * @return The next matched token, {@code null} if not found
48 | */
49 | Token findNextMatch();
50 |
51 | /**
52 | * Highlight and return the previous token
53 | *
54 | * @return The previous matched token, {@code null} if not found
55 | */
56 | Token findPrevMatch();
57 |
58 | /**
59 | * Clear all the matches tokens
60 | */
61 | void clearMatches();
62 | }
63 |
--------------------------------------------------------------------------------
/codeview/src/main/java/com/amrdeveloper/codeview/Keyword.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.amrdeveloper.codeview;
26 |
27 | /**
28 | * Keyword is used to save information to provide auto complete features
29 | *
30 | * @since 1.1.0
31 | */
32 | public class Keyword implements Code {
33 |
34 | private final String title;
35 | private final String prefix;
36 |
37 | public Keyword(String title) {
38 | this.title = title;
39 | this.prefix = title;
40 | }
41 |
42 | public Keyword(String title, String prefix) {
43 | this.title = title;
44 | this.prefix = prefix;
45 | }
46 |
47 | @Override
48 | public String getCodeTitle() {
49 | return title;
50 | }
51 |
52 | @Override
53 | public String getCodePrefix() {
54 | return prefix;
55 | }
56 |
57 | @Override
58 | public String getCodeBody() {
59 | return prefix;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/codeview/src/main/java/com/amrdeveloper/codeview/KeywordTokenizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.amrdeveloper.codeview;
26 |
27 | import android.widget.MultiAutoCompleteTextView;
28 |
29 | /**
30 | * The default tokenizer that used for CodeView auto complete feature
31 | */
32 | public class KeywordTokenizer implements MultiAutoCompleteTextView.Tokenizer {
33 |
34 | @Override
35 | public int findTokenStart(CharSequence charSequence, int cursor) {
36 | // All text until the current cursor position
37 | final String sequenceStr = charSequence.toString().substring(0, cursor);
38 |
39 | // Iterate until find space, newline or (, starting from the current cursor position
40 | for (int i = cursor - 1; i >= 0; i--) {
41 | // Return the next position after the prefix character
42 | final char c = sequenceStr.charAt(i);
43 | if (c == ' ' || c == '\n' || c == '(') return i + 1;
44 | }
45 |
46 | // If no prefix character found then token start is the start of text
47 | return 0;
48 | }
49 |
50 | @Override
51 | public int findTokenEnd(CharSequence charSequence, int cursor) {
52 | return charSequence.length();
53 | }
54 |
55 | @Override
56 | public CharSequence terminateToken(CharSequence charSequence) {
57 | return charSequence;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/codeview/src/main/java/com/amrdeveloper/codeview/Replaceable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.amrdeveloper.codeview;
26 |
27 | /**
28 | * Interface used to support find and replacement feature
29 | *
30 | * @since 1.2.1
31 | */
32 | public interface Replaceable {
33 |
34 | /**
35 | * Replace the first string that matched by the regex with new string
36 | *
37 | * @param regex regex Regex used to find the first target string
38 | * @param replacement Text to replace that matched string by it
39 | */
40 | void replaceFirstMatch(String regex, String replacement);
41 |
42 | /**
43 | * Replace all strings that matched by the regex with new string
44 | *
45 | * @param regex Regex used to find the target string
46 | * @param replacement Text to replace that matched string by it
47 | */
48 | void replaceAllMatches(String regex, String replacement);
49 | }
50 |
--------------------------------------------------------------------------------
/codeview/src/main/java/com/amrdeveloper/codeview/Snippet.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.amrdeveloper.codeview;
26 |
27 | /**
28 | * Snippet is used to save information to provide snippets features
29 | *
30 | * @since 1.1.0
31 | */
32 | public class Snippet implements Code {
33 |
34 | private final String title;
35 | private final String prefix;
36 | private final String body;
37 |
38 | public Snippet(String title, String body) {
39 | this.title = title;
40 | this.prefix = title;
41 | this.body = body;
42 | }
43 |
44 | public Snippet(String title, String prefix, String body) {
45 | this.title = title;
46 | this.prefix = prefix;
47 | this.body = body;
48 | }
49 |
50 | @Override
51 | public String getCodeTitle() {
52 | return title;
53 | }
54 |
55 | @Override
56 | public String getCodePrefix() {
57 | return prefix;
58 | }
59 |
60 | @Override
61 | public String getCodeBody() {
62 | return body;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/codeview/src/main/java/com/amrdeveloper/codeview/Token.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2020 AmrDeveloper (Amr Hesham)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.amrdeveloper.codeview;
26 |
27 | /**
28 | * Token is class to represent a position on the source code
29 | *
30 | * @since 1.2.1
31 | */
32 | public class Token {
33 |
34 | private final int start;
35 | private final int end;
36 |
37 | public Token(int start, int end) {
38 | this.start = start;
39 | this.end = end;
40 | }
41 |
42 | /**
43 | * @return The start position of the current token in source code
44 | */
45 | public int getStart() {
46 | return start;
47 | }
48 |
49 | /**
50 | * @return The end position of the current token in source code
51 | */
52 | public int getEnd() {
53 | return end;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/codeview/src/test/java/com/amrdeveloper/codeview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.amrdeveloper.codeview;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Test;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. For more details, visit
12 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Enables namespacing of each library's R class so that its R class includes only the
19 | # resources declared in the library itself and none from the library's dependencies,
20 | # thereby reducing the size of the R class for that library
21 | android.nonTransitiveRClass=true
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | agp = "8.7.3"
3 | androidCodeView = "1.0.4"
4 | androidxJunit = "1.2.1"
5 | appcompatVersion = "1.7.0"
6 | dynamicanimation = "1.0.0"
7 | espressoCoreVersion = "3.6.1"
8 | janino = "3.1.9"
9 | javaparserCore = "3.26.2"
10 | junit = "4.13.2"
11 | junitVersion = "1.2.1"
12 | espressoCore = "3.6.1"
13 | appcompat = "1.7.0"
14 | material = "1.12.0"
15 | activity = "1.9.2"
16 | constraintlayout = "2.1.4"
17 | materialVersion = "1.12.0"
18 |
19 | [libraries]
20 | android-code-view = { module = "com.github.chen0040:android-code-view", version.ref = "androidCodeView" }
21 | appcompat-v161 = { module = "androidx.appcompat:appcompat", version.ref = "appcompatVersion" }
22 | dynamicanimation = { module = "androidx.dynamicanimation:dynamicanimation", version.ref = "dynamicanimation" }
23 | espresso-core-v351 = { module = "androidx.test.espresso:espresso-core", version.ref = "espressoCoreVersion" }
24 | janino = { module = "org.codehaus.janino:janino", version.ref = "janino" }
25 | javaparser-core = { module = "com.github.javaparser:javaparser-core", version.ref = "javaparserCore" }
26 | junit = { group = "junit", name = "junit", version.ref = "junit" }
27 | ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
28 | espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
29 | appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
30 | junit-v115 = { module = "androidx.test.ext:junit", version.ref = "androidxJunit" }
31 | material = { group = "com.google.android.material", name = "material", version.ref = "material" }
32 | activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
33 | constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
34 | material-v1110 = { module = "com.google.android.material:material", version.ref = "materialVersion" }
35 |
36 | [plugins]
37 | android-application = { id = "com.android.application", version.ref = "agp" }
38 |
39 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Sep 06 17:00:14 IST 2024
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/node/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/node/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | }
4 |
5 | android {
6 | compileSdk 34
7 |
8 | defaultConfig {
9 | minSdk 27
10 | targetSdk 34
11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
12 | }
13 |
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | compileOptions {
21 | sourceCompatibility JavaVersion.VERSION_1_8
22 | targetCompatibility JavaVersion.VERSION_1_8
23 | }
24 | namespace 'com.gyso.treeview'
25 | }
26 |
27 | dependencies {
28 | implementation fileTree(dir: "libs", include: ["*.jar"])
29 | implementation libs.appcompat.v161
30 | implementation libs.material.v1110
31 | testImplementation libs.junit
32 | androidTestImplementation libs.junit.v115
33 | androidTestImplementation libs.espresso.core.v351
34 | implementation libs.dynamicanimation
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/node/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Siddhesh2377/AndroidBox/4cc1be686a75fa46cda216f4e3b74e04e6d4a2fc/node/consumer-rules.pro
--------------------------------------------------------------------------------
/node/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/node/src/androidTest/java/com/gyso/treeview/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.gyso.treeview.test", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/node/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/adapter/DrawInfo.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.adapter;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Paint;
5 | import android.graphics.Path;
6 | import android.graphics.Point;
7 | import android.graphics.PointF;
8 |
9 | /**
10 | * @Author: 怪兽N
11 | * @Time: 2021/5/7 21:15
12 | * @Email: 674149099@qq.com
13 | * @WeChat: guaishouN
14 | * @Describe:
15 | * In order to draw a custom line, there are too many draw info should be passed.
16 | * So, this class is estimated to package the draw element that need to draw a colorful line between two nodes.
17 | */
18 | public class DrawInfo {
19 | /**
20 | * canvas
21 | */
22 | private Canvas canvas;
23 | /**
24 | * node from view
25 | */
26 | private TreeViewHolder> fromHolder;
27 | /**
28 | * node to view
29 | */
30 | private TreeViewHolder> toHolder;
31 | /**
32 | * paint, before use you should reset
33 | */
34 | private Paint paint;
35 | /**
36 | * path, before use you should reset
37 | */
38 | private Path path;
39 | /**
40 | * space between Peer and Peer, means child and child
41 | */
42 | private int spacePeerToPeer;
43 | /**
44 | * space between parent and child
45 | */
46 | private int spaceParentToChild;
47 | /**
48 | * viewport width
49 | */
50 | private int windowWidth;
51 | /**
52 | * viewport height
53 | */
54 | private int windowHeight;
55 |
56 | public Canvas getCanvas() {
57 | return canvas;
58 | }
59 |
60 | public void setCanvas(Canvas canvas) {
61 | this.canvas = canvas;
62 | }
63 |
64 | public TreeViewHolder> getFromHolder() {
65 | return fromHolder;
66 | }
67 |
68 | public void setFromHolder(TreeViewHolder> fromHolder) {
69 | this.fromHolder = fromHolder;
70 | }
71 |
72 | public TreeViewHolder> getToHolder() {
73 | return toHolder;
74 | }
75 |
76 | public void setToHolder(TreeViewHolder> toHolder) {
77 | this.toHolder = toHolder;
78 | }
79 |
80 | public Paint getPaint() {
81 | return paint;
82 | }
83 |
84 | public void setPaint(Paint paint) {
85 | this.paint = paint;
86 | }
87 |
88 | public Path getPath() {
89 | return path;
90 | }
91 |
92 | public void setPath(Path path) {
93 | this.path = path;
94 | }
95 |
96 | public void setSpace(int spacePeerToPeer,int spaceParentToChild) {
97 | this.spacePeerToPeer = spacePeerToPeer;
98 | this.spaceParentToChild = spaceParentToChild;
99 | }
100 |
101 | public int getSpacePeerToPeer() {
102 | return spacePeerToPeer;
103 | }
104 |
105 | public int getSpaceParentToChild() {
106 | return spaceParentToChild;
107 | }
108 |
109 | public int getWindowWidth() {
110 | return windowWidth;
111 | }
112 |
113 | public void setWindowWidth(int windowWidth) {
114 | this.windowWidth = windowWidth;
115 | }
116 |
117 | public int getWindowHeight() {
118 | return windowHeight;
119 | }
120 |
121 | public void setWindowHeight(int windowHeight) {
122 | this.windowHeight = windowHeight;
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/adapter/TreeViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.adapter;
2 |
3 | import android.view.ViewGroup;
4 |
5 | import androidx.annotation.NonNull;
6 |
7 | import com.gyso.treeview.line.BaseLine;
8 | import com.gyso.treeview.listener.TreeViewNotifier;
9 | import com.gyso.treeview.model.NodeModel;
10 | import com.gyso.treeview.model.TreeModel;
11 |
12 | /**
13 | * @Author: 怪兽N
14 | * @Time: 2021/4/23 15:19
15 | * @Email: 674149099@qq.com
16 | * @WeChat: guaishouN
17 | * @Describe:
18 | * The view adapter for the {@link com.gyso.treeview.TreeViewContainer}
19 | */
20 | public abstract class TreeViewAdapter {
21 | private TreeViewNotifier notifier;
22 | private TreeModel treeModel;
23 |
24 | public void setTreeModel(TreeModel treeModel) {
25 | this.treeModel = treeModel;
26 | notifyDataSetChange();
27 | }
28 |
29 | /**
30 | * Get tree model
31 | * @return tree model
32 | */
33 | public TreeModel getTreeModel(){
34 | return treeModel;
35 | }
36 |
37 | /**
38 | * For create view holder by your self
39 | * @param viewGroup parent
40 | * @param model node
41 | * @return holder
42 | */
43 | public abstract TreeViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, NodeModel model);
44 |
45 | /**
46 | * when bind the holder, set up you view
47 | * @param holder holder
48 | */
49 | public abstract void onBindViewHolder(@NonNull TreeViewHolder holder);
50 |
51 | /**
52 | * Draw line between node and node by you decision.
53 | * If you return an BaseLine, line will be draw by the return one instead of TreeViewLayoutManager's.
54 | * @param drawInfo provides all you need to draw you line
55 | * @return the line draw you want to use for different nodes
56 | */
57 | public abstract BaseLine onDrawLine(DrawInfo drawInfo);
58 |
59 | /**
60 | * for recycling holder, exactly for recycling views
61 | * @param node
62 | * @return
63 | */
64 | public int getHolderType(NodeModel> node){
65 | return 0;
66 | }
67 |
68 | public void setNotifier(TreeViewNotifier notifier){
69 | this.notifier = notifier;
70 | }
71 |
72 | public void notifyDataSetChange(){
73 | if(notifier!=null){
74 | notifier.onDataSetChange();
75 | }
76 | }
77 |
78 | public void notifyItemViewChange(NodeModel node){
79 | if(notifier!=null){
80 | notifier.onItemViewChange(node);
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/adapter/TreeViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.adapter;
2 |
3 | import android.view.View;
4 |
5 | import androidx.annotation.NonNull;
6 |
7 | import com.gyso.treeview.layout.TreeLayoutManager;
8 | import com.gyso.treeview.model.NodeModel;
9 |
10 | /**
11 | * @Author: 怪兽N
12 | * @Time: 2021/4/23 15:20
13 | * @Email: 674149099@qq.com
14 | * @WeChat: guaishouN
15 | * @Describe:
16 | * View holder
17 | */
18 | public class TreeViewHolder {
19 | private int holderLayoutType = TreeLayoutManager.LAYOUT_TYPE_NONE;
20 | private View view;
21 | private NodeModel node;
22 | public TreeViewHolder(View view, @NonNull NodeModel node) {
23 | this.view = view;
24 | this.node = node;
25 | }
26 |
27 | public NodeModel getNode() {
28 | return node;
29 | }
30 |
31 | public View getView() {
32 | return view;
33 | }
34 |
35 | public void setView(View view) {
36 | this.view = view;
37 | }
38 |
39 | public void setNode(NodeModel> node) {
40 | this.node = (NodeModel)node;
41 | }
42 |
43 | public int getHolderLayoutType() {
44 | return holderLayoutType;
45 | }
46 |
47 | public void setHolderLayoutType(int holderLayoutType) {
48 | this.holderLayoutType = holderLayoutType;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/algorithm/force/FLink.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.algorithm.force;
2 |
3 | /**
4 | * Created by Z.Pan on 2016/10/9.
5 | */
6 |
7 | public class FLink {
8 |
9 | FNode source;
10 | FNode target;
11 | private String text;
12 |
13 | public FLink(FNode source, FNode target) {
14 | this.source = source;
15 | this.target = target;
16 | }
17 |
18 | public String getText() {
19 | return text;
20 | }
21 |
22 | public void setText(String text) {
23 | this.text = text;
24 | }
25 |
26 | double getNodeDistance() {
27 | float dx = source.x - target.x;
28 | float dy = source.y - target.y;
29 | return Math.sqrt(dx * dx + dy * dy);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/algorithm/force/FNode.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.algorithm.force;
2 |
3 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
4 | import static java.lang.annotation.RetentionPolicy.SOURCE;
5 |
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.Target;
8 |
9 | /**
10 | * 力导向图中显示的节点。
11 | *
12 | * Created by Z.Pan on 2016/10/8.
13 | */
14 |
15 | public class FNode {
16 |
17 | /** 根节点级别 */
18 | public static final int ROOT_NODE_LEVEL = 0;
19 |
20 | static final short DRAG_START = 2;
21 | static final short DRAG = 4;
22 | static final short DRAG_END = 6;
23 |
24 | private String text; // 节点显示的内容
25 | private Object obj; // 用来携带其他数据,如:该节点对应的数据实体 Bean,或数据库中的 _id
26 | private int level; // 级别
27 |
28 | public float x, y; // 当前坐标
29 | float px, py; // 前一个状态的坐标
30 | int weight; // 根据子节点自动计算,weight 越大,该节点越不容易被拖动
31 |
32 | private float radius = 50f; // 节点半径
33 | private short state; // 节点状态,该状态决定了是否处于稳定状态
34 |
35 | public FNode(String text) {
36 | this(text, 50f, ROOT_NODE_LEVEL);
37 | }
38 |
39 | public FNode(String text, float radius, int level) {
40 | this.text = text;
41 | this.radius = radius;
42 | this.level = level;
43 | x=y=-1f;
44 | weight=1;
45 | }
46 |
47 | public void setObj(Object obj) {
48 | this.obj = obj;
49 | }
50 |
51 | public String getText() {
52 | return text;
53 | }
54 |
55 | public Object getObj() {
56 | return obj;
57 | }
58 |
59 | public int getLevel() {
60 | return level;
61 | }
62 |
63 | public void setLevel(int level) {
64 | this.level = level;
65 | }
66 |
67 | float getRadius() {
68 | return radius;
69 | }
70 |
71 | boolean isRootNode() {
72 | return level == ROOT_NODE_LEVEL;
73 | }
74 |
75 | /**
76 | * 给定一个坐标 (x, y),判断该坐标是否在节点所在范围内。用来判断是否点击了该节点。
77 | * @param x x坐标
78 | * @param y y坐标
79 | * @param scale 缩放比例
80 | * @return true 表示 (x, y) 在该节点内部
81 | */
82 | boolean isInside(float x, float y, float scale) {
83 | float left = (this.x - radius) * scale;
84 | float top = (this.y - radius) * scale;
85 | float right = (this.x + radius) * scale;
86 | float bottom = (this.y + radius) * scale;
87 | return x >= left && x <= right && y >= top && y <= bottom;
88 | }
89 |
90 | boolean isStable() {
91 | return state != 0;
92 | }
93 |
94 | /**
95 | * 设置节点的状态是否正在被手指拖动。
96 | * @param state {@linkplain #DRAG_START} 开始拖动;{@linkplain #DRAG_END} 结束拖动。
97 | */
98 | void setDragState(@State short state) {
99 | switch (state) {
100 | case DRAG_START:
101 | this.state |= state;
102 | break;
103 | case DRAG_END:
104 | this.state &= ~state;
105 | break;
106 | }
107 | }
108 |
109 | @ShortDef({DRAG_START, DRAG, DRAG_END})
110 | @Retention(SOURCE)
111 | public @interface State {}
112 |
113 | @Retention(SOURCE)
114 | @Target({ANNOTATION_TYPE})
115 | public @interface ShortDef {
116 | short[] value() default {};
117 | boolean flag() default false;
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/algorithm/force/ForceListener.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.algorithm.force;
2 |
3 | /**
4 | * Created by Z.Pan on 2016/10/10.
5 | */
6 |
7 | public interface ForceListener {
8 | void refresh();
9 | }
10 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/algorithm/force/QuadTree.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.algorithm.force;
2 |
3 | /**
4 | * Created by Z.Pan on 2016/10/10.
5 | */
6 | class QuadTree {
7 | private static final float NULL = -1;
8 |
9 | static class Node {
10 | boolean isLeaf;
11 | Node[] children;
12 | FNode point;
13 | float x = NULL;
14 | float y = NULL;
15 |
16 | float charge;
17 | float pointCharge;
18 | float cx, cy;
19 |
20 | Node(boolean isLeaf, Node[] children, FNode point, float x, float y) {
21 | this.isLeaf = isLeaf;
22 | this.children = children;
23 | this.point = point;
24 | this.x = x;
25 | this.y = y;
26 | }
27 | }
28 |
29 | Node root;
30 |
31 | QuadTree() {
32 | root = generateNode();
33 | }
34 |
35 | void insert(Node n, FNode node, float minX, float minY, float maxX, float maxY) {
36 | if (Float.isNaN(minX) || Float.isNaN(minY) || Float.isNaN(maxX) || Float.isNaN(maxY)) {
37 | return;
38 | }
39 | if (n.isLeaf) {
40 | float nx = n.x;
41 | float ny = n.y;
42 |
43 | if (nx != NULL) {
44 | if (Math.abs(nx - node.x) + Math.abs(ny - node.y) < 0.01) {
45 | insertChild(n, node, minX, minY, maxX, maxY);
46 | } else {
47 | FNode nPoint = n.point;
48 | n.x = n.y = NULL;
49 | n.point = null;
50 | insertChild(n, nPoint, minX, minY, maxX, maxY);
51 | insertChild(n, node, minX, minY, maxX, maxY);
52 | }
53 | } else {
54 | n.x = node.x;
55 | n.y = node.y;
56 | n.point = node;
57 | }
58 | } else {
59 | insertChild(n, node, minX, minY, maxX, maxY);
60 | }
61 | }
62 |
63 | private void insertChild(Node n, FNode node, float minX, float minY, float maxX, float maxY) {
64 | float sx = (minX + maxX) * 0.5f;
65 | float sy = (minY + maxY) * 0.5f;
66 | boolean isRight = node.x >= sx;
67 | boolean isBottom = node.y >= sy;
68 | int right = isRight ? 1 : 0;
69 | int bottom = isBottom ? 1 : 0;
70 | int i = (bottom << 1) + right;
71 |
72 | n.isLeaf = false;
73 | if (n.children[i] == null) {
74 | Node nod = generateNode();
75 | n.children[i] = nod;
76 | n = nod;
77 | } else {
78 | n = n.children[i];
79 | }
80 |
81 | if (isRight) {
82 | minX = sx;
83 | } else {
84 | maxX = sx;
85 | }
86 |
87 | if (isBottom) {
88 | minY = sy;
89 | } else {
90 | maxY = sy;
91 | }
92 |
93 | insert(n, node, minX, minY, maxX, maxY);
94 | }
95 |
96 | /** generate a leaf node for quad tree. */
97 | private Node generateNode() {
98 | return new Node(true, new Node[4], null, NULL, NULL);
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/algorithm/ring/RingForSimple.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.algorithm.ring;
2 |
3 | import android.graphics.Point;
4 | import android.graphics.PointF;
5 | import android.util.SparseIntArray;
6 | import com.gyso.treeview.model.ITraversal;
7 | import com.gyso.treeview.model.NodeModel;
8 | import com.gyso.treeview.model.TreeModel;
9 | import com.gyso.treeview.util.TreeViewLog;
10 |
11 | import java.util.ArrayDeque;
12 | import java.util.Deque;
13 | import java.util.HashMap;
14 | import java.util.LinkedList;
15 | import java.util.Map;
16 | import java.util.concurrent.atomic.AtomicInteger;
17 |
18 | public class RingForSimple {
19 | public static final String TAG = RingForSimple.class.getSimpleName();
20 | private final static Map, RingForSimple> RING_MAP = new HashMap<>();
21 | private final PointF center = new PointF();
22 | private final TreeModel> model;
23 | private final Map, PointF> nodeModelPointFMap = new HashMap<>();
24 | private final Map, Double> nodeModelAngleMap = new HashMap<>();
25 | protected SparseIntArray floorStart = new SparseIntArray(200);
26 | private final AtomicInteger multi = new AtomicInteger(1);
27 | private int maxDeep;
28 | private final Map, Point> nodeWidthMap = new HashMap<>();
29 | private RingForSimple(TreeModel> model) {
30 | this.model = model;
31 | }
32 | public static RingForSimple getInstance(TreeModel> model){
33 | if(model==null){
34 | return null;
35 | }
36 | RingForSimple ring = RING_MAP.get(model);
37 | if(ring==null){
38 | ring = new RingForSimple(model);
39 | RING_MAP.put(model,ring);
40 | }
41 | return ring;
42 | }
43 | public RingForSimple setCenter(float x, float y) {
44 | center.x = x;
45 | center.y = y;
46 | TreeViewLog.e(TAG,"center["+x+","+y+"]");
47 | return this;
48 | }
49 |
50 | public RingForSimple setFloorStart(SparseIntArray floorStart) {
51 | this.floorStart = floorStart;
52 | return this;
53 | }
54 |
55 | public void reconstruction(TreeModel> mTreeModel) {
56 | TreeViewLog.e(TAG,"reconstruction start");
57 | nodeWidthMap.clear();
58 | Deque deque = new ArrayDeque<>();
59 | NodeModel rootNode = mTreeModel.getRootNode();
60 | deque.add(rootNode);
61 | SparseIntArray deepSum = new SparseIntArray();
62 | //calculate base deep
63 | while (!deque.isEmpty()) {
64 | NodeModel cur = deque.poll();
65 | if(cur==null){
66 | return;
67 | }
68 | cur.deep = deepSum.get(cur.floor,0);
69 | record(cur);
70 | NodeModel tmp = cur.parentNode;
71 | while (!tmp.equals(rootNode)){
72 | record(tmp);
73 | tmp = tmp.parentNode;
74 | }
75 | deepSum.put(cur.floor, cur.deep+1);
76 | LinkedList childNodes = cur.getChildNodes();
77 | if (childNodes.size() > 0) {
78 | deque.addAll(childNodes);
79 | }
80 | }
81 | }
82 |
83 | private void record(NodeModel node) {
84 | if (node == null) {
85 | return;
86 | }
87 | Point point = nodeWidthMap.get(node);
88 | if(point==null){
89 | point = new Point();
90 | nodeWidthMap.put(node, point);
91 | }
92 | maxDeep = Math.max(node.deep, maxDeep);
93 | point.x= Math.max(node.deep, point.x);
94 | point.y = Math.min(node.deep, point.y);
95 | }
96 |
97 | public Map, PointF> genPositions() {
98 | if (model == null) {
99 | return null;
100 | }
101 | NodeModel> rootNode = model.getRootNode();
102 | nodeModelPointFMap.clear();
103 | nodeModelPointFMap.put(rootNode, new PointF(center.y, center.x));
104 | int leafCount = maxDeep;
105 | LinkedList extends NodeModel>> rootNodeChildNodes = rootNode.getChildNodes();
106 | if(leafCount == 0 || rootNodeChildNodes.isEmpty()){
107 | return nodeModelPointFMap;
108 | }
109 |
110 | //keep in pie center
111 | double pieAngle = 2f*Math.PI / leafCount;
112 |
113 | //doTraversalNodes
114 | model.doTraversalNodes((ITraversal>) next -> {
115 | if(next.equals(rootNode)){
116 | return;
117 | }
118 | PointF pointF = new PointF();
119 | int deep = next.deep;
120 | int floor = next.floor;
121 | double angle = pieAngle * deep;
122 | LinkedList extends NodeModel>> childNodes = next.getChildNodes();
123 | if(!childNodes.isEmpty()){
124 | Point point = nodeWidthMap.get(next);
125 | int count = point.x-point.y;
126 | if(count>=2){
127 | double d = pieAngle*(count-1)/2f;
128 | angle += d;
129 | }
130 | }
131 | float radius = floorStart.get(floor);
132 | TreeViewLog.e(TAG,"radius["+radius+"]angle["+angle+"]");
133 | pointF.x = (float) (radius * Math.sin(angle))+center.y;
134 | pointF.y = (float) (radius * Math.cos(angle))+center.x;
135 | nodeModelPointFMap.put(next, pointF);
136 | nodeModelAngleMap.put(next,angle);
137 | });
138 | return nodeModelPointFMap;
139 | }
140 | }
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/algorithm/table/TableKey.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.algorithm.table;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 |
6 | public class TableKey {
7 | public int floor;
8 | public int deep;
9 |
10 | public TableKey(int floor, int deep) {
11 | this.floor = floor;
12 | this.deep = deep;
13 | }
14 |
15 | @Override
16 | public int hashCode() {
17 | return floor;
18 | }
19 |
20 | @Override
21 | public boolean equals(@Nullable Object obj) {
22 | if(obj instanceof TableKey){
23 | TableKey o = (TableKey)obj;
24 | return floor == o.floor && deep==o.deep;
25 | }
26 | return false;
27 | }
28 |
29 | @NonNull
30 | @Override
31 | public String toString() {
32 | return "["+floor+","+deep+"]";
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/algorithm/tight_table/TightTable.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.algorithm.tight_table;
2 |
3 | public class TightTable {
4 | public void tightTable(){
5 |
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/cache_pool/HolderPool.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.cache_pool;
2 |
3 | import android.graphics.PointF;
4 |
5 | import androidx.core.util.Pools;
6 |
7 | import com.gyso.treeview.adapter.TreeViewHolder;
8 |
9 | /**
10 | * @Author: 怪兽N
11 | * @Time: 2021/6/10 14:37
12 | * @Email: 674149099@qq.com
13 | * @WeChat: guaishouN
14 | * @Describe:
15 | * * Holder pool. {@link com.gyso.treeview.adapter.TreeViewHolder}
16 | * * NOTE: not safe pool, please just use in UI thread
17 | */
18 | public class HolderPool extends Pools.SimplePool> {
19 | public static final int DEFAULT_SIZE = 30;
20 | private final static HolderPool POOL = new HolderPool();
21 | /**
22 | * Creates a new instance.
23 | */
24 | public HolderPool() {
25 | super(DEFAULT_SIZE);
26 | }
27 |
28 | public TreeViewHolder> obtain(){
29 | return POOL.acquire();
30 | }
31 |
32 | public void free(TreeViewHolder> holder){
33 | try {
34 | POOL.release(holder);
35 | }catch (IllegalStateException e){
36 | e.printStackTrace();
37 | }
38 |
39 | }
40 |
41 | public static void freeAll(){
42 | while (POOL.acquire()!=null);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/cache_pool/PointPool.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.cache_pool;
2 |
3 | import android.graphics.PointF;
4 |
5 | import androidx.core.util.Pools;
6 |
7 | /**
8 | * @Author: 怪兽N
9 | * @Time: 2021/5/8 9:56
10 | * @Email: 674149099@qq.com
11 | * @WeChat: guaishouN
12 | * @Describe:
13 | * Point pool.
14 | * NOTE: not safe pool, please just use in UI thread
15 | */
16 | public class PointPool extends Pools.SimplePool {
17 | public static final int DEFAULT_SIZE = 20;
18 | private final static PointPool POOL = new PointPool();
19 | /**
20 | * Creates a new instance.
21 | */
22 | private PointPool() {
23 | super(DEFAULT_SIZE);
24 | }
25 |
26 | public static PointF obtain(){
27 | PointF point = POOL.acquire();
28 | if(point==null){
29 | return new PointF();
30 | }
31 | return point;
32 | }
33 |
34 | public static PointF obtain(float x, float y){
35 | PointF point = POOL.acquire();
36 | if(point==null){
37 | return new PointF(x,y);
38 | }
39 | point.set(x,y);
40 | return point;
41 | }
42 |
43 | public static void free(PointF p){
44 | POOL.release(p);
45 | }
46 |
47 | public static void freeAll(){
48 | while (POOL.acquire()!=null);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/layout/BoxLeftTreeLayoutManager.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.layout;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import com.gyso.treeview.TreeViewContainer;
7 | import com.gyso.treeview.adapter.TreeViewHolder;
8 | import com.gyso.treeview.line.BaseLine;
9 | import com.gyso.treeview.model.ITraversal;
10 | import com.gyso.treeview.model.NodeModel;
11 | import com.gyso.treeview.model.TreeModel;
12 | import com.gyso.treeview.util.ViewBox;
13 |
14 | public class BoxLeftTreeLayoutManager extends BoxRightTreeLayoutManager{
15 | private static final String TAG = BoxLeftTreeLayoutManager.class.getSimpleName();
16 | private boolean isJustCalculate;
17 | public BoxLeftTreeLayoutManager(Context context, int spaceParentToChild, int spacePeerToPeer, BaseLine baseline) {
18 | super(context, spaceParentToChild, spacePeerToPeer, baseline);
19 | }
20 |
21 | @Override
22 | public int getTreeLayoutType() {
23 | return LAYOUT_TYPE_HORIZON_LEFT;
24 | }
25 |
26 | @Override
27 | public void performLayout(final TreeViewContainer treeViewContainer) {
28 | isJustCalculate = true;
29 | super.performLayout(treeViewContainer);
30 | isJustCalculate = false;
31 | final TreeModel> mTreeModel = treeViewContainer.getTreeModel();
32 | if (mTreeModel != null) {
33 | final int cx = fixedViewBox.getWidth()/2;
34 | mTreeModel.doTraversalNodes(new ITraversal>() {
35 | @Override
36 | public void next(NodeModel> next) {
37 | mirrorByCx(next,treeViewContainer,cx);
38 | }
39 | @Override
40 | public void finish() {
41 | onManagerFinishLayoutAllNodes(treeViewContainer);
42 | }
43 | });
44 | }
45 | }
46 |
47 | private void mirrorByCx(NodeModel> currentNode, TreeViewContainer treeViewContainer,int centerX){
48 | TreeViewHolder> currentHolder = treeViewContainer.getTreeViewHolder(currentNode);
49 | View currentNodeView = currentHolder == null ? null : currentHolder.getView();
50 | if (currentNodeView == null) {
51 | throw new NullPointerException(" currentNodeView can not be null");
52 | }
53 | int left = centerX*2 - currentNodeView.getRight();
54 | int right = centerX*2- currentNodeView.getLeft();
55 | int top = currentNodeView.getTop();
56 | int bottom =currentNodeView.getBottom();
57 | ViewBox finalLocation = new ViewBox(top, left, bottom, right);
58 | onManagerLayoutNode(currentNode, currentNodeView, finalLocation, treeViewContainer);
59 | }
60 |
61 | @Override
62 | public void onManagerLayoutNode(NodeModel> currentNode, View currentNodeView, ViewBox finalLocation, TreeViewContainer treeViewContainer) {
63 | if(isJustCalculate){
64 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
65 | return;
66 | }
67 | if (!layoutAnimatePrepare(currentNode, currentNodeView, finalLocation, treeViewContainer)) {
68 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
69 | }
70 | }
71 |
72 | @Override
73 | public void onManagerFinishLayoutAllNodes(TreeViewContainer treeViewContainer) {
74 | if(!isJustCalculate){
75 | super.onManagerFinishLayoutAllNodes(treeViewContainer);
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/layout/BoxUpTreeLayoutManager.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.layout;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import com.gyso.treeview.TreeViewContainer;
7 | import com.gyso.treeview.adapter.TreeViewHolder;
8 | import com.gyso.treeview.line.BaseLine;
9 | import com.gyso.treeview.model.ITraversal;
10 | import com.gyso.treeview.model.NodeModel;
11 | import com.gyso.treeview.model.TreeModel;
12 | import com.gyso.treeview.util.ViewBox;
13 |
14 | public class BoxUpTreeLayoutManager extends BoxDownTreeLayoutManager {
15 | private static final String TAG = BoxUpTreeLayoutManager.class.getSimpleName();
16 | private boolean isJustCalculate;
17 | public BoxUpTreeLayoutManager(Context context, int spaceParentToChild, int spacePeerToPeer, BaseLine baseline) {
18 | super(context, spaceParentToChild, spacePeerToPeer, baseline);
19 | }
20 | @Override
21 | public int getTreeLayoutType() {
22 | return LAYOUT_TYPE_VERTICAL_UP;
23 | }
24 |
25 | @Override
26 | public void performLayout(final TreeViewContainer treeViewContainer) {
27 | isJustCalculate = true;
28 | super.performLayout(treeViewContainer);
29 | isJustCalculate = false;
30 | final TreeModel> mTreeModel = treeViewContainer.getTreeModel();
31 | if (mTreeModel != null) {
32 | final int cy= fixedViewBox.getHeight()/2;
33 | mTreeModel.doTraversalNodes(new ITraversal>() {
34 | @Override
35 | public void next(NodeModel> next) {
36 | mirrorByCy(next,treeViewContainer,cy);
37 | }
38 | @Override
39 | public void finish() {
40 | onManagerFinishLayoutAllNodes(treeViewContainer);
41 | }
42 | });
43 | }
44 | }
45 |
46 | private void mirrorByCy(NodeModel> currentNode, TreeViewContainer treeViewContainer,int centerY){
47 | TreeViewHolder> currentHolder = treeViewContainer.getTreeViewHolder(currentNode);
48 | View currentNodeView = currentHolder == null ? null : currentHolder.getView();
49 | if (currentNodeView == null) {
50 | throw new NullPointerException(" currentNodeView can not be null");
51 | }
52 | int left =currentNodeView.getLeft();
53 | int right = currentNodeView.getRight();
54 | int bottom= centerY*2- currentNodeView.getTop();
55 | int top = centerY*2- currentNodeView.getBottom();
56 | ViewBox finalLocation = new ViewBox(top, left, bottom, right);
57 | onManagerLayoutNode(currentNode, currentNodeView, finalLocation, treeViewContainer);
58 | }
59 |
60 | @Override
61 | public void onManagerLayoutNode(NodeModel> currentNode, View currentNodeView, ViewBox finalLocation, TreeViewContainer treeViewContainer) {
62 | if(isJustCalculate){
63 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
64 | return;
65 | }
66 | if (!layoutAnimatePrepare(currentNode, currentNodeView, finalLocation, treeViewContainer)) {
67 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
68 | }
69 | }
70 |
71 | @Override
72 | public void onManagerFinishLayoutAllNodes(TreeViewContainer treeViewContainer) {
73 | if(!isJustCalculate){
74 | super.onManagerFinishLayoutAllNodes(treeViewContainer);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/layout/CompactLeftTreeLayoutManager.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.layout;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import com.gyso.treeview.TreeViewContainer;
7 | import com.gyso.treeview.adapter.TreeViewHolder;
8 | import com.gyso.treeview.line.BaseLine;
9 | import com.gyso.treeview.model.ITraversal;
10 | import com.gyso.treeview.model.NodeModel;
11 | import com.gyso.treeview.model.TreeModel;
12 | import com.gyso.treeview.util.ViewBox;
13 |
14 | public class CompactLeftTreeLayoutManager extends CompactRightTreeLayoutManager{
15 | private static final String TAG = TableLeftTreeLayoutManager.class.getSimpleName();
16 | private boolean isJustCalculate;
17 | public CompactLeftTreeLayoutManager(Context context, int spaceParentToChild, int spacePeerToPeer, BaseLine baseline) {
18 | super(context, spaceParentToChild, spacePeerToPeer, baseline);
19 | }
20 |
21 | @Override
22 | public int getTreeLayoutType() {
23 | return LAYOUT_TYPE_HORIZON_LEFT;
24 | }
25 |
26 | @Override
27 | public void performLayout(final TreeViewContainer treeViewContainer) {
28 | isJustCalculate = true;
29 | super.performLayout(treeViewContainer);
30 | isJustCalculate = false;
31 | final TreeModel> mTreeModel = treeViewContainer.getTreeModel();
32 | if (mTreeModel != null) {
33 | final int cx = fixedViewBox.getWidth()/2;
34 | mTreeModel.doTraversalNodes(new ITraversal>() {
35 | @Override
36 | public void next(NodeModel> next) {
37 | mirrorByCx(next,treeViewContainer,cx);
38 | }
39 | @Override
40 | public void finish() {
41 | onManagerFinishLayoutAllNodes(treeViewContainer);
42 | }
43 | });
44 | }
45 | }
46 |
47 | private void mirrorByCx(NodeModel> currentNode, TreeViewContainer treeViewContainer,int centerX){
48 | TreeViewHolder> currentHolder = treeViewContainer.getTreeViewHolder(currentNode);
49 | View currentNodeView = currentHolder == null ? null : currentHolder.getView();
50 | if (currentNodeView == null) {
51 | throw new NullPointerException(" currentNodeView can not be null");
52 | }
53 | int left = centerX*2 - currentNodeView.getRight();
54 | int right = centerX*2- currentNodeView.getLeft();
55 | int top = currentNodeView.getTop();
56 | int bottom =currentNodeView.getBottom();
57 | ViewBox finalLocation = new ViewBox(top, left, bottom, right);
58 | onManagerLayoutNode(currentNode, currentNodeView, finalLocation, treeViewContainer);
59 | }
60 |
61 | @Override
62 | public void onManagerLayoutNode(NodeModel> currentNode, View currentNodeView, ViewBox finalLocation, TreeViewContainer treeViewContainer) {
63 | if(isJustCalculate){
64 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
65 | return;
66 | }
67 | if (!layoutAnimatePrepare(currentNode, currentNodeView, finalLocation, treeViewContainer)) {
68 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
69 | }
70 | }
71 |
72 | @Override
73 | public void onManagerFinishLayoutAllNodes(TreeViewContainer treeViewContainer) {
74 | if(!isJustCalculate){
75 | super.onManagerFinishLayoutAllNodes(treeViewContainer);
76 | }
77 | }
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/layout/CompactUpTreeLayoutManager.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.layout;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import com.gyso.treeview.TreeViewContainer;
7 | import com.gyso.treeview.adapter.TreeViewHolder;
8 | import com.gyso.treeview.line.BaseLine;
9 | import com.gyso.treeview.model.ITraversal;
10 | import com.gyso.treeview.model.NodeModel;
11 | import com.gyso.treeview.model.TreeModel;
12 | import com.gyso.treeview.util.ViewBox;
13 |
14 | public class CompactUpTreeLayoutManager extends CompactDownTreeLayoutManager {
15 | private static final String TAG = CompactUpTreeLayoutManager.class.getSimpleName();
16 | private boolean isJustCalculate;
17 | public CompactUpTreeLayoutManager(Context context, int spaceParentToChild, int spacePeerToPeer, BaseLine baseline) {
18 | super(context, spaceParentToChild, spacePeerToPeer, baseline);
19 | }
20 | @Override
21 | public int getTreeLayoutType() {
22 | return LAYOUT_TYPE_VERTICAL_UP;
23 | }
24 |
25 | @Override
26 | public void performLayout(final TreeViewContainer treeViewContainer) {
27 | isJustCalculate = true;
28 | super.performLayout(treeViewContainer);
29 | isJustCalculate = false;
30 | final TreeModel> mTreeModel = treeViewContainer.getTreeModel();
31 | if (mTreeModel != null) {
32 | final int cy= fixedViewBox.getHeight()/2;
33 | mTreeModel.doTraversalNodes(new ITraversal>() {
34 | @Override
35 | public void next(NodeModel> next) {
36 | mirrorByCy(next,treeViewContainer,cy);
37 | }
38 | @Override
39 | public void finish() {
40 | onManagerFinishLayoutAllNodes(treeViewContainer);
41 | }
42 | });
43 | }
44 | }
45 |
46 | private void mirrorByCy(NodeModel> currentNode, TreeViewContainer treeViewContainer,int centerY){
47 | TreeViewHolder> currentHolder = treeViewContainer.getTreeViewHolder(currentNode);
48 | View currentNodeView = currentHolder == null ? null : currentHolder.getView();
49 | if (currentNodeView == null) {
50 | throw new NullPointerException(" currentNodeView can not be null");
51 | }
52 | int left =currentNodeView.getLeft();
53 | int right = currentNodeView.getRight();
54 | int bottom= centerY*2- currentNodeView.getTop();
55 | int top = centerY*2- currentNodeView.getBottom();
56 | ViewBox finalLocation = new ViewBox(top, left, bottom, right);
57 | onManagerLayoutNode(currentNode, currentNodeView, finalLocation, treeViewContainer);
58 | }
59 |
60 | @Override
61 | public void onManagerLayoutNode(NodeModel> currentNode, View currentNodeView, ViewBox finalLocation, TreeViewContainer treeViewContainer) {
62 | if(isJustCalculate){
63 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
64 | return;
65 | }
66 | if (!layoutAnimatePrepare(currentNode, currentNodeView, finalLocation, treeViewContainer)) {
67 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
68 | }
69 | }
70 |
71 | @Override
72 | public void onManagerFinishLayoutAllNodes(TreeViewContainer treeViewContainer) {
73 | if(!isJustCalculate){
74 | super.onManagerFinishLayoutAllNodes(treeViewContainer);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/layout/TableLeftTreeLayoutManager.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.layout;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import com.gyso.treeview.TreeViewContainer;
6 | import com.gyso.treeview.adapter.TreeViewHolder;
7 | import com.gyso.treeview.line.BaseLine;
8 | import com.gyso.treeview.model.ITraversal;
9 | import com.gyso.treeview.model.NodeModel;
10 | import com.gyso.treeview.model.TreeModel;
11 | import com.gyso.treeview.util.ViewBox;
12 |
13 | public class TableLeftTreeLayoutManager extends TableRightTreeLayoutManager {
14 | private static final String TAG = TableLeftTreeLayoutManager.class.getSimpleName();
15 | private boolean isJustCalculate;
16 | public TableLeftTreeLayoutManager(Context context, int spaceParentToChild, int spacePeerToPeer, BaseLine baseline) {
17 | super(context, spaceParentToChild, spacePeerToPeer, baseline);
18 | }
19 |
20 | @Override
21 | public int getTreeLayoutType() {
22 | return LAYOUT_TYPE_HORIZON_LEFT;
23 | }
24 |
25 | @Override
26 | public void performLayout(final TreeViewContainer treeViewContainer) {
27 | isJustCalculate = true;
28 | super.performLayout(treeViewContainer);
29 | isJustCalculate = false;
30 | final TreeModel> mTreeModel = treeViewContainer.getTreeModel();
31 | if (mTreeModel != null) {
32 | final int cx = fixedViewBox.getWidth()/2;
33 | mTreeModel.doTraversalNodes(new ITraversal>() {
34 | @Override
35 | public void next(NodeModel> next) {
36 | mirrorByCx(next,treeViewContainer,cx);
37 | }
38 | @Override
39 | public void finish() {
40 | onManagerFinishLayoutAllNodes(treeViewContainer);
41 | }
42 | });
43 | }
44 | }
45 |
46 | private void mirrorByCx(NodeModel> currentNode, TreeViewContainer treeViewContainer,int centerX){
47 | TreeViewHolder> currentHolder = treeViewContainer.getTreeViewHolder(currentNode);
48 | View currentNodeView = currentHolder == null ? null : currentHolder.getView();
49 | if (currentNodeView == null) {
50 | throw new NullPointerException(" currentNodeView can not be null");
51 | }
52 | int left = centerX*2 - currentNodeView.getRight();
53 | int right = centerX*2- currentNodeView.getLeft();
54 | int top = currentNodeView.getTop();
55 | int bottom =currentNodeView.getBottom();
56 | ViewBox finalLocation = new ViewBox(top, left, bottom, right);
57 | onManagerLayoutNode(currentNode, currentNodeView, finalLocation, treeViewContainer);
58 | }
59 |
60 | @Override
61 | public void onManagerLayoutNode(NodeModel> currentNode, View currentNodeView, ViewBox finalLocation, TreeViewContainer treeViewContainer) {
62 | if(isJustCalculate){
63 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
64 | return;
65 | }
66 | if (!layoutAnimatePrepare(currentNode, currentNodeView, finalLocation, treeViewContainer)) {
67 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
68 | }
69 | }
70 |
71 | @Override
72 | public void onManagerFinishLayoutAllNodes(TreeViewContainer treeViewContainer) {
73 | if(!isJustCalculate){
74 | super.onManagerFinishLayoutAllNodes(treeViewContainer);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/layout/TableUpTreeLayoutManagerTable.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.layout;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import com.gyso.treeview.TreeViewContainer;
7 | import com.gyso.treeview.adapter.TreeViewHolder;
8 | import com.gyso.treeview.line.BaseLine;
9 | import com.gyso.treeview.model.ITraversal;
10 | import com.gyso.treeview.model.NodeModel;
11 | import com.gyso.treeview.model.TreeModel;
12 | import com.gyso.treeview.util.ViewBox;
13 |
14 | public class TableUpTreeLayoutManagerTable extends TableDownTreeLayoutManager {
15 | private static final String TAG = TableUpTreeLayoutManagerTable.class.getSimpleName();
16 | private boolean isJustCalculate;
17 | public TableUpTreeLayoutManagerTable(Context context, int spaceParentToChild, int spacePeerToPeer, BaseLine baseline) {
18 | super(context, spaceParentToChild, spacePeerToPeer, baseline);
19 | }
20 | @Override
21 | public int getTreeLayoutType() {
22 | return LAYOUT_TYPE_VERTICAL_UP;
23 | }
24 |
25 | @Override
26 | public void performLayout(final TreeViewContainer treeViewContainer) {
27 | isJustCalculate = true;
28 | super.performLayout(treeViewContainer);
29 | isJustCalculate = false;
30 | final TreeModel> mTreeModel = treeViewContainer.getTreeModel();
31 | if (mTreeModel != null) {
32 | final int cy= fixedViewBox.getHeight()/2;
33 | mTreeModel.doTraversalNodes(new ITraversal>() {
34 | @Override
35 | public void next(NodeModel> next) {
36 | mirrorByCy(next,treeViewContainer,cy);
37 | }
38 | @Override
39 | public void finish() {
40 | onManagerFinishLayoutAllNodes(treeViewContainer);
41 | }
42 | });
43 | }
44 | }
45 |
46 | private void mirrorByCy(NodeModel> currentNode, TreeViewContainer treeViewContainer,int centerY){
47 | TreeViewHolder> currentHolder = treeViewContainer.getTreeViewHolder(currentNode);
48 | View currentNodeView = currentHolder == null ? null : currentHolder.getView();
49 | if (currentNodeView == null) {
50 | throw new NullPointerException(" currentNodeView can not be null");
51 | }
52 | int left =currentNodeView.getLeft();
53 | int right = currentNodeView.getRight();
54 | int bottom= centerY*2- currentNodeView.getTop();
55 | int top = centerY*2- currentNodeView.getBottom();
56 | ViewBox finalLocation = new ViewBox(top, left, bottom, right);
57 | onManagerLayoutNode(currentNode, currentNodeView, finalLocation, treeViewContainer);
58 | }
59 |
60 | @Override
61 | public void onManagerLayoutNode(NodeModel> currentNode, View currentNodeView, ViewBox finalLocation, TreeViewContainer treeViewContainer) {
62 | if(isJustCalculate){
63 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
64 | return;
65 | }
66 | if (!layoutAnimatePrepare(currentNode, currentNodeView, finalLocation, treeViewContainer)) {
67 | currentNodeView.layout(finalLocation.left, finalLocation.top, finalLocation.right, finalLocation.bottom);
68 | }
69 | }
70 |
71 | @Override
72 | public void onManagerFinishLayoutAllNodes(TreeViewContainer treeViewContainer) {
73 | if(!isJustCalculate){
74 | super.onManagerFinishLayoutAllNodes(treeViewContainer);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/line/AngledLine.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.line;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.graphics.PointF;
9 | import android.view.View;
10 |
11 | import com.gyso.treeview.adapter.DrawInfo;
12 | import com.gyso.treeview.adapter.TreeViewHolder;
13 | import com.gyso.treeview.cache_pool.PointPool;
14 | import com.gyso.treeview.layout.TreeLayoutManager;
15 | import com.gyso.treeview.model.NodeModel;
16 | import com.gyso.treeview.util.DensityUtils;
17 |
18 | /**
19 | * @Author: 怪兽N
20 | * @Time: 2021/5/18 16:47
21 | * @Email: 674149099@qq.com
22 | * @WeChat: guaishouN
23 | * @Describe:
24 | * AngledLine between two nodes
25 | */
26 | public class AngledLine extends BaseLine {
27 | public static final int DEFAULT_LINE_WIDTH_DP = 3;
28 | private int lineColor = Color.parseColor("#055287");
29 | private int lineWidth = DEFAULT_LINE_WIDTH_DP;
30 | public AngledLine() {
31 | super();
32 | }
33 |
34 | public AngledLine(int lineColor, int lineWidth_dp) {
35 | this();
36 | this.lineColor = lineColor;
37 | this.lineWidth = lineWidth_dp;
38 | }
39 |
40 | public void setLineColor(int lineColor) {
41 | this.lineColor = lineColor;
42 | }
43 |
44 | public void setLineWidth(int lineWidth) {
45 | this.lineWidth = lineWidth;
46 | }
47 | @Override
48 | public void draw(DrawInfo drawInfo) {
49 | Canvas canvas = drawInfo.getCanvas();
50 | TreeViewHolder> fromHolder = drawInfo.getFromHolder();
51 | TreeViewHolder> toHolder = drawInfo.getToHolder();
52 | Paint mPaint = drawInfo.getPaint();
53 | Path mPath = drawInfo.getPath();
54 | int holderLayoutType = toHolder.getHolderLayoutType();
55 | int spacePeerToPeer = drawInfo.getSpacePeerToPeer();
56 | int spaceParentToChild = drawInfo.getSpaceParentToChild();
57 |
58 | //get view and node
59 | View fromView = fromHolder.getView();
60 | NodeModel> fromNode = fromHolder.getNode();
61 | View toView = toHolder.getView();
62 | NodeModel> toNode = toHolder.getNode();
63 | Context context = fromView.getContext();
64 |
65 | PointF startPoint,point1,endPoint,point2;
66 | if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_HORIZON_RIGHT){
67 | startPoint = PointPool.obtain(fromView.getRight(),(fromView.getTop()+fromView.getBottom())/2f);
68 | point1 = PointPool.obtain(startPoint.x+spaceParentToChild/3f,startPoint.y);
69 | endPoint = PointPool.obtain(toView.getLeft(),(toView.getTop()+toView.getBottom())/2f);
70 | point2 = PointPool.obtain(startPoint.x+spaceParentToChild/3f,endPoint.y);
71 |
72 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_HORIZON_LEFT){
73 | startPoint = PointPool.obtain(fromView.getLeft(),(fromView.getTop()+fromView.getBottom())/2f);
74 | point1 = PointPool.obtain(startPoint.x-spaceParentToChild/3f,startPoint.y);
75 | endPoint = PointPool.obtain(toView.getRight(),(toView.getTop()+toView.getBottom())/2f);
76 | point2 = PointPool.obtain(startPoint.x-spaceParentToChild/3f,endPoint.y);
77 |
78 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_VERTICAL_DOWN){
79 | startPoint = PointPool.obtain((fromView.getLeft()+fromView.getRight())/2f,fromView.getBottom());
80 | point1 = PointPool.obtain(startPoint.x,startPoint.y+spaceParentToChild/3f);
81 | endPoint = PointPool.obtain((toView.getLeft()+toView.getRight())/2f,toView.getTop());
82 | point2 = PointPool.obtain(endPoint.x,startPoint.y+spaceParentToChild/3f);
83 |
84 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_VERTICAL_UP){
85 | startPoint = PointPool.obtain((fromView.getLeft()+fromView.getRight())/2f,fromView.getTop());
86 | point1 = PointPool.obtain(startPoint.x,startPoint.y-spaceParentToChild/3f);
87 | endPoint = PointPool.obtain((toView.getLeft()+toView.getRight())/2f,toView.getBottom());
88 | point2 = PointPool.obtain(endPoint.x,startPoint.y-spaceParentToChild/3f);
89 |
90 | }else{
91 | super.draw(drawInfo);
92 | return;
93 | }
94 |
95 | //set paint
96 | mPath.reset();
97 | mPaint.reset();
98 | mPaint.setColor(lineColor);
99 | mPaint.setStyle(Paint.Style.STROKE);
100 | mPaint.setStrokeWidth(DensityUtils.dp2px(context,lineWidth));
101 | mPaint.setAntiAlias(true);
102 |
103 | mPath.moveTo(startPoint.x,startPoint.y);
104 | mPath.lineTo(point1.x,point1.y);
105 | mPath.lineTo(point2.x,point2.y);
106 | mPath.lineTo(endPoint.x,endPoint.y);
107 |
108 | //do not forget release
109 | PointPool.free(startPoint);
110 | PointPool.free(point1);
111 | PointPool.free(point2);
112 | PointPool.free(endPoint);
113 | //draw
114 | canvas.drawPath(mPath,mPaint);
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/line/BaseLine.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.line;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.view.View;
9 | import com.gyso.treeview.adapter.DrawInfo;
10 | import com.gyso.treeview.adapter.TreeViewHolder;
11 | import com.gyso.treeview.util.DensityUtils;
12 |
13 | /**
14 | * @Author: 怪兽N
15 | * @Time: 2021/5/7 21:02
16 | * @Email: 674149099@qq.com
17 | * @WeChat: guaishouN
18 | * @Describe:
19 | * line to connect the fromNodeView and toNodeView
20 | */
21 | public class BaseLine {
22 | /**
23 | * this method will be invoke when the tree view is onDispatchDraw
24 | */
25 | public void draw(DrawInfo drawInfo){
26 | Canvas canvas = drawInfo.getCanvas();
27 | TreeViewHolder> fromHolder = drawInfo.getFromHolder();
28 | TreeViewHolder> toHolder = drawInfo.getToHolder();
29 | Paint mPaint = drawInfo.getPaint();
30 | Path mPath = drawInfo.getPath();
31 |
32 | //get view and node
33 | View fromView = fromHolder.getView();
34 | View toView = toHolder.getView();
35 | Context context = fromView.getContext();
36 |
37 | //set paint
38 | mPaint.reset();
39 | mPath.reset();
40 | mPaint.setColor(Color.MAGENTA);
41 | mPaint.setStyle(Paint.Style.STROKE);
42 | mPaint.setStrokeWidth(DensityUtils.dp2px(context,3));
43 | mPaint.setAntiAlias(true);
44 |
45 | int fromCenterX = (fromView.getLeft()+fromView.getRight())/2;
46 | int fromCenterY = (fromView.getTop()+fromView.getBottom())/2;
47 | int toCenterX = (toView.getLeft()+toView.getRight())/2;
48 | int toCenterY = (toView.getTop()+toView.getBottom())/2;
49 |
50 | mPath.moveTo(fromCenterX, fromCenterY);
51 | mPath.lineTo(toCenterX, toCenterY);
52 |
53 | //draw
54 | canvas.drawPath(mPath,mPaint);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/line/DashLine.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.line;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.DashPathEffect;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.graphics.PointF;
10 | import android.view.View;
11 |
12 | import com.gyso.treeview.adapter.DrawInfo;
13 | import com.gyso.treeview.adapter.TreeViewHolder;
14 | import com.gyso.treeview.cache_pool.PointPool;
15 | import com.gyso.treeview.layout.TreeLayoutManager;
16 | import com.gyso.treeview.model.NodeModel;
17 | import com.gyso.treeview.util.DensityUtils;
18 |
19 | /**
20 | * @Author: 怪兽N
21 | * @Time: 2021/5/8 17:41
22 | * @Email: 674149099@qq.com
23 | * @WeChat: guaishouN
24 | * @Describe:
25 | * DashPathEffect line
26 | */
27 | public class DashLine extends BaseLine {
28 | public static final int DEFAULT_LINE_WIDTH_DP = 3;
29 | private int lineColor = Color.parseColor("#E57373");
30 | private int lineWidth = DEFAULT_LINE_WIDTH_DP;
31 | private final static DashPathEffect effect = new DashPathEffect(new float[]{20,10},10);
32 | public DashLine() {
33 | super();
34 | }
35 |
36 | public DashLine(int lineColor, int lineWidth_dp) {
37 | this();
38 | this.lineColor = lineColor;
39 | this.lineWidth = lineWidth_dp;
40 | }
41 |
42 | public void setLineColor(int lineColor) {
43 | this.lineColor = lineColor;
44 | }
45 |
46 | public void setLineWidth(int lineWidth) {
47 | this.lineWidth = lineWidth;
48 | }
49 |
50 | @Override
51 | public void draw(DrawInfo drawInfo) {
52 | Canvas canvas = drawInfo.getCanvas();
53 | TreeViewHolder> fromHolder = drawInfo.getFromHolder();
54 | TreeViewHolder> toHolder = drawInfo.getToHolder();
55 | Paint mPaint = drawInfo.getPaint();
56 | Path mPath = drawInfo.getPath();
57 | int holderLayoutType = toHolder.getHolderLayoutType();
58 | int spacePeerToPeer = drawInfo.getSpacePeerToPeer();
59 | int spaceParentToChild = drawInfo.getSpaceParentToChild();
60 |
61 | //get view and node
62 | View fromView = fromHolder.getView();
63 | NodeModel> fromNode = fromHolder.getNode();
64 | View toView = toHolder.getView();
65 | NodeModel> toNode = toHolder.getNode();
66 | Context context = fromView.getContext();
67 |
68 | PointF startPoint,point1,endPoint,point2;
69 | if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_HORIZON_RIGHT){
70 | startPoint = PointPool.obtain(fromView.getRight(),(fromView.getTop()+fromView.getBottom())/2f);
71 | point1 = PointPool.obtain(startPoint.x+DensityUtils.dp2px(context,15),startPoint.y);
72 | endPoint = PointPool.obtain(toView.getLeft(),(toView.getTop()+toView.getBottom())/2f);
73 | point2 = PointPool.obtain(startPoint.x,endPoint.y);
74 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_HORIZON_LEFT){
75 | startPoint = PointPool.obtain(fromView.getLeft(),(fromView.getTop()+fromView.getBottom())/2f);
76 | point1 = PointPool.obtain(startPoint.x-DensityUtils.dp2px(context,15),startPoint.y);
77 | endPoint = PointPool.obtain(toView.getRight(),(toView.getTop()+toView.getBottom())/2f);
78 | point2 = PointPool.obtain(startPoint.x,endPoint.y);
79 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_VERTICAL_DOWN){
80 | startPoint = PointPool.obtain((fromView.getLeft()+fromView.getRight())/2f,fromView.getBottom());
81 | point1 = PointPool.obtain(startPoint.x,startPoint.y+DensityUtils.dp2px(context,15));
82 | endPoint = PointPool.obtain((toView.getLeft()+toView.getRight())/2f,toView.getTop());
83 | point2 = PointPool.obtain(endPoint.x,startPoint.y);
84 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_VERTICAL_UP){
85 | startPoint = PointPool.obtain((fromView.getLeft()+fromView.getRight())/2f,fromView.getTop());
86 | point1 = PointPool.obtain(startPoint.x,startPoint.y-DensityUtils.dp2px(context,15));
87 | endPoint = PointPool.obtain((toView.getLeft()+toView.getRight())/2f,toView.getBottom());
88 | point2 = PointPool.obtain(endPoint.x,startPoint.y);
89 | }else{
90 | super.draw(drawInfo);
91 | return;
92 | }
93 |
94 | mPaint.reset();
95 | mPath.reset();
96 | //set paint
97 | mPaint.setColor(lineColor);
98 | mPaint.setStyle(Paint.Style.STROKE);
99 | mPaint.setStrokeWidth(DensityUtils.dp2px(context,lineWidth));
100 | mPaint.setAntiAlias(true);
101 | mPaint.setPathEffect(effect);
102 |
103 | mPath.moveTo(startPoint.x,startPoint.y);
104 | mPath.cubicTo(
105 | point1.x,point1.y,
106 | point2.x,point2.y,
107 | endPoint.x,endPoint.y);
108 |
109 | //do not forget release
110 | PointPool.free(startPoint);
111 | PointPool.free(point1);
112 | PointPool.free(point2);
113 | PointPool.free(endPoint);
114 | //draw
115 | canvas.drawPath(mPath,mPaint);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/line/SmoothLine.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.line;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.graphics.PointF;
9 | import android.view.View;
10 |
11 | import com.gyso.treeview.adapter.DrawInfo;
12 | import com.gyso.treeview.adapter.TreeViewHolder;
13 | import com.gyso.treeview.cache_pool.PointPool;
14 | import com.gyso.treeview.layout.TreeLayoutManager;
15 | import com.gyso.treeview.model.NodeModel;
16 | import com.gyso.treeview.util.DensityUtils;
17 |
18 | /**
19 | * @Author: 怪兽N
20 | * @Time: 2021/5/8 9:47
21 | * @Email: 674149099@qq.com
22 | * @WeChat: guaishouN
23 | * @Describe:
24 | * Simple smooth line
25 | */
26 | public class SmoothLine extends BaseLine {
27 | public static final int DEFAULT_LINE_WIDTH_DP = 3;
28 | private int lineColor = Color.parseColor("#055287");
29 | private int lineWidth = DEFAULT_LINE_WIDTH_DP;
30 | public SmoothLine() {
31 | super();
32 | }
33 |
34 | public SmoothLine(int lineColor, int lineWidth_dp) {
35 | this();
36 | this.lineColor = lineColor;
37 | this.lineWidth = lineWidth_dp;
38 | }
39 |
40 | public void setLineColor(int lineColor) {
41 | this.lineColor = lineColor;
42 | }
43 |
44 | public void setLineWidth(int lineWidth) {
45 | this.lineWidth = lineWidth;
46 | }
47 |
48 | @Override
49 | public void draw(DrawInfo drawInfo) {
50 | Canvas canvas = drawInfo.getCanvas();
51 | TreeViewHolder> fromHolder = drawInfo.getFromHolder();
52 | TreeViewHolder> toHolder = drawInfo.getToHolder();
53 | Paint mPaint = drawInfo.getPaint();
54 | Path mPath = drawInfo.getPath();
55 | int holderLayoutType = toHolder.getHolderLayoutType();
56 | int spacePeerToPeer = drawInfo.getSpacePeerToPeer();
57 | int spaceParentToChild = drawInfo.getSpaceParentToChild();
58 |
59 | //get view and node
60 | View fromView = fromHolder.getView();
61 | NodeModel> fromNode = fromHolder.getNode();
62 | View toView = toHolder.getView();
63 | NodeModel> toNode = toHolder.getNode();
64 | Context context = fromView.getContext();
65 |
66 | PointF startPoint,point1,endPoint,point2;
67 | if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_HORIZON_RIGHT){
68 | startPoint = PointPool.obtain(fromView.getRight(),(fromView.getTop()+fromView.getBottom())/2f);
69 | point1 = PointPool.obtain(startPoint.x+DensityUtils.dp2px(context,15),startPoint.y);
70 | endPoint = PointPool.obtain(toView.getLeft(),(toView.getTop()+toView.getBottom())/2f);
71 | point2 = PointPool.obtain(startPoint.x,endPoint.y);
72 |
73 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_HORIZON_LEFT){
74 | startPoint = PointPool.obtain(fromView.getLeft(),(fromView.getTop()+fromView.getBottom())/2f);
75 | point1 = PointPool.obtain(startPoint.x-DensityUtils.dp2px(context,15),startPoint.y);
76 | endPoint = PointPool.obtain(toView.getRight(),(toView.getTop()+toView.getBottom())/2f);
77 | point2 = PointPool.obtain(startPoint.x,endPoint.y);
78 |
79 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_VERTICAL_DOWN){
80 | startPoint = PointPool.obtain((fromView.getLeft()+fromView.getRight())/2f,fromView.getBottom());
81 | point1 = PointPool.obtain(startPoint.x,startPoint.y+DensityUtils.dp2px(context,15));
82 | endPoint = PointPool.obtain((toView.getLeft()+toView.getRight())/2f,toView.getTop());
83 | point2 = PointPool.obtain(endPoint.x,startPoint.y);
84 |
85 | }else if(holderLayoutType== TreeLayoutManager.LAYOUT_TYPE_VERTICAL_UP){
86 | startPoint = PointPool.obtain((fromView.getLeft()+fromView.getRight())/2f,fromView.getTop());
87 | point1 = PointPool.obtain(startPoint.x,startPoint.y-DensityUtils.dp2px(context,15));
88 | endPoint = PointPool.obtain((toView.getLeft()+toView.getRight())/2f,toView.getBottom());
89 | point2 = PointPool.obtain(endPoint.x,startPoint.y);
90 |
91 | }else{
92 | super.draw(drawInfo);
93 | return;
94 | }
95 |
96 | mPaint.reset();
97 | mPath.reset();
98 | //set paint
99 | mPaint.setColor(lineColor);
100 | mPaint.setStyle(Paint.Style.STROKE);
101 | mPaint.setStrokeWidth(DensityUtils.dp2px(context,lineWidth));
102 | mPaint.setAntiAlias(true);
103 | mPath.moveTo(startPoint.x,startPoint.y);
104 | mPath.cubicTo(
105 | point1.x,point1.y,
106 | point2.x,point2.y,
107 | endPoint.x,endPoint.y);
108 | //do not forget release
109 | PointPool.free(startPoint);
110 | PointPool.free(point1);
111 | PointPool.free(point2);
112 | PointPool.free(endPoint);
113 | //draw
114 | canvas.drawPath(mPath,mPaint);
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/line/StraightLine.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.line;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.graphics.PointF;
9 | import android.view.View;
10 |
11 | import com.gyso.treeview.adapter.DrawInfo;
12 | import com.gyso.treeview.adapter.TreeViewHolder;
13 | import com.gyso.treeview.cache_pool.PointPool;
14 | import com.gyso.treeview.layout.TreeLayoutManager;
15 | import com.gyso.treeview.model.NodeModel;
16 | import com.gyso.treeview.util.DensityUtils;
17 |
18 | /**
19 | * @Author: 怪兽N
20 | * @Time: 2021/5/8 9:40
21 | * @Email: 674149099@qq.com
22 | * @WeChat: guaishouN
23 | * @Describe:
24 | * Straight Line
25 | */
26 | public class StraightLine extends BaseLine {
27 | public static final int DEFAULT_LINE_WIDTH_DP = 3;
28 | private int lineColor = Color.parseColor("#055287");
29 | private int lineWidth = DEFAULT_LINE_WIDTH_DP;
30 | public StraightLine() {
31 | super();
32 | }
33 |
34 | public StraightLine(int lineColor, int lineWidth_dp) {
35 | this();
36 | this.lineColor = lineColor;
37 | this.lineWidth = lineWidth_dp;
38 | }
39 |
40 | public void setLineColor(int lineColor) {
41 | this.lineColor = lineColor;
42 | }
43 |
44 | public void setLineWidth(int lineWidth) {
45 | this.lineWidth = lineWidth;
46 | }
47 |
48 | @Override
49 | public void draw(DrawInfo drawInfo) {
50 | Canvas canvas = drawInfo.getCanvas();
51 | TreeViewHolder> fromHolder = drawInfo.getFromHolder();
52 | TreeViewHolder> toHolder = drawInfo.getToHolder();
53 | Paint mPaint = drawInfo.getPaint();
54 | Path mPath = drawInfo.getPath();
55 | int holderLayoutType = toHolder.getHolderLayoutType();
56 | int spacePeerToPeer = drawInfo.getSpacePeerToPeer();
57 | int spaceParentToChild = drawInfo.getSpaceParentToChild();
58 | //get view and node
59 | View fromView = fromHolder.getView();
60 | NodeModel> fromNode = fromHolder.getNode();
61 | View toView = toHolder.getView();
62 | NodeModel> toNode = toHolder.getNode();
63 | Context context = fromView.getContext();
64 |
65 |
66 | PointF startPoint,endPoint;
67 | if(holderLayoutType == TreeLayoutManager.LAYOUT_TYPE_HORIZON_RIGHT){
68 | startPoint = PointPool.obtain(fromView.getRight(),(fromView.getTop()+fromView.getBottom())/2f);
69 | endPoint = PointPool.obtain(toView.getLeft(),(toView.getTop()+toView.getBottom())/2f);
70 |
71 | }else if(holderLayoutType == TreeLayoutManager.LAYOUT_TYPE_HORIZON_LEFT){
72 | startPoint = PointPool.obtain(fromView.getLeft(),(fromView.getTop()+fromView.getBottom())/2f);
73 | endPoint = PointPool.obtain(toView.getRight(),(toView.getTop()+toView.getBottom())/2f);
74 |
75 | }else if(holderLayoutType == TreeLayoutManager.LAYOUT_TYPE_VERTICAL_UP){
76 | startPoint = PointPool.obtain((fromView.getLeft()+fromView.getRight())/2f,fromView.getTop());
77 | endPoint = PointPool.obtain((toView.getLeft()+toView.getRight())/2f,toView.getBottom());
78 |
79 | }else if (holderLayoutType == TreeLayoutManager.LAYOUT_TYPE_VERTICAL_DOWN){
80 | startPoint = PointPool.obtain((fromView.getLeft()+fromView.getRight())/2f,fromView.getBottom());
81 | endPoint = PointPool.obtain((toView.getLeft()+toView.getRight())/2f,toView.getTop());
82 |
83 | }else{
84 | super.draw(drawInfo);
85 | return;
86 | }
87 |
88 | //set paint
89 | mPaint.reset();
90 | mPath.reset();
91 | mPaint.setColor(lineColor);
92 | mPaint.setStyle(Paint.Style.STROKE);
93 | mPaint.setStrokeWidth(DensityUtils.dp2px(context,lineWidth));
94 | mPaint.setAntiAlias(true);
95 |
96 | mPath.moveTo(startPoint.x,startPoint.y);
97 | mPath.lineTo(endPoint.x,endPoint.y);
98 | //release
99 | PointPool.free(startPoint);
100 | PointPool.free(endPoint);
101 | //draw
102 | canvas.drawPath(mPath,mPaint);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/listener/TreeViewControlListener.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.listener;
2 |
3 | import android.view.View;
4 |
5 | import androidx.annotation.Nullable;
6 |
7 | import com.gyso.treeview.model.NodeModel;
8 |
9 | /**
10 | * @Author: 怪兽N
11 | * @Time: 2021/6/15
12 | * @Email: 674149099@qq.com
13 | * @WeChat: guaishouN
14 | * @Describe:
15 | * Listener for drag-move node, scale, drag the hold treeView
16 | */
17 | public interface TreeViewControlListener {
18 | int MIN_SCALE = -1;
19 | int FREE_SCALE = 0;
20 | int MAX_SCALE = 1;
21 | void onScaling(int state, int percent);
22 | void onDragMoveNodesHit(@Nullable NodeModel> draggingNode, @Nullable NodeModel> hittingNode, @Nullable View draggingView, @Nullable View hittingView);
23 | }
24 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/listener/TreeViewItemClick.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.listener;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * guaishouN 674149099@qq.com
7 | */
8 |
9 | public interface TreeViewItemClick {
10 | void onItemClick(View item);
11 | }
12 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/listener/TreeViewItemLongClick.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.listener;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * guaishouN 674149099@qq.com
7 | */
8 |
9 | public interface TreeViewItemLongClick {
10 | void onLongClick(View view);
11 | }
12 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/listener/TreeViewNotifier.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.listener;
2 |
3 |
4 | import com.gyso.treeview.model.NodeModel;
5 |
6 | /**
7 | * @Author: 怪兽N
8 | * @Time: 2021/4/23
9 | * @Email: 674149099@qq.com
10 | * @WeChat: guaishouN
11 | * @Describe:
12 | */
13 | public interface TreeViewNotifier{
14 | void onDataSetChange();
15 | void onRemoveNode(NodeModel>nodeModel);
16 | void onRemoveChildNodes(NodeModel> parentNode);
17 | void onItemViewChange(NodeModel> nodeModel);
18 | void onAddNodes(NodeModel> parent, NodeModel>... childNodes);
19 | }
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/model/ITraversal.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.model;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * traversal callback
7 | * guaishouN 674149099@qq.com
8 | */
9 |
10 | public interface ITraversal extends Serializable {
11 | void next(T next);
12 | default void finish(){}
13 | }
14 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/onNodeEvents.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview;
2 |
3 | import com.gyso.treeview.model.NodeModel;
4 |
5 | public interface onNodeEvents {
6 | boolean onNodeDrop(NodeModel> parent, NodeModel> child);
7 | }
8 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/touch/DragBlock.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.touch;
2 |
3 | import android.graphics.PointF;
4 | import android.os.Handler;
5 | import android.os.Looper;
6 | import android.os.SystemClock;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.view.ViewParent;
10 | import android.view.animation.Interpolator;
11 | import android.widget.OverScroller;
12 |
13 | import com.gyso.treeview.R;
14 | import com.gyso.treeview.TreeViewContainer;
15 | import com.gyso.treeview.adapter.TreeViewHolder;
16 | import com.gyso.treeview.cache_pool.PointPool;
17 | import com.gyso.treeview.model.NodeModel;
18 | import com.gyso.treeview.util.ViewBox;
19 |
20 | import java.util.ArrayList;
21 | import java.util.HashMap;
22 | import java.util.LinkedList;
23 | import java.util.List;
24 | import java.util.Map;
25 |
26 | /**
27 | * @Author: 怪兽N
28 | * @Time: 2021/6/7 17:56
29 | * @Email: 674149099@qq.com
30 | * @WeChat: guaishouN
31 | * @Describe:
32 | * drag block
33 | */
34 | public class DragBlock {
35 | private final List tmp;
36 | private volatile boolean isDragging;
37 | private final TreeViewContainer container;
38 | private final Map originPositionMap;
39 | private final OverScroller mScroller;
40 | private PointF prePointF = null;
41 | /**
42 | * Interpolator defining the animation curve for mScroller
43 | */
44 | private static final Interpolator sInterpolator = t -> {
45 | t -= 1.0f;
46 | return t * t * t * t * t + 1.0f;
47 | };
48 |
49 | public DragBlock(TreeViewContainer parent){
50 | tmp = new ArrayList<>();
51 | container = parent;
52 | this.mScroller = new OverScroller(container.getContext(), sInterpolator);
53 | originPositionMap = new HashMap<>();
54 | }
55 |
56 | public boolean load(View view){
57 | if(originPositionMap.isEmpty() && tmp.isEmpty()){
58 | tmp.add(view);
59 | originPositionMap.put(view,new ViewBox(view));
60 | addItem(view);
61 | return true;
62 | }
63 | return false;
64 | }
65 |
66 | private void addItem(View view){
67 | Object tag = view.getTag(R.id.item_holder);
68 | if(tag instanceof TreeViewHolder){
69 | TreeViewHolder> holder = (TreeViewHolder>)tag;
70 | NodeModel> node = holder.getNode();
71 | for (NodeModel> n:node.getChildNodes()){
72 | TreeViewHolder> h = container.getTreeViewHolder(n);
73 | tmp.add(h.getView());
74 | originPositionMap.put(h.getView(),new ViewBox(h.getView()));
75 | addItem(h.getView());
76 | }
77 | }
78 | }
79 |
80 | public void drag(int dx, int dy){
81 | if(!mScroller.isFinished()){
82 | return;
83 | }
84 | this.isDragging = true;
85 | for (int i = 0; i < tmp.size(); i++) {
86 | View view = tmp.get(i);
87 | view.offsetLeftAndRight(dx);
88 | view.offsetTopAndBottom(dy);
89 | }
90 | }
91 |
92 | public void setDragging(boolean dragging) {
93 | isDragging = dragging;
94 | }
95 |
96 | private void autoRelease(){
97 | if(mScroller.isFinished() && !isDragging){
98 | originPositionMap.clear();
99 | tmp.clear();
100 | System.gc();
101 | }
102 | }
103 |
104 | public void smoothRecover(View referenceView) {
105 | if(!mScroller.isFinished()){
106 | return;
107 | }
108 | ViewBox rBox = originPositionMap.get(referenceView);
109 | if(rBox ==null){
110 | return;
111 | }
112 | prePointF=PointPool.obtain(0f,0f);
113 | mScroller.startScroll(0,0,referenceView.getLeft()-rBox.left,referenceView.getTop()-rBox.top);
114 | }
115 |
116 | public boolean computeScroll() {
117 | boolean isSuc = mScroller.computeScrollOffset();
118 | if(isSuc){
119 | PointF curPointF = PointPool.obtain(mScroller.getCurrX(), mScroller.getCurrY());
120 | mScroller.getCurrY();
121 | for (int i = 0; i < tmp.size(); i++) {
122 | View view = tmp.get(i);
123 | int dx = (int)(curPointF.x-prePointF.x);
124 | int dy = (int)(curPointF.y-prePointF.y);
125 | view.offsetLeftAndRight(-dx);
126 | view.offsetTopAndBottom(-dy);
127 | }
128 | if(prePointF!=null){
129 | prePointF.set(curPointF);
130 | }
131 | PointPool.free(curPointF);
132 | return true;
133 | }
134 | autoRelease();
135 | return false;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/touch/onDoubleTapListener.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.touch;
2 |
3 | public interface onDoubleTapListener {
4 | void onDoubleTapListener();
5 | }
6 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/util/DensityUtils.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.util;
2 |
3 | import android.content.Context;
4 | import android.util.TypedValue;
5 |
6 | /**
7 | * 单位转换 工具类
8 | */
9 | public class DensityUtils {
10 |
11 | /**
12 | * dp转px
13 | */
14 | public static int dp2px(Context context, float dpVal) {
15 | int result = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources()
16 | .getDisplayMetrics());
17 | return result;
18 | }
19 |
20 | /**
21 | * sp转px
22 | */
23 | public static int sp2px(Context context, float spVal) {
24 | int result = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, context.getResources()
25 | .getDisplayMetrics());
26 | return result;
27 | }
28 |
29 | /**
30 | * px转dp
31 | */
32 | public static int px2dp(Context context, float pxVal) {
33 | final float scale = context.getResources().getDisplayMetrics().density;
34 | int result = (int) (pxVal / scale);
35 | return result;
36 | }
37 |
38 | /**
39 | * px转sp
40 | */
41 | public static float px2sp(Context context, float pxVal) {
42 | int result = (int) (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
43 | return result;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/util/Interpolators.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.util;
2 |
3 |
4 | import android.view.animation.AccelerateDecelerateInterpolator;
5 | import android.view.animation.AccelerateInterpolator;
6 | import android.view.animation.BounceInterpolator;
7 | import android.view.animation.DecelerateInterpolator;
8 | import android.view.animation.Interpolator;
9 | import android.view.animation.LinearInterpolator;
10 | import android.view.animation.PathInterpolator;
11 |
12 |
13 | /**
14 | * @Author: 怪兽N
15 | * @Time: 2021/6/10 16:24
16 | * @Email: 674149099@qq.com
17 | * @WeChat: guaishouN
18 | * @Describe:
19 | * Utility class to receive interpolators from
20 | */
21 | public class Interpolators {
22 | public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
23 |
24 | /**
25 | * Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t
26 | * goes from 1 to 0 instead of 0 to 1).
27 | */
28 | public static final Interpolator FAST_OUT_SLOW_IN_REVERSE =
29 | new PathInterpolator(0.8f, 0f, 0.6f, 1f);
30 | public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
31 | public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
32 | public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
33 | public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
34 | public static final Interpolator LINEAR = new LinearInterpolator();
35 | public static final Interpolator ACCELERATE = new AccelerateInterpolator();
36 | public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator();
37 | public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
38 | public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
39 | public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
40 | public static final Interpolator PANEL_CLOSE_ACCELERATED
41 | = new PathInterpolator(0.3f, 0, 0.5f, 1);
42 | public static final Interpolator BOUNCE = new BounceInterpolator();
43 |
44 | /**
45 | * Interpolator to be used when animating a move based on a click. Pair with enough duration.
46 | */
47 | public static final Interpolator TOUCH_RESPONSE =
48 | new PathInterpolator(0.3f, 0f, 0.1f, 1f);
49 |
50 | /**
51 | * Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t
52 | * goes from 1 to 0 instead of 0 to 1).
53 | */
54 | public static final Interpolator TOUCH_RESPONSE_REVERSE =
55 | new PathInterpolator(0.9f, 0f, 0.7f, 1f);
56 | }
57 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/util/TreeViewLog.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.util;
2 |
3 | import android.util.Log;
4 |
5 |
6 | /**
7 | * @Author: 怪兽N
8 | * @Time: 2021/5/8 15:10
9 | * @Email: 674149099@qq.com
10 | * @WeChat: guaishouN
11 | * @Describe:
12 | * logger
13 | */
14 | public class TreeViewLog{
15 | private static boolean isDebug = false;
16 | public static void d(String tag, String msg){
17 | if(isDebug){
18 | Log.d(tag, msg);
19 | }
20 | }
21 | public static void e(String tag, String msg){
22 | if(isDebug){
23 | Log.e(tag, msg);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/node/src/main/java/com/gyso/treeview/util/ViewBox.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview.util;
2 |
3 | import android.graphics.Matrix;
4 | import android.view.View;
5 |
6 | public class ViewBox {
7 |
8 | public int top;
9 | public int left;
10 | public int right;
11 | public int bottom;
12 |
13 | public ViewBox(){
14 |
15 | }
16 | public ViewBox(View view){
17 | this(view.getTop(),view.getLeft(),view.getBottom(),view.getRight());
18 | }
19 |
20 | public ViewBox(int top, int left, int bottom, int right) {
21 | this.top = top;
22 | this.left = left;
23 | this.right = right;
24 | this.bottom = bottom;
25 | }
26 |
27 | public void setValues(ViewBox viewBox) {
28 | this.top = viewBox.top;
29 | this.left = viewBox.left;
30 | this.right = viewBox.right;
31 | this.bottom = viewBox.bottom;
32 | }
33 |
34 | public void setValues(int top, int left,int bottom,int right) {
35 | this.top = top;
36 | this.left = left;
37 | this.bottom = bottom;
38 | this.right = right;
39 | }
40 |
41 | public static ViewBox getViewBox(View view) {
42 | return new ViewBox(view);
43 | }
44 |
45 | /**
46 | *.scaleX(centerM[0])
47 | *.translationX(centerM[2])
48 | *.scaleY(centerM[4])
49 | *.translationY(centerM[5])
50 | *
51 | *float left = v.getLeft()*v.getScaleX()+v.getTranslationX();
52 | *float top = v.getTop()*v.getScaleY()+v.getTranslationY();
53 | *float right = v.getRight()*v.getScaleX()+v.getTranslationX();
54 | *float bottom = v.getBottom()*v.getScaleY()+v.getTranslationY();
55 | */
56 | public ViewBox convert(Matrix matrix) {
57 | float[] fs = new float[9];
58 | matrix.getValues(fs);
59 | float scaleX = fs[Matrix.MSCALE_X];
60 | float scaleY = fs[Matrix.MSCALE_Y];
61 | float translX = fs[Matrix.MTRANS_X];
62 | float translY = fs[Matrix.MTRANS_Y];
63 | float leftI = left*scaleX+translX;
64 | float topI = top*scaleY+translY;
65 | float rightI = right*scaleX+translX;
66 | float bottomI = bottom*scaleY+translY;
67 | return new ViewBox((int)topI,(int)leftI,(int)bottomI,(int)rightI);
68 | }
69 |
70 | public ViewBox invert(Matrix matrix){
71 | float[] fs = new float[9];
72 | matrix.getValues(fs);
73 | float scaleX = fs[Matrix.MSCALE_X];
74 | float scaleY = fs[Matrix.MSCALE_Y];
75 | float translX = fs[Matrix.MTRANS_X];
76 | float translY = fs[Matrix.MTRANS_Y];
77 | float leftI = (left-translX)/scaleX;
78 | float topI = (top-translY)/scaleY;
79 | float rightI = (right-translX)/scaleX;
80 | float bottomI = (bottom-translY)/scaleY;
81 | setValues((int)topI,(int)leftI,(int)rightI,(int)bottomI);
82 | return new ViewBox((int)topI,(int)leftI,(int)bottomI,(int)rightI);
83 | }
84 |
85 | public boolean contain(ViewBox other){
86 | return other!=null &&
87 | top<=other.top &&
88 | left<=other.left &&
89 | right>=other.right &&
90 | bottom>=other.bottom;
91 | }
92 |
93 | public ViewBox multiply(float radio) {
94 | return new ViewBox(
95 | (int)(top * radio),
96 | (int)(left * radio),
97 | (int)(bottom * radio),
98 | (int)(right * radio)
99 | );
100 | }
101 |
102 | public ViewBox add(ViewBox other) {
103 | if (other == null) {
104 | return this;
105 | }
106 | return new ViewBox(
107 | top + other.top,
108 | left + other.left,
109 | bottom + other.bottom,
110 | right + other.right
111 | );
112 | }
113 |
114 | public ViewBox subtract(ViewBox other){
115 | if (other == null) {
116 | return this;
117 | }
118 | return new ViewBox(
119 | top - other.top,
120 | left - other.left,
121 | bottom - other.bottom,
122 | right - other.right
123 | );
124 | }
125 |
126 | /**
127 | * get the box height which added 2*dy
128 | * @return height
129 | */
130 | public int getHeight(){
131 | return bottom-top;
132 | }
133 |
134 | /**
135 | * get the box width which added 2*dy
136 | * @return width
137 | */
138 | public int getWidth(){
139 | return right-left;
140 | }
141 |
142 | public void clear() {
143 | this.top = 0;
144 | this.left = 0;
145 | this.right = 0;
146 | this.bottom = 0;
147 | }
148 |
149 | @Override
150 | public String toString() {
151 | return "{" +
152 | "t:" + top +
153 | " l:" + left +
154 | " b:" + bottom +
155 | " r:" + right +
156 | '}';
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/node/src/main/res/values/values.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | #E1BEE7
16 |
--------------------------------------------------------------------------------
/node/src/test/java/com/gyso/treeview/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.gyso.treeview;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google {
4 | content {
5 | includeGroupByRegex("com\\.android.*")
6 | includeGroupByRegex("com\\.google.*")
7 | includeGroupByRegex("androidx.*")
8 | }
9 | }
10 | mavenCentral()
11 | gradlePluginPortal()
12 | maven { url "https://jitpack.io" }
13 | }
14 | }
15 | dependencyResolutionManagement {
16 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
17 | repositories {
18 | google()
19 | mavenCentral()
20 | maven { url "https://jitpack.io" }
21 | }
22 | }
23 |
24 | rootProject.name = "AndroidBox"
25 | include ':app'
26 | include ':codeview'
27 | include ':node'
28 |
--------------------------------------------------------------------------------