├── .DS_Store
├── .gitignore
├── .idea
├── modules.xml
└── vcs.xml
├── LICENSE
├── README.md
├── ThinkMap.iml
├── app
├── .gitignore
├── build.gradle
├── note
│ └── 软件设计
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── owant
│ │ └── thinkmap
│ │ ├── ExampleInstrumentedTest.java
│ │ └── ui
│ │ └── splash
│ │ └── SplashActivityTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── owant
│ │ │ └── thinkmap
│ │ │ ├── App.java
│ │ │ ├── AppConstants.java
│ │ │ ├── AppPermissions.java
│ │ │ ├── adapter
│ │ │ └── CurrentWorkAdapter.java
│ │ │ ├── base
│ │ │ ├── BaseActivity.java
│ │ │ ├── BaseAlertDialog.java
│ │ │ ├── BaseFragment.java
│ │ │ ├── BasePresenter.java
│ │ │ └── BaseView.java
│ │ │ ├── control
│ │ │ └── MoveAndScaleHandler.java
│ │ │ ├── drawable
│ │ │ └── GravityCompoundDrawable.java
│ │ │ ├── file
│ │ │ ├── Conf.java
│ │ │ ├── OwantFileCreate.java
│ │ │ └── ZipTool.java
│ │ │ ├── line
│ │ │ ├── EaseCubicInterpolator.java
│ │ │ └── ReboundInterpolator.java
│ │ │ ├── manager
│ │ │ └── ThreadPoolManager.java
│ │ │ ├── model
│ │ │ ├── CurrentFileModel.java
│ │ │ ├── ForTreeItem.java
│ │ │ ├── NodeModel.java
│ │ │ └── TreeModel.java
│ │ │ ├── net
│ │ │ └── BaseResponse.java
│ │ │ ├── test
│ │ │ └── ExampleCreator.java
│ │ │ ├── ui
│ │ │ ├── EditAlertDialog.java
│ │ │ ├── SplashActivity.java
│ │ │ ├── about
│ │ │ │ └── AboutUsActivity.java
│ │ │ ├── codemode
│ │ │ │ └── CodeModeActivity.java
│ │ │ ├── editmap
│ │ │ │ ├── EditMapActivity.java
│ │ │ │ ├── EditMapContract.java
│ │ │ │ └── EditMapPresenter.java
│ │ │ ├── splash
│ │ │ │ └── SplashActivity.java
│ │ │ └── workspace
│ │ │ │ ├── WorkSpaceActivity.java
│ │ │ │ ├── WorkSpaceContract.java
│ │ │ │ └── WorkSpacePresenter.java
│ │ │ ├── util
│ │ │ ├── AndroidUtil.java
│ │ │ ├── DensityUtils.java
│ │ │ ├── LOG.java
│ │ │ ├── LooperFlag.java
│ │ │ ├── MakeZipClient.java
│ │ │ ├── SharePreUtil.java
│ │ │ ├── StringTool.java
│ │ │ └── code
│ │ │ │ ├── BindView.jar
│ │ │ │ └── BindViewTool.java
│ │ │ └── view
│ │ │ ├── NodeView.java
│ │ │ ├── RecycleItemClickListener.java
│ │ │ ├── RecycleItemLongClickListener.java
│ │ │ ├── RightTreeLayoutManager.java
│ │ │ ├── TreeLayoutManager.java
│ │ │ ├── TreeView.java
│ │ │ ├── TreeViewItemClick.java
│ │ │ ├── TreeViewItemLongClick.java
│ │ │ └── ViewBox.java
│ └── res
│ │ ├── anim
│ │ ├── alpha_exit.xml
│ │ ├── alpha_in.xml
│ │ ├── big_enter.xml
│ │ └── right_in.xml
│ │ ├── color
│ │ └── tab_color.xml
│ │ ├── drawable
│ │ ├── box.xml
│ │ ├── btn_bg.xml
│ │ ├── dialog_edit_input_bg.xml
│ │ ├── edit_bg.xml
│ │ ├── enter_bg.xml
│ │ ├── node_view_bg.xml
│ │ ├── selector_purple.xml
│ │ └── tab_bg.xml
│ │ ├── layout-v21
│ │ ├── div_edit_menu.xml
│ │ └── item_current_file.xml
│ │ ├── layout
│ │ ├── activity_about_us.xml
│ │ ├── activity_code_model.xml
│ │ ├── activity_edit_think_map.xml
│ │ ├── activity_main.xml
│ │ ├── activity_splash.xml
│ │ ├── activity_support.xml
│ │ ├── activity_work_space_2.xml
│ │ ├── dialog_edit_input.xml
│ │ ├── div_action_bar.xml
│ │ ├── div_edit_menu.xml
│ │ ├── item_current_file.xml
│ │ ├── scroll_item_menu.xml
│ │ ├── test_3.xml
│ │ └── test_gv.xml
│ │ ├── menu
│ │ └── work_space_menu.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_app.png
│ │ └── support_code.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ ├── clear_input.png
│ │ ├── ic_back.png
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_app.png
│ │ └── menu_moreoverflow.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_app.png
│ │ ├── introduce.png
│ │ ├── iv_add_node.png
│ │ ├── iv_add_sub_node.png
│ │ ├── iv_code_mode.png
│ │ ├── iv_front_view.png
│ │ ├── menu_delete.png
│ │ └── search.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── raw
│ │ └── examples.zip
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── owant
│ └── thinkmap
│ ├── ExampleUnitTest.java
│ └── model
│ └── TreeModelTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── info2.png
└── settings.gradle
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 | .idea/gradle.xml
11 | .idea/misc.xml
12 | .idea/runConfigurations.xml
13 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### Draw a tree in android,ThinkMap
2 |
3 |
4 |
5 | ### The Simple code
6 |
7 | following the simple code, you can build a tree.
8 |
9 | ```
10 | final NodeModel nodeA = new NodeModel<>("A");
11 | final NodeModel nodeB = new NodeModel<>("B");
12 | final NodeModel nodeC = new NodeModel<>("C");
13 | final NodeModel nodeD = new NodeModel<>("D");
14 | final NodeModel nodeE = new NodeModel<>("E");
15 | final NodeModel nodeF = new NodeModel<>("F");
16 | final NodeModel nodeG = new NodeModel<>("G");
17 | final NodeModel nodeH = new NodeModel<>("H");
18 | final NodeModel nodeI = new NodeModel<>("I");
19 | final NodeModel nodeJ = new NodeModel<>("J");
20 | final NodeModel nodeK = new NodeModel<>("K");
21 | final NodeModel nodeL = new NodeModel<>("L");
22 | final NodeModel nodeM = new NodeModel<>("M");
23 | final NodeModel nodeN = new NodeModel<>("N");
24 | final NodeModel nodeO = new NodeModel<>("O");
25 | final NodeModel nodeP = new NodeModel<>("P");
26 | final NodeModel nodeQ = new NodeModel<>("Q");
27 | final NodeModel nodeR = new NodeModel<>("R");
28 | final NodeModel nodeS = new NodeModel<>("S");
29 | final NodeModel nodeT = new NodeModel<>("T");
30 | final NodeModel nodeU = new NodeModel<>("U");
31 | final NodeModel nodeV = new NodeModel<>("V");
32 | final NodeModel nodeW = new NodeModel<>("W");
33 | final NodeModel nodeX = new NodeModel<>("X");
34 | final NodeModel nodeY = new NodeModel<>("Y");
35 | final NodeModel nodeZ = new NodeModel<>("Z");
36 |
37 |
38 | final TreeModel tree = new TreeModel<>(nodeA);
39 | tree.addNode(nodeA, nodeB, nodeC, nodeD);
40 | tree.addNode(nodeC, nodeE, nodeF, nodeG, nodeH, nodeI);
41 | tree.addNode(nodeB, nodeJ, nodeK, nodeL);
42 | tree.addNode(nodeD, nodeM, nodeN, nodeO);
43 | tree.addNode(nodeF, nodeP, nodeQ, nodeR, nodeS);
44 | tree.addNode(nodeR, nodeT, nodeU, nodeV, nodeW, nodeX);
45 | tree.addNode(nodeT, nodeY, nodeZ);
46 |
47 | int dx = DensityUtils.dp2px(this, 20);
48 | int dy = DensityUtils.dp2px(this, 20);
49 | int mHeight = DensityUtils.dp2px(this, 720);
50 |
51 | testTreeView.setTreeLayoutManager(new RightTreeLayoutManager(dx, dy, mHeight));
52 | testTreeView.setTreeModel(tree);
53 |
54 | ```
55 |
56 |
57 | ### AppStore
58 |
59 | http://shouji.baidu.com/software/11238419.html
60 |
61 |
62 | ### Other
63 |
64 | https://blog.csdn.net/u012131702/article/details/54409193
65 |
66 |
--------------------------------------------------------------------------------
/ThinkMap.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | signingConfigs {
5 | config {
6 | keyAlias 'OWANT'
7 | keyPassword 'owant123456'
8 | storeFile file('/Users/owant/Desktop/MyKey')
9 | storePassword 'owant123456'
10 | }
11 | }
12 | compileSdkVersion 26
13 | buildToolsVersion "26.0.1"
14 | defaultConfig {
15 | applicationId "com.owant.thinkmap"
16 | minSdkVersion 15
17 | targetSdkVersion 26
18 | versionCode 10
19 | versionName "1.0.4"
20 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
21 | }
22 |
23 | buildTypes {
24 |
25 | debug{
26 | applicationIdSuffix ".debug"
27 | manifestPlaceholders = [app_name: "ThinkMap_Debug"]
28 | //示例版本,用于判断是否需要更新示例
29 | resValue("string", "examplesVersion", "v1.0.5")
30 | minifyEnabled false
31 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
32 |
33 |
34 | }
35 |
36 | release {
37 | applicationIdSuffix ".debug"
38 | manifestPlaceholders = [app_name: "ThinkMap_Debug"]
39 | //示例版本,用于判断是否需要更新示例
40 | resValue("string", "examplesVersion", "v1.0.5")
41 | minifyEnabled false
42 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
43 | }
44 | }
45 | }
46 |
47 |
48 | ext {
49 | support_version = "25.3.1"
50 | }
51 |
52 | dependencies {
53 | compile fileTree(include: ['*.jar'], dir: 'libs')
54 | testCompile 'junit:junit:4.12'
55 | compile 'com.nineoldandroids:library:2.4.0'
56 | compile 'eu.the4thfloor.volley:com.android.volley:2015.05.28'
57 | compile "com.android.support:appcompat-v7:${support_version}"
58 | compile "com.android.support:cardview-v7:${support_version}"
59 | compile "com.android.support:recyclerview-v7:${support_version}"
60 | //leak检测
61 | debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
62 | releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
63 | testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
64 | androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.2', {
65 | exclude group: 'com.android.support', module: 'support-annotations'
66 | exclude group: 'com.android.support', module: 'support-v4'
67 | exclude group: 'com.android.support', module: 'design'
68 | exclude group: 'com.android.support', module: 'recyclerview-v7'
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/note/软件设计:
--------------------------------------------------------------------------------
1 | 文件格式:.owant
2 | 文件目录为
3 | 文件名(my_play.owant)
4 | content
5 | conf.txt
6 |
7 | 流程:
8 | (要进行清理)
9 | 1.在owantmaps里创建一个create_file文件夹;
10 | 2.content文件进行写序列化的tree对象;
11 | 3.创建一个conf.txt文件进行保存文件基本信息,修改日期,文件名,系统的版本;
12 | 4.为file_name_temp和conf.txt进行压缩为owant文件;
13 | 5.删除create_file文件夹下的所有文件;
14 |
15 |
16 |
17 | TreeView的设计结构
18 |
19 | TreeView
20 | +setTreeModel(TreeModel model)
21 | +setTreeLayoutManager(TreeLayoutManager manager) //树形结构的位置管理器
22 | +onMeasure()
23 | +onLayout()
24 |
25 |
26 | TreeLayoutManager
27 | +onTreeLayout() //进行树形结构的位置确认
28 | +onTreeLayoutCallback(int left,int right,int top,int bottom) //位置确定后的回调
29 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/owant/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | #基本模型不能混淆
20 | -keep class com.owant.thinkmap.model.*{*;}
21 | -keep public class * extends com.owant.thinkmap.model.NodeModel
22 | -keep public class * extends com.owant.thinkmap.model.TreeModel
23 |
24 | #使用了fastJSON不能混淆泛型,注解
25 | -keepattributes Signature
26 | -keepattributes *Annotation*
27 |
28 |
29 | ##支付宝混淆
30 | #-libraryjars libs/alipaySDK-20150602.jar
31 | #-keep class com.alipay.android.app.IAlixPay{*;}
32 | #-keep class com.alipay.android.app.IAlixPay$Stub{*;}
33 | #-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
34 | #-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
35 | #-keep class com.alipay.sdk.app.PayTask{ public *;}
36 | #-keep class com.alipay.sdk.app.AuthTask{ public *;}
37 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/owant/thinkmap/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.owant.thinkmap", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/owant/thinkmap/ui/splash/SplashActivityTest.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui.splash;
2 |
3 |
4 | import android.support.test.rule.ActivityTestRule;
5 | import android.support.test.runner.AndroidJUnit4;
6 | import android.test.suitebuilder.annotation.LargeTest;
7 | import android.view.View;
8 | import android.widget.ImageButton;
9 | import android.widget.Toolbar;
10 |
11 | import org.hamcrest.Matcher;
12 | import org.junit.Rule;
13 | import org.junit.Test;
14 | import org.junit.runner.RunWith;
15 |
16 | import static android.support.test.espresso.Espresso.onView;
17 | import static android.support.test.espresso.action.ViewActions.click;
18 | import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
19 | import static android.support.test.espresso.matcher.ViewMatchers.withParent;
20 | import static android.support.test.espresso.matcher.ViewMatchers.withText;
21 | import static org.hamcrest.Matchers.allOf;
22 |
23 | @LargeTest
24 | @RunWith(AndroidJUnit4.class)
25 | public class SplashActivityTest {
26 |
27 | @Rule
28 | public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(SplashActivity.class);
29 |
30 | @Test
31 | public void splashActivityTest() throws InterruptedException {
32 |
33 | onView(navigationIconMatcher()).perform(click());
34 | onView(withText("QQ")).perform(click());
35 |
36 | }
37 |
38 | public static Matcher navigationIconMatcher() {
39 | return allOf(
40 | isAssignableFrom(ImageButton.class),
41 | withParent(isAssignableFrom(Toolbar.class)));
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
84 |
85 |
88 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/App.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap;
2 |
3 | import android.app.Application;
4 |
5 | import com.owant.thinkmap.util.SharePreUtil;
6 |
7 | /**
8 | * Created by owant on 22/03/2017.
9 | */
10 |
11 | public class App extends Application {
12 |
13 | @Override
14 | public void onCreate() {
15 | super.onCreate();
16 |
17 | //初始化工具
18 | SharePreUtil.getInstance().init(getApplicationContext());
19 | // LeakCanary.install(this);
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/AppConstants.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap;
2 |
3 | /**
4 | * Created by owant on 17/03/2017.
5 | */
6 |
7 | public class AppConstants {
8 |
9 | //owant文件
10 | public final static String owant_maps = "/OwantMaps/";
11 | public final static String temp_create_file = "temp_create_file/";
12 | public final static String content = "content";
13 | public final static String conf = "conf.txt";
14 |
15 | //演示文件
16 | public final static String examples_names = "examples.zip";
17 | public final static String sp_examples_version = "examples_version";
18 |
19 | /**
20 | * 控制LOG
21 | */
22 | public static final boolean CONFIG_DEBUG = true;
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/AppPermissions.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap;
2 |
3 | import android.Manifest;
4 | import android.os.Build;
5 | import android.support.annotation.RequiresApi;
6 |
7 | /**
8 | * Created by owant on 23/03/2017.
9 | */
10 |
11 | @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
12 | public class AppPermissions {
13 |
14 | //权限请求
15 | public static int request_permission_storage = 2;
16 |
17 | /**
18 | *
19 | *
20 | */
21 | public static String[] permission_storage = new String[]{
22 | Manifest.permission.WRITE_EXTERNAL_STORAGE,
23 | Manifest.permission.READ_EXTERNAL_STORAGE
24 | };
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/adapter/CurrentWorkAdapter.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 |
10 | import com.owant.thinkmap.R;
11 | import com.owant.thinkmap.model.CurrentFileModel;
12 | import com.owant.thinkmap.view.RecycleItemClickListener;
13 | import com.owant.thinkmap.view.RecycleItemLongClickListener;
14 |
15 | import java.util.ArrayList;
16 |
17 | /**
18 | * Created by owant on 27/02/2017.
19 | */
20 |
21 | public class CurrentWorkAdapter extends RecyclerView.Adapter {
22 |
23 | public Context mContext;
24 | public ArrayList mLists;
25 |
26 | public RecycleItemClickListener mRecycleItemClickListener;
27 | public RecycleItemLongClickListener mRecycleItemLongClickListener;
28 |
29 | public CurrentWorkAdapter(Context mContext, ArrayList mLists) {
30 | this.mContext = mContext;
31 | this.mLists = mLists;
32 | }
33 |
34 | @Override
35 | public CurrentFileViewHold onCreateViewHolder(ViewGroup parent, int viewType) {
36 | View view = LayoutInflater.from(mContext).inflate(R.layout.item_current_file, parent, false);
37 | CurrentFileViewHold currentFileViewHold = new CurrentFileViewHold(
38 | view,
39 | mRecycleItemClickListener,
40 | mRecycleItemLongClickListener);
41 |
42 | return currentFileViewHold;
43 | }
44 |
45 | @Override
46 | public void onBindViewHolder(CurrentFileViewHold holder, int position) {
47 | CurrentFileModel fileModel = mLists.get(position);
48 | holder.rootValue.setText(fileModel.mapRoot);
49 | holder.filePath.setText(fileModel.filePath);
50 | }
51 |
52 | @Override
53 | public int getItemCount() {
54 | return mLists.size();
55 | }
56 |
57 | public void setRecycleItemClickListener(RecycleItemClickListener recycleItemClickListener) {
58 | mRecycleItemClickListener = recycleItemClickListener;
59 | }
60 |
61 | public void setRecycleItemLongClickListener(RecycleItemLongClickListener recycleItemLongClickListener) {
62 | mRecycleItemLongClickListener = recycleItemLongClickListener;
63 | }
64 |
65 | static class CurrentFileViewHold extends RecyclerView.ViewHolder {
66 | private TextView rootValue;
67 | private TextView filePath;
68 | private RecycleItemClickListener mListener;
69 | private RecycleItemLongClickListener mLongClickListener;
70 |
71 | public CurrentFileViewHold(final View itemView,
72 | RecycleItemClickListener listener,
73 | RecycleItemLongClickListener longListener) {
74 | super(itemView);
75 | rootValue = (TextView) itemView.findViewById(R.id.owant_file_root_value);
76 | filePath = (TextView) itemView.findViewById(R.id.owant_file_path);
77 | mListener = listener;
78 | mLongClickListener = longListener;
79 |
80 | itemView.setOnClickListener(new View.OnClickListener() {
81 | @Override
82 | public void onClick(View v) {
83 | if (mListener != null) {
84 | mListener.onItemClick(itemView, getAdapterPosition());
85 | }
86 | }
87 | });
88 |
89 | itemView.setOnLongClickListener(new View.OnLongClickListener() {
90 | @Override
91 | public boolean onLongClick(View v) {
92 | if (mLongClickListener != null) {
93 | mLongClickListener.onItemLongClick(itemView, getAdapterPosition());
94 | }
95 | return false;
96 | }
97 | });
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/base/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.base;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.app.AppCompatActivity;
6 |
7 |
8 | /**
9 | * Created by owant on 22/02/2017.
10 | */
11 | public abstract class BaseActivity extends AppCompatActivity {
12 |
13 | @Override
14 | protected void onCreate(@Nullable Bundle savedInstanceState) {
15 | super.onCreate(savedInstanceState);
16 |
17 | onBaseIntent();
18 |
19 | onBasePreLayout();
20 |
21 | setContentView(onBaseLayoutId(savedInstanceState));
22 |
23 | onBaseBindView();
24 |
25 | onLoadData();
26 | }
27 |
28 | /**
29 | * Intent进来的数据处理
30 | */
31 | protected abstract void onBaseIntent();
32 |
33 | /**
34 | * 设置布局之前的处理
35 | */
36 | protected abstract void onBasePreLayout();
37 |
38 | /**
39 | * 返回布局文件
40 | *
41 | * @return id
42 | */
43 | protected abstract int onBaseLayoutId(@Nullable Bundle savedInstanceState);
44 |
45 | protected abstract void onBaseBindView();
46 |
47 | /**
48 | * 加载数据
49 | */
50 | protected abstract void onLoadData();
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/base/BaseAlertDialog.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.base;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.IdRes;
5 | import android.support.annotation.NonNull;
6 | import android.support.annotation.Nullable;
7 | import android.support.annotation.StyleRes;
8 | import android.support.v7.app.AlertDialog;
9 | import android.view.View;
10 |
11 | /**
12 | * Created by owant on 24/02/2017.
13 | */
14 |
15 | public abstract class BaseAlertDialog extends AlertDialog {
16 |
17 | private View mainView;
18 |
19 | protected BaseAlertDialog(@NonNull Context context) {
20 | this(context, 0);
21 | }
22 |
23 | protected BaseAlertDialog(@NonNull Context context, @StyleRes int themeResId) {
24 | super(context, themeResId);
25 | }
26 |
27 | @Override
28 | public void setView(View view) {
29 | super.setView(view);
30 | mainView = view;
31 | onBaseBindView();
32 | }
33 |
34 | @Nullable
35 | @Override
36 | public View findViewById(@IdRes int id) {
37 | if (mainView != null) {
38 | return mainView.findViewById(id);
39 | }
40 | return super.findViewById(id);
41 | }
42 |
43 | protected abstract void onBaseBindView();
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/base/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.base;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | /**
12 | * Created by owant on 22/02/2017.
13 | */
14 |
15 | public abstract class BaseFragment extends Fragment {
16 |
17 | @Nullable
18 | @Override
19 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
20 | View tabView = inflater.inflate(onBaseLayoutId(), container, false);
21 | return tabView;
22 | }
23 |
24 | protected abstract int onBaseLayoutId();
25 |
26 | @Override
27 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
28 | super.onActivityCreated(savedInstanceState);
29 |
30 | onBaseBindView();
31 |
32 | onBaseLoadData();
33 | }
34 |
35 | protected abstract void onBaseBindView();
36 |
37 | protected abstract void onBaseLoadData();
38 |
39 | @Override
40 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
41 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/base/BasePresenter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016, The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.owant.thinkmap.base;
18 |
19 | public interface BasePresenter {
20 |
21 | void start();
22 |
23 | void onRecycle();
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/base/BaseView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016, The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.owant.thinkmap.base;
18 |
19 | public interface BaseView {
20 |
21 | void setPresenter(T presenter);
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/control/MoveAndScaleHandler.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.control;
2 |
3 | import android.content.Context;
4 | import android.view.MotionEvent;
5 | import android.view.ScaleGestureDetector;
6 | import android.view.View;
7 |
8 | import com.nineoldandroids.view.ViewHelper;
9 |
10 | /**
11 | * Created by owant on 09/02/2017.
12 | */
13 |
14 | public class MoveAndScaleHandler implements ScaleGestureDetector.OnScaleGestureListener {
15 |
16 | static final float max_scale = 1.2f;
17 | static final float min_scale = 0.3f;
18 |
19 | /**
20 | * 作用于的View
21 | */
22 | private View mView;
23 |
24 | private int lastX = 0;
25 | private int lastY = 0;
26 |
27 | private int mode = 0;
28 |
29 | private ScaleGestureDetector mScaleGestureDetector;
30 | private Context mContext;
31 |
32 | public MoveAndScaleHandler(Context context, View view) {
33 | this.mView = view;
34 | this.mContext = context;
35 | mScaleGestureDetector = new ScaleGestureDetector(mContext, this);
36 | }
37 |
38 | public boolean onTouchEvent(MotionEvent event) {
39 |
40 | int currentX = (int) event.getRawX();//获得手指当前的坐标,相对于屏幕
41 | int currentY = (int) event.getRawY();
42 |
43 | switch (event.getAction() & MotionEvent.ACTION_MASK) {
44 | case MotionEvent.ACTION_DOWN:
45 | mode = 1;
46 | break;
47 | case MotionEvent.ACTION_UP:
48 | mode = 0;
49 | break;
50 | case MotionEvent.ACTION_POINTER_UP:
51 | //将模式进行为负数这样,多指下,抬起不会触发移动
52 | mode = -2;
53 | break;
54 | case MotionEvent.ACTION_POINTER_DOWN:
55 | mode += 1;
56 | break;
57 |
58 | case MotionEvent.ACTION_MOVE:
59 | if (mode >= 2) {
60 | //缩放
61 | //mScaleGestureDetector.onTouchEvent(event);
62 |
63 | } else if (mode == 1) {
64 | int deltaX = currentX - lastX;
65 | int deltaY = currentY - lastY;
66 |
67 | int translationX = (int) ViewHelper.getTranslationX(mView) + deltaX;
68 | int translationY = (int) ViewHelper.getTranslationY(mView) + deltaY;
69 |
70 | ViewHelper.setTranslationX(mView, translationX);
71 | ViewHelper.setTranslationY(mView, translationY);
72 | }
73 | break;
74 | }
75 |
76 | lastX = currentX;
77 | lastY = currentY;
78 |
79 | return true;
80 |
81 | }
82 |
83 | /**
84 | * 两点之间的距离
85 | *
86 | * @param event
87 | * @return
88 | */
89 | private float spacing(MotionEvent event) {
90 | float x = event.getX(0) - event.getX(1);
91 | float y = event.getY(0) - event.getY(1);
92 | return (float) Math.sqrt(x * x + y * y);
93 | }
94 |
95 | @Override
96 | public boolean onScale(ScaleGestureDetector detector) {
97 |
98 | float scaleFactor = detector.getScaleFactor();
99 |
100 | if (scaleFactor >= max_scale) {
101 | scaleFactor = max_scale;
102 | }
103 | if (scaleFactor <= min_scale) {
104 | scaleFactor = min_scale;
105 | }
106 |
107 | float old = mView.getScaleX();
108 | if (Math.abs(scaleFactor - old) > 0.6 || Math.abs(scaleFactor - old) < 0.02) {
109 | //忽略
110 | } else {
111 | ViewHelper.setScaleX(mView, scaleFactor);
112 | ViewHelper.setScaleY(mView, scaleFactor);
113 | }
114 |
115 | return false;
116 | }
117 |
118 | @Override
119 | public boolean onScaleBegin(ScaleGestureDetector detector) {
120 | return true;
121 | }
122 |
123 | @Override
124 | public void onScaleEnd(ScaleGestureDetector detector) {
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/drawable/GravityCompoundDrawable.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.drawable;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.ColorFilter;
5 | import android.graphics.PixelFormat;
6 | import android.graphics.drawable.Drawable;
7 | import android.support.annotation.IntRange;
8 | import android.support.annotation.Nullable;
9 |
10 | /**
11 | * Created by owant on 01/04/2017.
12 | */
13 |
14 | public class GravityCompoundDrawable extends Drawable {
15 |
16 | // inner Drawable
17 | private final Drawable mDrawable;
18 |
19 | public GravityCompoundDrawable(Drawable drawable) {
20 | mDrawable = drawable;
21 | }
22 |
23 | @Override
24 | public int getIntrinsicWidth() {
25 | return mDrawable.getIntrinsicWidth();
26 | }
27 |
28 | @Override
29 | public int getIntrinsicHeight() {
30 | return mDrawable.getIntrinsicHeight();
31 | }
32 |
33 | @Override
34 | public void draw(Canvas canvas) {
35 | int halfCanvas= canvas.getHeight() / 2;
36 | int halfDrawable = mDrawable.getIntrinsicHeight() / 2;
37 |
38 | // align to top
39 | canvas.save();
40 | canvas.translate(0, -halfCanvas + halfDrawable);
41 | mDrawable.draw(canvas);
42 | canvas.restore();
43 | }
44 |
45 | @Override
46 | public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
47 |
48 | }
49 |
50 | @Override
51 | public void setColorFilter(@Nullable ColorFilter colorFilter) {
52 |
53 | }
54 |
55 | @Override
56 | public int getOpacity() {
57 | return PixelFormat.TRANSPARENT;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/file/Conf.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.file;
2 |
3 | /**
4 | * Created by owant on 25/02/2017.
5 | * conf.txt
6 | */
7 |
8 | public class Conf {
9 | public String app_version;
10 | public String android_version;
11 | public String map_name;
12 | public String date;
13 |
14 | @Override
15 | public String toString() {
16 | return "Conf{" +
17 | "app_version='" + app_version + '\'' +
18 | ", android_version='" + android_version + '\'' +
19 | ", map_name='" + map_name + '\'' +
20 | ", date='" + date + '\'' +
21 | '}';
22 | }
23 |
24 | public static void main(String[] args) {
25 | Conf conf = new Conf();
26 | conf.android_version = "android5.0";
27 | conf.app_version = "1.0.1";
28 | conf.date = "2017-2-27";
29 | System.out.println(conf.toString());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/file/OwantFileCreate.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.file;
2 |
3 | import android.os.Environment;
4 | import android.util.Log;
5 |
6 | import com.owant.thinkmap.AppConstants;
7 | import com.owant.thinkmap.model.TreeModel;
8 | import com.owant.thinkmap.util.MakeZipClient;
9 |
10 | import java.io.ByteArrayOutputStream;
11 | import java.io.File;
12 | import java.io.FileInputStream;
13 | import java.io.FileOutputStream;
14 | import java.io.IOException;
15 | import java.io.InputStream;
16 | import java.io.InvalidClassException;
17 | import java.io.ObjectInputStream;
18 | import java.io.ObjectOutputStream;
19 | import java.util.zip.ZipEntry;
20 | import java.util.zip.ZipFile;
21 |
22 | /**
23 | * Created by owant on 25/02/2017.
24 | * (要进行清理)
25 | * 1.在owantmaps里创建一个temp_create_file文件夹;
26 | * 2.content文件进行写序列画的tree对象;
27 | * 3.创建一个conf.txt文件进行保存文件基本信息,修改日期,文件名,系统的版本;
28 | * 4.为file_name_temp和conf.txt进行压缩为owant文件;
29 | * 5.删除create_file文件夹下的所有文件;
30 | */
31 | public class OwantFileCreate {
32 |
33 | private final static String TAG = "OwantFileCreate";
34 |
35 | public void createOwantMapsDirectory() {
36 | if (hansSDCard()) {
37 | String map_path = Environment.getExternalStorageDirectory().getPath() + AppConstants.owant_maps;
38 | File owantMapDirectory = new File(map_path);
39 | if (!owantMapDirectory.exists()) {
40 | boolean mkdir = owantMapDirectory.mkdirs();
41 | Log.i(TAG, "创建owantmaps文件路径:" + mkdir + owantMapDirectory.getAbsolutePath());
42 | }
43 | } else {
44 | Log.e(TAG, "createOwantMapsDirectory: 没有内存卡!");
45 | }
46 | }
47 |
48 | public void createTempDirectory() {
49 | if (hansSDCard()) {
50 | String path = Environment.getExternalStorageDirectory().getPath() + AppConstants.owant_maps + AppConstants.temp_create_file;
51 | File owantMapDirectory = new File(path);
52 | if (!owantMapDirectory.exists()) {
53 | owantMapDirectory.mkdirs();
54 | Log.i(TAG, "创建Temp文件夹:" + path);
55 | }
56 | } else {
57 | Log.e(TAG, "createTempDirectory: 没有内存卡!");
58 | return;
59 | }
60 |
61 |
62 | }
63 |
64 | public void writeContent(Object object) {
65 | try {
66 |
67 | String content_path = Environment.getExternalStorageDirectory().getPath() +
68 | AppConstants.owant_maps +
69 | AppConstants.temp_create_file + "content";
70 |
71 | writeTreeObject(content_path, object);
72 |
73 | } catch (IOException e) {
74 | e.printStackTrace();
75 | }
76 | }
77 |
78 | public void writeConf(Conf conf) {
79 | try {
80 | String conf_path = Environment.getExternalStorageDirectory().getPath() +
81 | AppConstants.owant_maps +
82 | AppConstants.temp_create_file + "conf.txt";
83 |
84 | writeFile(conf_path, conf.toString());
85 | } catch (IOException e) {
86 | e.printStackTrace();
87 | }
88 | }
89 |
90 | public void makeOwantFile(String saveName) {
91 | MakeZipClient client = new MakeZipClient();
92 | String temp_path = Environment.getExternalStorageDirectory().getPath() +
93 | AppConstants.owant_maps + AppConstants.temp_create_file;
94 | String savePath = Environment.getExternalStorageDirectory().getPath() +
95 | AppConstants.owant_maps + saveName;
96 | if (!savePath.endsWith(".owant")) {
97 | savePath = savePath + ".owant";
98 | }
99 | File saveFile = new File(savePath);
100 | client.create(temp_path, saveFile);
101 |
102 | Log.i(TAG, "创建owant文件成功" + savePath);
103 | }
104 |
105 | public void deleteTemp() {
106 | String temp_path = Environment.getExternalStorageDirectory().getPath()
107 | + AppConstants.owant_maps +
108 | AppConstants.temp_create_file;
109 |
110 | File file = new File(temp_path);
111 | delete(file);
112 | }
113 |
114 | public String readConf(String zipFilePath) {
115 | String info = readZipFile(zipFilePath, AppConstants.conf);
116 | return info;
117 | }
118 |
119 | public Object readContentObject(String zipFilePath) throws ClassNotFoundException, InvalidClassException {
120 | Object o = null;
121 | o = readZipFileObject(zipFilePath, AppConstants.content);
122 | return o;
123 | }
124 |
125 | private void delete(File file) {
126 | if (file.isFile()) {
127 | file.delete();
128 | return;
129 | }
130 | if (file.isDirectory()) {
131 | File[] childFiles = file.listFiles();
132 | if (childFiles == null || childFiles.length == 0) {
133 | file.delete();
134 | return;
135 | }
136 | for (int i = 0; i < childFiles.length; i++) {
137 | delete(childFiles[i]);
138 | }
139 | file.delete();
140 | }
141 | }
142 |
143 | private void writeTreeObject(String filePath, Object object) throws IOException {
144 | FileOutputStream fos = new FileOutputStream(filePath);
145 | ObjectOutputStream oos = new ObjectOutputStream(fos);
146 | oos.writeObject(object);
147 | oos.close();
148 | }
149 |
150 | public TreeModel readTreeObject(String filePath) throws IOException, ClassNotFoundException, InvalidClassException {
151 | TreeModel tree;
152 | FileInputStream fos = new FileInputStream(filePath);
153 | ObjectInputStream ois = new ObjectInputStream(fos);
154 | tree = (TreeModel) ois.readObject();
155 | return tree;
156 | }
157 |
158 | private void writeFile(String path, String fileContext) throws IOException {
159 | FileOutputStream fos = new FileOutputStream(path);
160 | fos.write(fileContext.getBytes("iso8859-1"));
161 | fos.close();
162 | }
163 |
164 | private String readFile(String path) throws IOException {
165 | FileInputStream fis = new FileInputStream(path);
166 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
167 | byte[] buf = new byte[1024];
168 | int len = 0;
169 | while ((len = fis.read(buf)) != -1) {
170 | baos.write(buf, 0, len);
171 | }
172 | fis.close();
173 | baos.close();
174 | return baos.toString();
175 | }
176 |
177 | public boolean hansSDCard() {
178 | return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
179 | }
180 |
181 | private Object readZipFileObject(String filePath, String fileName) throws ClassNotFoundException, InvalidClassException {
182 | InputStream inputStream = null;
183 | ZipFile zipFile = null;
184 | ObjectInputStream objectInputStream = null;
185 | Object targetObject = null;
186 | try {
187 | File file = new File(filePath);
188 | zipFile = new ZipFile(file);
189 | ZipEntry zipEntry = new ZipEntry(fileName);
190 | inputStream = zipFile.getInputStream(zipEntry);
191 | objectInputStream = new ObjectInputStream(inputStream);
192 | targetObject = objectInputStream.readObject();
193 | zipFile.close();
194 | inputStream.close();
195 | objectInputStream.close();
196 | } catch (IOException e) {
197 | e.printStackTrace();
198 | } finally {
199 | if (zipFile != null) {
200 | try {
201 | zipFile.close();
202 | } catch (IOException e) {
203 | e.printStackTrace();
204 | }
205 | }
206 | if (inputStream != null) {
207 | try {
208 | inputStream.close();
209 | } catch (IOException e) {
210 | e.printStackTrace();
211 | }
212 | }
213 | if (objectInputStream != null) {
214 | try {
215 | objectInputStream.close();
216 | } catch (IOException e) {
217 | e.printStackTrace();
218 | }
219 | }
220 | }
221 | return targetObject;
222 | }
223 |
224 | private String readZipFile(String filePath, String fileName) {
225 | StringBuffer buffer = new StringBuffer();
226 | InputStream inputStream = null;
227 | ZipFile zipFile = null;
228 | try {
229 | File file = new File(filePath);
230 | zipFile = new ZipFile(file);
231 | ZipEntry zipEntry = new ZipEntry(fileName);
232 | inputStream = zipFile.getInputStream(zipEntry);
233 | byte[] bytes = new byte[1024];
234 | int len;
235 | while ((len = inputStream.read(bytes)) != -1) {
236 | buffer.append(new String(bytes, 0, len));
237 | }
238 | inputStream.close();
239 | zipFile.close();
240 | } catch (IOException e) {
241 | e.printStackTrace();
242 | } finally {
243 | if (zipFile != null) {
244 | try {
245 | zipFile.close();
246 | } catch (IOException e) {
247 | e.printStackTrace();
248 | }
249 | }
250 | if (inputStream != null) {
251 | try {
252 | inputStream.close();
253 | } catch (IOException e) {
254 | e.printStackTrace();
255 | }
256 | }
257 | }
258 | return buffer.toString();
259 | }
260 |
261 | }
262 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/file/ZipTool.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.file;
2 |
3 | import java.io.File;
4 | import java.io.FileOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.OutputStream;
8 | import java.util.Enumeration;
9 | import java.util.zip.ZipEntry;
10 | import java.util.zip.ZipFile;
11 |
12 | /**
13 | * Created by owant on 17/03/2017.
14 | */
15 |
16 | public class ZipTool {
17 |
18 | /**
19 | * 解压到指定目录
20 | */
21 | public static void unZipFiles(String zipPath, String descDir) throws IOException {
22 | unZipFiles(new File(zipPath), descDir);
23 | }
24 |
25 | /**
26 | * 解压文件到指定目录
27 | */
28 | public static void unZipFiles(File zipFile, String descDir) throws IOException {
29 | File pathFile = new File(descDir);
30 | if (!pathFile.exists()) {
31 | pathFile.mkdirs();
32 | }
33 | ZipFile zip = new ZipFile(zipFile);
34 | for (Enumeration entries = zip.entries(); entries.hasMoreElements(); ) {
35 | ZipEntry entry = (ZipEntry) entries.nextElement();
36 | String zipEntryName = entry.getName();
37 |
38 | System.out.println("zipEntryName="+zipEntryName);
39 |
40 | InputStream in = zip.getInputStream(entry);
41 | String outPath = (descDir + zipEntryName).replaceAll("\\*", "/");
42 |
43 | //判断路径是否存在,不存在则创建文件路径
44 | File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
45 | if (!file.exists()) {
46 | file.mkdirs();
47 | }
48 | //判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
49 | if (new File(outPath).isDirectory()) {
50 | continue;
51 | }
52 | //输出文件路径信息
53 | System.out.println("outPath=" + outPath);
54 |
55 | OutputStream out = new FileOutputStream(outPath);
56 | byte[] buf1 = new byte[1024];
57 | int len;
58 | while ((len = in.read(buf1)) > 0) {
59 | out.write(buf1, 0, len);
60 | }
61 | in.close();
62 | out.close();
63 | }
64 | System.out.println("******************解压完毕********************");
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/line/EaseCubicInterpolator.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.line;
2 |
3 | import android.graphics.PointF;
4 | import android.view.animation.Interpolator;
5 |
6 | /**
7 | * 贝塞尔曲线的加速器
8 | * 网站生成贝斯尔曲线的网站 http://cubic-bezier.com/
9 | * 讲解网站 http://www.tuicool.com/articles/3yANji
10 | *
11 | * 使用列子:new EaseCubicInterpolator(0.31f, 0.85f,0.77f, 0.14f);
12 | */
13 | public class EaseCubicInterpolator implements Interpolator {
14 |
15 | private final static int ACCURACY = 4096;
16 | private int mLastI = 0;
17 | private final PointF mControlPoint1 = new PointF();
18 | private final PointF mControlPoint2 = new PointF();
19 |
20 | /**
21 | * 设置中间两个控制点.
22 | *
23 | * 在线工具: http://cubic-bezier.com/
24 | *
25 | * @param x1
26 | * @param y1
27 | * @param x2
28 | * @param y2
29 | */
30 | public EaseCubicInterpolator(float x1, float y1, float x2, float y2) {
31 | mControlPoint1.x = x1;
32 | mControlPoint1.y = y1;
33 | mControlPoint2.x = x2;
34 | mControlPoint2.y = y2;
35 | }
36 |
37 | @Override
38 | public float getInterpolation(float input) {
39 | float t = input;
40 |
41 | // 近似求解t的值[0,1]
42 | for (int i = mLastI; i < ACCURACY; i++) {
43 | t = 1.0f * i / ACCURACY;
44 | double x = cubicCurves(t, 0, mControlPoint1.x, mControlPoint2.x, 1);
45 | if (x >= input) {
46 | mLastI = i;
47 | break;
48 | }
49 | }
50 |
51 | double value = cubicCurves(t, 0, mControlPoint1.y, mControlPoint2.y, 1);
52 | if (value > 0.999d) {
53 | value = 1;
54 | mLastI = 0;
55 | }
56 | return (float) value;
57 | }
58 |
59 | /**
60 | * 求三次贝塞尔曲线(四个控制点)一个点某个维度的值.
61 | *
62 | * 参考资料: http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/
63 | *
64 | * @param t 取值[0, 1]
65 | * @param value0
66 | * @param value1
67 | * @param value2
68 | * @param value3
69 | * @return
70 | */
71 |
72 | public static double cubicCurves(double t, double value0, double value1,
73 | double value2, double value3) {
74 | double value;
75 | double u = 1 - t;
76 | double tt = t * t;
77 | double uu = u * u;
78 | double uuu = uu * u;
79 | double ttt = tt * t;
80 | value = uuu * value0;
81 | value += 3 * uu * t * value1;
82 | value += 3 * u * tt * value2;
83 | value += ttt * value3;
84 |
85 | return value;
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/line/ReboundInterpolator.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.line;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.animation.Interpolator;
6 |
7 | public class ReboundInterpolator implements Interpolator {
8 | /**
9 | * Value at which the interpolation changes from decelerate to bounce
10 | */
11 | private static final float UNION = 0.2f;
12 |
13 | public ReboundInterpolator() {
14 | }
15 |
16 | public ReboundInterpolator(Context context, AttributeSet attrs) {
17 | }
18 |
19 | @Override
20 | public float getInterpolation(float input) {
21 | if (input < UNION) {
22 | // Decelerate interpolator
23 | float value = mapRange(input, 0f, UNION, 0f, 1f);
24 | return getDecelerateInterpolation(value);
25 | } else {
26 | // Bounce interpolator
27 | float value = mapRange(input, UNION, 1f, 0f, 1f);
28 | return 1f - getBounceInterpolation(value);
29 | }
30 | }
31 |
32 | /**
33 | * @param input Input value
34 | * @return Output value
35 | * @see {@link android.view.animation.DecelerateInterpolator}
36 | */
37 | private float getDecelerateInterpolation(float input) {
38 | return 1.0f - (1.0f - input) * (1.0f - input);
39 | }
40 |
41 | /**
42 | * @param t Input value
43 | * @return Output value
44 | * @see {@link android.view.animation.BounceInterpolator}
45 | */
46 | private float getBounceInterpolation(float t) {
47 | // Change for the interpolation ends in 1.0
48 | if (t == 1f) return 1f;
49 | // _b(t) = t * t * 8
50 | // bs(t) = _b(t) for t < 0.3535
51 | // bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408
52 | // bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644
53 | // bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0
54 | // b(t) = bs(t * 1.1226)
55 | t *= 1.1226f;
56 | if (t < 0.3535f) return bounce(t);
57 | else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f;
58 | else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;
59 | else return bounce(t - 1.0435f) + 0.95f;
60 | }
61 |
62 | private static float bounce(float t) {
63 | return t * t * 8.0f;
64 | }
65 |
66 | /**
67 | * Maps value which is in the range fromLow and fromHigh to it's corresponding value in the range toLow, toHigh
68 | *
69 | * @param value Input value to convert
70 | * @param fromLow Lowest value in the range of input value
71 | * @param fromHigh Highest value in the range of input value
72 | * @param toLow Lowest value in the range of output value
73 | * @param toHigh Highest value in the range of output value
74 | * @return Output value converted to the range
75 | * @see Tylos / Map Range
76 | */
77 | private static float mapRange(float value, float fromLow, float fromHigh, float toLow, float toHigh) {
78 | return toLow + (((value - fromLow) / (fromHigh - fromLow)) * (toHigh - toLow));
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/manager/ThreadPoolManager.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.manager;
2 |
3 | import java.util.concurrent.Executors;
4 | import java.util.concurrent.ThreadPoolExecutor;
5 |
6 | /**
7 | * Created by owant on 17/03/2017.
8 | */
9 |
10 | public class ThreadPoolManager {
11 |
12 | private ThreadPoolExecutor mPoolExecutor;
13 | private final static int default_thread_size = 4;
14 |
15 | private static class ThreadPoolManagerHolder {
16 | private static ThreadPoolManager instance = new ThreadPoolManager();
17 | }
18 |
19 | private ThreadPoolManager() {
20 | mPoolExecutor = (ThreadPoolExecutor) Executors
21 | .newFixedThreadPool(getBestThreadSize());
22 | }
23 |
24 | private int getBestThreadSize() {
25 | return default_thread_size;
26 | }
27 |
28 | public static ThreadPoolManager getInstance() {
29 | return ThreadPoolManagerHolder.instance;
30 | }
31 |
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/model/CurrentFileModel.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.model;
2 |
3 | /**
4 | * Created by owant on 27/02/2017.
5 | */
6 |
7 | public class CurrentFileModel {
8 | //文件名字
9 | public String fileName;
10 | //修改时间
11 | public String editTime;
12 | //文件路径
13 | public String filePath;
14 | //图片跟节点
15 | public String mapRoot;
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/model/ForTreeItem.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.model;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * Created by owant on 09/03/2017.
7 | */
8 |
9 | public interface ForTreeItem> extends Serializable{
10 | void next(int msg, T next);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/model/NodeModel.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.model;
2 |
3 | import java.io.Serializable;
4 | import java.util.LinkedList;
5 |
6 | /**
7 | * Created by owant on 09/02/2017.
8 | */
9 | public class NodeModel implements Serializable {
10 |
11 |
12 | /**
13 | * the parent node,if root node parent node=null;
14 | */
15 | public NodeModel parentNode;
16 |
17 | /**
18 | * the data value
19 | */
20 | public T value;
21 |
22 | /**
23 | * have the child nodes
24 | */
25 | public LinkedList> childNodes;
26 |
27 | /**
28 | * focus tag for the tree add nodes
29 | */
30 | public transient boolean focus = false;
31 |
32 | /**
33 | * index of the tree floor
34 | */
35 | public int floor;
36 |
37 | public boolean hidden = false;
38 |
39 | public NodeModel(T value) {
40 | this.value = value;
41 | this.childNodes = new LinkedList<>();
42 |
43 | this.focus = false;
44 | this.parentNode = null;
45 | }
46 |
47 | public NodeModel getParentNode() {
48 | return parentNode;
49 | }
50 |
51 | public void setParentNode(NodeModel parentNode) {
52 | this.parentNode = parentNode;
53 | }
54 |
55 | public T getValue() {
56 | return value;
57 | }
58 |
59 | public void setValue(T value) {
60 | this.value = value;
61 | }
62 |
63 | public LinkedList> getChildNodes() {
64 | return childNodes;
65 | }
66 |
67 | public void setChildNodes(LinkedList> childNodes) {
68 | this.childNodes = childNodes;
69 | }
70 |
71 | public boolean isFocus() {
72 | return focus;
73 | }
74 |
75 | public void setFocus(boolean focus) {
76 | this.focus = focus;
77 | }
78 |
79 | public int getFloor() {
80 | return floor;
81 | }
82 |
83 | public void setFloor(int floor) {
84 | this.floor = floor;
85 | }
86 |
87 | public boolean isHidden() {
88 | return hidden;
89 | }
90 |
91 | public void setHidden(boolean hidden) {
92 | this.hidden = hidden;
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/model/TreeModel.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.model;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 | import java.io.ObjectInputStream;
7 | import java.io.ObjectOutputStream;
8 | import java.io.Serializable;
9 | import java.util.ArrayDeque;
10 | import java.util.ArrayList;
11 | import java.util.Deque;
12 | import java.util.LinkedList;
13 | import java.util.Stack;
14 |
15 | /**
16 | * Created by owant on 09/02/2017.
17 | */
18 | public class TreeModel implements Serializable {
19 |
20 | /**
21 | * the root for the tree
22 | */
23 | private NodeModel rootNode;
24 |
25 | /**
26 | * 模型里的接口是不用序列号的
27 | */
28 |
29 | private transient ForTreeItem> mForTreeItem;
30 |
31 | public TreeModel(NodeModel rootNode) {
32 | this.rootNode = rootNode;
33 | }
34 |
35 | /**
36 | * add the node in some father node
37 | *
38 | * @param start
39 | * @param nodes
40 | */
41 | public void addNode(NodeModel start, NodeModel... nodes) {
42 | int index = 1;
43 | NodeModel temp = start;
44 | if (temp.getParentNode() != null) {
45 | index = temp.getParentNode().floor;
46 | }
47 |
48 | LinkedList> childNodes = temp.getChildNodes();
49 |
50 | for (NodeModel t : nodes) {
51 | t.setParentNode(start);
52 | t.setFloor(index);
53 |
54 | //校验是否存在
55 | boolean exist = false;
56 | for (NodeModel hash : childNodes) {
57 | if (hash == t) {
58 | exist = true;
59 | continue;
60 | }
61 | }
62 | if (!exist)
63 | start.getChildNodes().add(t);
64 | }
65 | }
66 |
67 | public boolean removeNode(NodeModel starNode, NodeModel deleteNote) {
68 | boolean rm = false;
69 | int size = starNode.getChildNodes().size();
70 | if (size > 0) {
71 | rm = starNode.getChildNodes().remove(deleteNote);
72 | }
73 | return rm;
74 | }
75 |
76 | public boolean inTree(NodeModel starNode, NodeModel deleteNote) {
77 | boolean in = false;
78 | Deque> queue = new ArrayDeque<>();
79 | NodeModel rootNode = starNode;
80 | queue.add(rootNode);
81 |
82 | while (!queue.isEmpty()) {
83 | rootNode = (NodeModel) queue.poll();
84 | if (rootNode == deleteNote) {
85 | in = true;
86 | }
87 |
88 | LinkedList> childNodes = rootNode.getChildNodes();
89 | if (childNodes.size() > 0) {
90 | for (NodeModel item : childNodes) {
91 | queue.add(item);
92 | }
93 | }
94 | }
95 | return in;
96 | }
97 |
98 | public NodeModel getRootNode() {
99 | return rootNode;
100 | }
101 |
102 | public void setRootNode(NodeModel rootNode) {
103 | this.rootNode = rootNode;
104 | }
105 |
106 | /**
107 | * 同一个父节点的上下
108 | *
109 | * @param midPreNode
110 | * @return
111 | */
112 | private NodeModel getLowNode(NodeModel midPreNode) {
113 | NodeModel find = null;
114 | NodeModel parentNode = midPreNode.getParentNode();
115 |
116 | if (parentNode != null && parentNode.getChildNodes().size() >= 2) {
117 | Deque> queue = new ArrayDeque<>();
118 | NodeModel rootNode = parentNode;
119 | queue.add(rootNode);
120 | boolean up = false;
121 | while (!queue.isEmpty()) {
122 |
123 | rootNode = (NodeModel) queue.poll();
124 | if (up) {
125 | if (rootNode.getFloor() == midPreNode.getFloor()) {
126 | find = rootNode;
127 | }
128 | break;
129 | }
130 |
131 | //到了该元素
132 | if (rootNode == midPreNode) up = true;
133 | LinkedList> childNodes = rootNode.getChildNodes();
134 | if (childNodes.size() > 0) {
135 | for (NodeModel item : childNodes) {
136 | queue.add(item);
137 | }
138 | }
139 | }
140 | }
141 | return find;
142 | }
143 |
144 | private NodeModel getPreNode(NodeModel midPreNode) {
145 |
146 | NodeModel parentNode = midPreNode.getParentNode();
147 | NodeModel find = null;
148 |
149 | if (parentNode != null && parentNode.getChildNodes().size() > 0) {
150 |
151 | Deque> queue = new ArrayDeque<>();
152 | NodeModel rootNode = parentNode;
153 | queue.add(rootNode);
154 |
155 | while (!queue.isEmpty()) {
156 | rootNode = (NodeModel) queue.poll();
157 | //到了该元素
158 | if (rootNode == midPreNode) {
159 | //返回之前的值
160 | break;
161 | }
162 |
163 | find = rootNode;
164 | LinkedList> childNodes = rootNode.getChildNodes();
165 | if (childNodes.size() > 0) {
166 | for (NodeModel item : childNodes) {
167 | queue.add(item);
168 | }
169 | }
170 | }
171 |
172 | if (find != null && find.getFloor() != midPreNode.getFloor()) {
173 | find = null;
174 | }
175 | }
176 | return find;
177 | }
178 |
179 | public ArrayList> getAllLowNodes(NodeModel addNode) {
180 | ArrayList> array = new ArrayList<>();
181 | NodeModel parentNode = addNode.getParentNode();
182 | while (parentNode != null) {
183 | NodeModel lowNode = getLowNode(parentNode);
184 | while (lowNode != null) {
185 | array.add(lowNode);
186 | lowNode = getLowNode(lowNode);
187 | }
188 | parentNode = parentNode.getParentNode();
189 | }
190 | return array;
191 | }
192 |
193 | public ArrayList> getAllPreNodes(NodeModel addNode) {
194 | ArrayList> array = new ArrayList<>();
195 | NodeModel parentNode = addNode.getParentNode();
196 | while (parentNode != null) {
197 | NodeModel lowNode = getPreNode(parentNode);
198 | while (lowNode != null) {
199 | array.add(lowNode);
200 | lowNode = getPreNode(lowNode);
201 | }
202 | parentNode = parentNode.getParentNode();
203 | }
204 | return array;
205 | }
206 |
207 | public LinkedList> getNodeChildNodes(NodeModel node) {
208 | return node.getChildNodes();
209 | }
210 |
211 | public void ergodicTreeInDeep(int msg) {
212 | Stack> stack = new Stack<>();
213 | NodeModel rootNode = getRootNode();
214 | stack.add(rootNode);
215 | while (!stack.isEmpty()) {
216 | NodeModel pop = stack.pop();
217 | if (mForTreeItem != null) {
218 | mForTreeItem.next(msg, pop);
219 | }
220 | LinkedList> childNodes = pop.getChildNodes();
221 | for (NodeModel item : childNodes) {
222 | stack.add(item);
223 | }
224 | }
225 | }
226 |
227 | public void ergodicTreeInWith(int msg) {
228 | Deque> queue = new ArrayDeque<>();
229 | NodeModel rootNode = getRootNode();
230 | queue.add(rootNode);
231 | while (!queue.isEmpty()) {
232 | rootNode = (NodeModel) queue.poll();
233 | if (mForTreeItem != null) {
234 | mForTreeItem.next(msg, rootNode);
235 | }
236 | LinkedList> childNodes = rootNode.getChildNodes();
237 | if (childNodes.size() > 0) {
238 | for (NodeModel item : childNodes) {
239 | queue.add(item);
240 | }
241 | }
242 | }
243 | }
244 |
245 | public void addForTreeItem(ForTreeItem> forTreeItem) {
246 | this.mForTreeItem = forTreeItem;
247 | }
248 |
249 | public Object deepClone() throws IOException, ClassNotFoundException {
250 | ByteArrayOutputStream bo=new ByteArrayOutputStream();
251 | ObjectOutputStream oo=new ObjectOutputStream(bo);
252 | oo.writeObject(this);
253 |
254 | ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
255 | ObjectInputStream oi=new ObjectInputStream(bi);
256 | return(oi.readObject());
257 | }
258 |
259 |
260 |
261 | }
262 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/net/BaseResponse.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.net;
2 |
3 | /**
4 | * Created by owant on 17/03/2017.
5 | */
6 |
7 | public class BaseResponse {
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/test/ExampleCreator.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.test;
2 |
3 | import com.owant.thinkmap.file.Conf;
4 | import com.owant.thinkmap.file.OwantFileCreate;
5 | import com.owant.thinkmap.model.NodeModel;
6 | import com.owant.thinkmap.model.TreeModel;
7 | import com.owant.thinkmap.util.AndroidUtil;
8 |
9 | import java.text.SimpleDateFormat;
10 | import java.util.Calendar;
11 | import java.util.Date;
12 | import java.util.Locale;
13 |
14 | /**
15 | * Created by owant on 31/03/2017.
16 | */
17 |
18 | public class ExampleCreator {
19 |
20 | public static void main(String[] args) {
21 |
22 | }
23 |
24 |
25 | public static String format = "NodeModel node{0} = new NodeModel<>(\"{0}\");";
26 |
27 | public static void createTreeNodes() {
28 | for (char i = 'A'; i < 'Z'; i++) {
29 | String value = format;
30 | value = value.replace("{0}", i + "");
31 | System.out.println(value);
32 | }
33 | }
34 |
35 | public static void createExampleMapVersion() {
36 |
37 | NodeModel root = new NodeModel<>("ThinkMap版本情况");
38 | TreeModel treeModel = new TreeModel<>(root);
39 |
40 | NodeModel version1 = new NodeModel<>("V1.0.1");
41 | NodeModel version2 = new NodeModel<>("V1.0.2");
42 | NodeModel version3 = new NodeModel<>("V1.0.3");
43 | NodeModel version4 = new NodeModel<>("V1.0.4");
44 |
45 | treeModel.addNode(root, version1, version2, version3, version4);
46 |
47 | //版本1的情况
48 | NodeModel v1_draw_tree = new NodeModel<>("绘制树形结构");
49 | NodeModel v1_add_child_note = new NodeModel<>("添加子节点");
50 | NodeModel v1_add_node = new NodeModel<>("添加同层节点");
51 | NodeModel v1_front = new NodeModel<>("对焦中心");
52 | NodeModel v1_map_move = new NodeModel<>("视图移动");
53 | NodeModel v1_open_owant_file = new NodeModel<>("打开.owant文件");
54 |
55 | treeModel.addNode(version1, v1_draw_tree, v1_add_child_note,
56 | v1_add_node, v1_front, v1_map_move, v1_open_owant_file);
57 |
58 | //版本2情况
59 | NodeModel v2_fixed_location = new NodeModel<>("Fixed位置错误");
60 | NodeModel v2_add_handle = new NodeModel<>("添加了缩放手势");
61 | NodeModel v2_tree_manager = new NodeModel<>("抽取TreeLayoutManger\n提供更多的Style可能");
62 | NodeModel v2_fixed_click = new NodeModel<>("Fixed长按和点击问题");
63 | NodeModel v2_add_example = new NodeModel<>("添加演示例子");
64 |
65 | treeModel.addNode(version2, v2_fixed_location, v2_add_handle, v2_tree_manager,
66 | v2_tree_manager, v2_fixed_click, v2_add_example);
67 |
68 | //版本3情况
69 | NodeModel v3_android4 = new NodeModel<>("Fixed Android4.0出现BUG");
70 | NodeModel v3_splash = new NodeModel<>("添加欢迎界面");
71 | NodeModel v3_permission = new NodeModel<>("修复动态权限申请问题");
72 | NodeModel v3_review = new NodeModel<>("ReView优化");
73 |
74 | treeModel.addNode(version3, v3_android4, v3_splash, v3_permission, v3_review);
75 |
76 |
77 | //版本4情況
78 | NodeModel v4_fixed_scale_light = new NodeModel<>("Fixed 缩放出现抖动");
79 | NodeModel v4_review = new NodeModel<>("ReView优化,Github上\n建立release分支");
80 | treeModel.addNode(version4, v4_fixed_scale_light, v4_review);
81 |
82 |
83 | //穿件owant文件
84 | OwantFileCreate owantFileCreate = new OwantFileCreate();
85 |
86 | //创建文件夹
87 | owantFileCreate.createOwantMapsDirectory();
88 | //删除临时文件
89 | owantFileCreate.createTempDirectory();
90 | //写入内容
91 | owantFileCreate.writeContent(treeModel);
92 |
93 | Conf conf = new Conf();
94 | Date time = Calendar.getInstance().getTime();
95 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
96 | conf.date = simpleDateFormat.format(time);
97 | conf.app_version = "v1.0.4";
98 | conf.android_version = AndroidUtil.getAndroidSystemVersion();
99 | conf.map_name = treeModel.getRootNode().getValue();
100 |
101 | //写入配置
102 | owantFileCreate.writeConf(conf);
103 | //创建压缩包
104 | owantFileCreate.makeOwantFile("演示-App版本情况");
105 | //删除临时文件
106 | owantFileCreate.deleteTemp();
107 | }
108 |
109 | public static void createExampleHowToUse() {
110 |
111 | NodeModel root = new NodeModel<>("ThinkMap使用教程");
112 | TreeModel treeModel = new TreeModel<>(root);
113 |
114 | NodeModel subNode = new NodeModel<>("SubNode");
115 | NodeModel node = new NodeModel<>("Node");
116 | NodeModel frontView = new NodeModel<>("FrontView");
117 | NodeModel codeMode = new NodeModel<>("CodeMode");
118 |
119 | treeModel.addNode(root, subNode, node, frontView, codeMode);
120 |
121 | NodeModel subNode1 = new NodeModel<>("添加子节点");
122 | NodeModel node1 = new NodeModel<>("添加同层节点");
123 | NodeModel frontView1 = new NodeModel<>("对焦中心");
124 | NodeModel codeMode1 = new NodeModel<>("编码模式");
125 |
126 | treeModel.addNode(subNode, subNode1);
127 | treeModel.addNode(node, node1);
128 | treeModel.addNode(frontView, frontView1);
129 | treeModel.addNode(codeMode, codeMode1);
130 |
131 | //穿件owant文件
132 | OwantFileCreate owantFileCreate = new OwantFileCreate();
133 | owantFileCreate.createOwantMapsDirectory();
134 | owantFileCreate.createTempDirectory();
135 | owantFileCreate.writeContent(treeModel);
136 |
137 | Conf conf = new Conf();
138 | Date time = Calendar.getInstance().getTime();
139 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
140 | conf.date = simpleDateFormat.format(time);
141 | conf.app_version = "v1.0.3";
142 | conf.android_version = AndroidUtil.getAndroidSystemVersion();
143 | conf.map_name = treeModel.getRootNode().getValue();
144 | owantFileCreate.writeConf(conf);
145 | owantFileCreate.makeOwantFile("演示-使用教程");
146 | owantFileCreate.deleteTemp();
147 | }
148 |
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/EditAlertDialog.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.StyleRes;
6 | import android.text.Editable;
7 | import android.text.TextUtils;
8 | import android.view.View;
9 | import android.view.animation.Animation;
10 | import android.view.animation.CycleInterpolator;
11 | import android.view.animation.TranslateAnimation;
12 | import android.widget.Button;
13 | import android.widget.EditText;
14 | import android.widget.ImageView;
15 | import android.widget.RelativeLayout;
16 | import android.widget.TextView;
17 |
18 | import com.owant.thinkmap.AppConstants;
19 | import com.owant.thinkmap.R;
20 | import com.owant.thinkmap.base.BaseAlertDialog;
21 | import com.owant.thinkmap.model.NodeModel;
22 | import com.owant.thinkmap.util.AndroidUtil;
23 | import com.owant.thinkmap.util.LOG;
24 |
25 | import java.util.List;
26 |
27 | /**
28 | * Created by owant on 24/02/2017.
29 | */
30 | public class EditAlertDialog extends BaseAlertDialog {
31 |
32 | private TextView dialog_edit_tv_title;
33 | private EditText dialog_edit_et_input;
34 | private Button dialog_btn_enter;
35 | private Button dialog_btn_delete;
36 | private ImageView dialog_edit_iv_input_clear;
37 | private TextView dialog_edit_tv_had_same_file;
38 | private RelativeLayout dialog_edit_check_state;
39 |
40 | private String conditonDeleteTextValue;
41 | private String conditonEnterTextValue;
42 |
43 | private EnterCallBack enterCallBack;
44 | private DeleteCallBack deleteCallBack;
45 |
46 | private NodeModel nodeModel;
47 | private List checkLists;
48 |
49 |
50 | public EditAlertDialog(@NonNull Context context) {
51 | this(context, 0);
52 | }
53 |
54 | public EditAlertDialog(@NonNull Context context, @StyleRes int themeResId) {
55 | super(context, R.style.DivDialog);
56 | }
57 |
58 | @Override
59 | protected void onBaseBindView() {
60 | dialog_edit_tv_title = (TextView) findViewById(R.id.dialog_edit_tv_title);
61 | dialog_edit_et_input = (EditText) findViewById(R.id.dialog_edit_et_input);
62 | dialog_btn_enter = (Button) findViewById(R.id.dialog_btn_enter);
63 | dialog_btn_delete = (Button) findViewById(R.id.dialog_btn_delete);
64 | dialog_edit_iv_input_clear = (ImageView) findViewById(R.id.dialog_edit_iv_input_clear);
65 | dialog_edit_check_state = (RelativeLayout) findViewById(R.id.dialog_edit_check_state);
66 | dialog_edit_tv_had_same_file = (TextView) findViewById(R.id.dialog_edit_tv_had_same_file);
67 |
68 | if (dialog_btn_enter != null) {
69 | dialog_btn_enter.setOnClickListener(new View.OnClickListener() {
70 | @Override
71 | public void onClick(View v) {
72 | if (enterCallBack != null) {
73 | String value = getInput().toString() + "";
74 | //同名文件提示更改
75 | if (checkLists != null) {
76 | if (AppConstants.CONFIG_DEBUG) {
77 | for (String str : checkLists) {
78 | LOG.jLogi("list=%s", str);
79 | }
80 | }
81 |
82 | LOG.jLogi("value=%s", value);
83 | if (checkLists.contains(value)) {
84 | dialog_edit_tv_had_same_file.setVisibility(View.VISIBLE);
85 | dialog_edit_tv_had_same_file.setText(getContext().
86 | getResources().getString(R.string.same_name_file));
87 | Animation shake = new TranslateAnimation(0, 10, 0, 0);
88 | shake.setDuration(1000);
89 | //重三次
90 | shake.setInterpolator(new CycleInterpolator(7));
91 | dialog_edit_check_state.startAnimation(shake);
92 | return;
93 |
94 | } else if (TextUtils.isEmpty(value)) {
95 | dialog_edit_tv_had_same_file.setVisibility(View.VISIBLE);
96 | dialog_edit_tv_had_same_file.setText(getContext().
97 | getResources().getString(R.string.file_name_empty));
98 |
99 | Animation shake = new TranslateAnimation(0, 10, 0, 0);
100 | shake.setDuration(1000);
101 | //重三次
102 | shake.setInterpolator(new CycleInterpolator(7));
103 | dialog_edit_check_state.startAnimation(shake);
104 | return;
105 | } else {
106 | dialog_edit_tv_had_same_file.setVisibility(View.INVISIBLE);
107 | }
108 | }
109 |
110 |
111 | enterCallBack.onEdit(value);
112 | AndroidUtil.hideKeyboard(getContext(), dialog_edit_et_input);
113 | }
114 | }
115 | });
116 | }
117 |
118 | if (dialog_edit_iv_input_clear != null) {
119 | dialog_edit_iv_input_clear.setOnClickListener(new View.OnClickListener() {
120 | @Override
121 | public void onClick(View v) {
122 | setInput("");
123 | }
124 | });
125 | }
126 |
127 | if (dialog_btn_delete != null) {
128 | dialog_btn_delete.setOnClickListener(new View.OnClickListener() {
129 | @Override
130 | public void onClick(View v) {
131 | if (deleteCallBack != null) {
132 |
133 | if (dialog_edit_tv_title.getText() == EditAlertDialog.this.getContext()
134 | .getResources().getString(R.string.save_file)) {
135 | deleteCallBack.onDelete();
136 |
137 | } else if (nodeModel != null) {
138 | //根节点不能进行删除
139 | NodeModel parentNode = nodeModel.getParentNode();
140 | if (parentNode != null) {
141 | deleteCallBack.onDeleteModel(nodeModel);
142 | }
143 | }
144 |
145 | }
146 | dismiss();
147 | AndroidUtil.hideKeyboard(getContext(), dialog_edit_et_input);
148 | }
149 | });
150 | }
151 | }
152 |
153 | public void setDivTitle(String title) {
154 | dialog_edit_tv_title.setText(title);
155 | }
156 |
157 | private Editable getInput() {
158 | return dialog_edit_et_input.getText();
159 | }
160 |
161 | public void setInput(String value) {
162 | if (dialog_edit_et_input != null) {
163 | dialog_edit_et_input.setText(value);
164 | }
165 | }
166 |
167 | public void setConditionEnterTextValue(String conditionEnterTextValue) {
168 | this.conditonEnterTextValue = conditionEnterTextValue;
169 | if (dialog_btn_enter != null) {
170 | dialog_btn_enter.setText(conditionEnterTextValue);
171 | }
172 | }
173 |
174 | public void setConditionDeleteTextValue(String conditionDeleteTextValue) {
175 | this.conditonDeleteTextValue = conditionDeleteTextValue;
176 | if (dialog_btn_delete != null) {
177 | dialog_btn_delete.setText(conditionDeleteTextValue);
178 | }
179 | }
180 |
181 | public void setCheckLists(List checkLists) {
182 | this.checkLists = checkLists;
183 | }
184 |
185 | public void setNodeModel(NodeModel nodeModel) {
186 | this.nodeModel = nodeModel;
187 | if (nodeModel.getParentNode() == null) {
188 | if (dialog_btn_delete != null) {
189 | dialog_btn_delete.setEnabled(false);
190 | }
191 | } else {
192 | if (dialog_btn_delete != null) {
193 | dialog_btn_delete.setEnabled(true);
194 | }
195 | }
196 | }
197 |
198 | public void addEnterCallBack(EnterCallBack callBack) {
199 | this.enterCallBack = callBack;
200 | }
201 |
202 | public void addDeleteCallBack(DeleteCallBack callBack) {
203 | deleteCallBack = callBack;
204 | }
205 |
206 | public void clearInput() {
207 | setInput("");
208 | }
209 |
210 | public interface EnterCallBack {
211 | void onEdit(String value);
212 | }
213 |
214 | public interface DeleteCallBack {
215 | void onDeleteModel(NodeModel nodeModel);
216 |
217 | void onDelete();
218 | }
219 |
220 | }
221 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/SplashActivity.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui;
2 |
3 | import android.content.Intent;
4 | import android.content.pm.PackageManager;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.support.annotation.NonNull;
8 | import android.support.annotation.Nullable;
9 | import android.support.annotation.RequiresApi;
10 | import android.support.v4.app.ActivityCompat;
11 | import android.support.v4.content.ContextCompat;
12 | import android.widget.Toast;
13 |
14 | import com.owant.thinkmap.AppPermissions;
15 | import com.owant.thinkmap.R;
16 | import com.owant.thinkmap.base.BaseActivity;
17 | import com.owant.thinkmap.ui.workspace.WorkSpaceActivity;
18 | import com.owant.thinkmap.util.AndroidUtil;
19 |
20 | public class SplashActivity extends BaseActivity {
21 |
22 | @Override
23 | protected void onBaseIntent() {
24 |
25 | }
26 |
27 | @Override
28 | protected void onBasePreLayout() {
29 |
30 | }
31 |
32 | @Override
33 | protected int onBaseLayoutId(@Nullable Bundle savedInstanceState) {
34 | return R.layout.activity_splash;
35 | }
36 |
37 | @Override
38 | protected void onBaseBindView() {
39 |
40 | if (AndroidUtil.isMPermission()) {
41 | if (ContextCompat.checkSelfPermission(SplashActivity.this,
42 | AppPermissions.permission_storage[0]) != PackageManager.PERMISSION_GRANTED ||
43 | ContextCompat.checkSelfPermission(SplashActivity.this,
44 | AppPermissions.permission_storage[1]) != PackageManager.PERMISSION_GRANTED) {
45 |
46 | requestStoragePermission();
47 |
48 | } else {
49 | intentToWorkSpace();
50 | }
51 |
52 | } else {
53 |
54 | intentToWorkSpace();
55 | }
56 |
57 | }
58 |
59 | private void intentToWorkSpace() {
60 | new Thread(new Runnable() {
61 |
62 | @Override
63 | public void run() {
64 | try {
65 | Thread.sleep(1200);
66 | Intent intent = new Intent(SplashActivity.this, WorkSpaceActivity.class);
67 | startActivity(intent);
68 | SplashActivity.this.finish();
69 |
70 | } catch (InterruptedException e) {
71 | e.printStackTrace();
72 | }
73 | }
74 | }).start();
75 | }
76 |
77 | @Override
78 | protected void onLoadData() {
79 |
80 | }
81 |
82 | /**
83 | * 请求内存卡权限
84 | */
85 | @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
86 | private void requestStoragePermission() {
87 | ActivityCompat.requestPermissions(SplashActivity.this
88 | , AppPermissions.permission_storage,
89 | AppPermissions.request_permission_storage);
90 | }
91 |
92 | @Override
93 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
94 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
95 | if (requestCode == AppPermissions.request_permission_storage) {
96 | if (AndroidUtil.verifyPermissions(grantResults)) {
97 | intentToWorkSpace();
98 | } else {
99 | Toast.makeText(this, "the permission denied!", Toast.LENGTH_SHORT).show();
100 | }
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/about/AboutUsActivity.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui.about;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.view.MenuItem;
6 |
7 | import com.owant.thinkmap.R;
8 | import com.owant.thinkmap.base.BaseActivity;
9 |
10 | /**
11 | * Created by owant on 30/03/2017.
12 | */
13 |
14 | public class AboutUsActivity extends BaseActivity {
15 |
16 | @Override
17 | protected void onBaseIntent() {
18 |
19 | }
20 |
21 | @Override
22 | protected void onBasePreLayout() {
23 |
24 | }
25 |
26 | @Override
27 | protected int onBaseLayoutId(@Nullable Bundle savedInstanceState) {
28 | return R.layout.activity_about_us;
29 | }
30 |
31 | @Override
32 | protected void onBaseBindView() {
33 | getSupportActionBar().setTitle(R.string.about);
34 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
35 | }
36 |
37 | @Override
38 | protected void onLoadData() {
39 |
40 | }
41 |
42 | @Override
43 | public boolean onOptionsItemSelected(MenuItem item) {
44 | int itemId = item.getItemId();
45 | switch (itemId) {
46 | case android.R.id.home:
47 | finish();
48 | break;
49 | }
50 | return super.onOptionsItemSelected(item);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/codemode/CodeModeActivity.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui.codemode;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 |
6 | import com.owant.thinkmap.R;
7 | import com.owant.thinkmap.base.BaseActivity;
8 |
9 | /**
10 | * Created by owant on 14/03/2017.
11 | */
12 |
13 | public class CodeModeActivity extends BaseActivity {
14 |
15 | @Override
16 | protected void onBaseIntent() {
17 |
18 | }
19 |
20 | @Override
21 | protected void onBasePreLayout() {
22 |
23 | }
24 |
25 | @Override
26 | protected int onBaseLayoutId(@Nullable Bundle savedInstanceState) {
27 | return R.layout.activity_code_model;
28 | }
29 |
30 | @Override
31 | protected void onBaseBindView() {
32 |
33 | }
34 |
35 | @Override
36 | protected void onLoadData() {
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/editmap/EditMapContract.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui.editmap;
2 |
3 | import com.owant.thinkmap.base.BasePresenter;
4 | import com.owant.thinkmap.base.BaseView;
5 | import com.owant.thinkmap.model.NodeModel;
6 | import com.owant.thinkmap.model.TreeModel;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * Created by owant on 21/03/2017.
12 | */
13 |
14 | public interface EditMapContract {
15 |
16 | interface Presenter extends BasePresenter {
17 |
18 | /**
19 | * 设置读取的文件路径
20 | */
21 | void setLoadMapPath(String path);
22 |
23 | /**
24 | * 刷新文件路径下的owant文件集合
25 | */
26 | void refreshOwantFilesLists();
27 |
28 | /**
29 | * 读取owant文件
30 | */
31 | void readOwantFile();
32 |
33 | /**
34 | * 创建默认的TreeModel
35 | */
36 | void createDefaultTreeModel();
37 |
38 | /**
39 | * 添加节点
40 | */
41 | void addNote();
42 |
43 | /**
44 | * 添加子节点
45 | */
46 | void addSubNote();
47 |
48 | /**
49 | * 编辑节点
50 | */
51 | void editNote();
52 |
53 | /**
54 | * 对焦中心
55 | */
56 | void focusMid();
57 |
58 | /**
59 | * 保存文件
60 | */
61 | void saveFile();
62 |
63 | /**
64 | * 进行保存
65 | */
66 | void doSaveFile(String fileName);
67 |
68 | /**
69 | * 设置树形模型
70 | *
71 | * @param treeModel
72 | */
73 | void setTreeModel(TreeModel treeModel);
74 |
75 | /**
76 | * 获取树形模型
77 | *
78 | * @return 树形模型
79 | */
80 | TreeModel getTreeModel();
81 |
82 | /**
83 | * 获取文件目录下的owant文件集合
84 | *
85 | * @return owant文件集合
86 | */
87 | List getOwantLists();
88 |
89 | String getSaveInput();
90 | }
91 |
92 | interface View extends BaseView {
93 |
94 | /**
95 | * 显示加载文件
96 | */
97 | void showLoadingFile();
98 |
99 | /**
100 | * 设置树形结构数据
101 | *
102 | * @param treeModel
103 | */
104 | void setTreeViewData(TreeModel treeModel);
105 |
106 | /**
107 | * 隐藏加载数据
108 | */
109 | void hideLoadingFile();
110 |
111 | /**
112 | * 显示添加节点
113 | */
114 | void showAddNoteDialog();
115 |
116 | /**
117 | * 显示添加子节点
118 | */
119 | void showAddSubNoteDialog();
120 |
121 | /**
122 | * 显示编辑节点
123 | */
124 | void showEditNoteDialog();
125 |
126 | /**
127 | * 显示保存数据
128 | *
129 | * @param fileName
130 | */
131 | void showSaveFileDialog(String fileName);
132 |
133 | /**
134 | * 对焦中心
135 | */
136 | void focusingMid();
137 |
138 | /**
139 | * 获得默认root节点的text
140 | *
141 | * @return
142 | */
143 | String getDefaultPlanStr();
144 |
145 | /**
146 | * 获得最近对焦
147 | *
148 | * @return
149 | */
150 | NodeModel getCurrentFocusNode();
151 |
152 | /**
153 | * 获取Plan的默认字符
154 | *
155 | * @return My Plan
156 | */
157 | String getDefaultSaveFilePath();
158 |
159 | /**
160 | * 获得app的版本
161 | *
162 | * @return 版本号
163 | */
164 | String getAppVersion();
165 |
166 | void finishActivity();
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/editmap/EditMapPresenter.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui.editmap;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.owant.thinkmap.AppConstants;
6 | import com.owant.thinkmap.file.Conf;
7 | import com.owant.thinkmap.file.OwantFileCreate;
8 | import com.owant.thinkmap.model.NodeModel;
9 | import com.owant.thinkmap.model.TreeModel;
10 | import com.owant.thinkmap.util.AndroidUtil;
11 | import com.owant.thinkmap.util.LOG;
12 | import com.owant.thinkmap.util.StringTool;
13 |
14 | import java.io.File;
15 | import java.io.IOException;
16 | import java.io.InvalidClassException;
17 | import java.text.SimpleDateFormat;
18 | import java.util.ArrayList;
19 | import java.util.Calendar;
20 | import java.util.Date;
21 | import java.util.LinkedList;
22 | import java.util.List;
23 | import java.util.Locale;
24 | import java.util.Stack;
25 |
26 | /**
27 | * Created by owant on 21/03/2017.
28 | */
29 | public class EditMapPresenter implements EditMapContract.Presenter {
30 |
31 | private EditMapContract.View mView;
32 |
33 | private boolean mIsCreate;
34 | private String mFilePath;
35 | private String mDefaultFilePath;
36 | private String mFileName;
37 | private TreeModel mTreeModel;
38 |
39 | private TreeModel mOldTreeModel;
40 |
41 | private String[] mOwantFilesArray;
42 |
43 | public EditMapPresenter(EditMapContract.View view) {
44 | mView = view;
45 | }
46 |
47 | @Override
48 | public void start() {
49 | mIsCreate = true;
50 | mFileName = mView.getDefaultPlanStr();
51 | mView.showLoadingFile();
52 | }
53 |
54 | @Override
55 | public void onRecycle() {
56 | mOwantFilesArray = null;
57 | mTreeModel = null;
58 | }
59 |
60 | @Override
61 | public void setLoadMapPath(String path) {
62 | // 获取到是否是编辑文件
63 | // 文件的名字
64 | // 文件路径下的owant file lists
65 | mIsCreate = false;
66 |
67 | LOG.jLogi("owant file path=%s", path);
68 | mFilePath = path;
69 |
70 | String saveFileName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
71 | mFileName = saveFileName;
72 |
73 | refreshOwantFilesLists();
74 | }
75 |
76 | @Override
77 | public void createDefaultTreeModel() {
78 | NodeModel plan = new NodeModel<>(mView.getDefaultPlanStr());
79 | mTreeModel = new TreeModel<>(plan);
80 | mView.setTreeViewData(mTreeModel);
81 | refreshOwantFilesLists();
82 | }
83 |
84 | @Override
85 | public void refreshOwantFilesLists() {
86 | if (!TextUtils.isEmpty(mFilePath)) {
87 | File editFilePath = new File(mFilePath);
88 | String[] lists = editFilePath.getParentFile().list();
89 |
90 | //设置存在的owant集合
91 | sortFiles(lists);
92 |
93 | } else {
94 | // 默认文件路径
95 | mDefaultFilePath = mView.getDefaultSaveFilePath();
96 | File file = new File(mDefaultFilePath);
97 | if (!file.exists()) {
98 | file.mkdirs();
99 | LOG.jLogi("create default file path=%s", "true");
100 | }
101 | LOG.jLogi("defaultFilePath=%s", mDefaultFilePath);
102 | if (file.exists()) {
103 | String[] lists = file.list();
104 | sortFiles(lists);
105 | } else {
106 | LOG.jLoge("defaultPath is empty!");
107 | }
108 | }
109 | }
110 |
111 | private void sortFiles(String[] lists) {
112 | ArrayList owantFiles = new ArrayList<>();
113 | for (String fileName : lists) {
114 | if (fileName.endsWith(".owant")) {
115 | LOG.jLogi("file=%s", fileName);
116 | fileName = fileName.substring(0, fileName.lastIndexOf("."));
117 | if (!StringTool.isEmpty(fileName)) {
118 | owantFiles.add(fileName);
119 | }
120 |
121 | //编辑模式,不能修改文件名字
122 | if (!mIsCreate) {
123 | owantFiles.remove(fileName);
124 | }
125 | }
126 | }
127 |
128 | if (owantFiles.size() > 0) {
129 | mOwantFilesArray = owantFiles.toArray(new String[owantFiles.size()]);
130 | if (AppConstants.CONFIG_DEBUG) {
131 | for (String str : mOwantFilesArray) {
132 | LOG.jLogi("mOwantFilesArray str=%s", str);
133 | }
134 | }
135 | }
136 |
137 | }
138 |
139 | @Override
140 | public void readOwantFile() {
141 | //读取owant文件
142 | if (!StringTool.isEmpty(mFilePath)) {
143 | try {
144 | OwantFileCreate owantFileCreate = new OwantFileCreate();
145 | LOG.jLogi("filePath=%s", mFilePath);
146 | Object o = owantFileCreate.readContentObject(mFilePath);
147 | TreeModel tree = (TreeModel) o;
148 | mTreeModel = tree;
149 | mView.setTreeViewData(mTreeModel);
150 |
151 | mIsCreate = false;
152 | //拷贝一份
153 | mOldTreeModel = (TreeModel) mTreeModel.deepClone();
154 |
155 | } catch (ClassNotFoundException e) {
156 | e.printStackTrace();
157 | } catch (InvalidClassException e) {
158 | e.printStackTrace();
159 | } catch (IOException e) {
160 | e.printStackTrace();
161 | }
162 | }
163 | }
164 |
165 | @Override
166 | public void addNote() {
167 | mView.showAddNoteDialog();
168 | }
169 |
170 | @Override
171 | public void addSubNote() {
172 | mView.showAddSubNoteDialog();
173 | }
174 |
175 | @Override
176 | public void editNote() {
177 | mView.showEditNoteDialog();
178 | }
179 |
180 | @Override
181 | public void focusMid() {
182 | mView.focusingMid();
183 | }
184 |
185 | @Override
186 | public void saveFile() {
187 | //TODO 进行判断是否改变了文本
188 | //只有在编剧模式下才进行判断其他的跳过
189 | boolean equals = false;
190 | if (!mIsCreate) {
191 | //进行判断
192 | equals = isEqualsOldTreeModel();
193 | }
194 |
195 | if (equals) {
196 | LOG.jLogi("no change =%s", "true");
197 | mView.finishActivity();
198 | } else {
199 | LOG.jLogi("change =%s", "false");
200 | mView.showSaveFileDialog(mFilePath);
201 | }
202 | }
203 |
204 | private boolean isEqualsOldTreeModel() {
205 | boolean equals = false;
206 | TreeModel temp = mTreeModel;
207 | TreeModel compareTemp = mOldTreeModel;
208 |
209 | StringBuffer tempBuffer = new StringBuffer();
210 | Stack> stack = new Stack<>();
211 | NodeModel rootNode = temp.getRootNode();
212 | stack.add(rootNode);
213 | while (!stack.isEmpty()) {
214 | NodeModel pop = stack.pop();
215 | tempBuffer.append(pop.value);
216 | LinkedList> childNodes = pop.getChildNodes();
217 | for (NodeModel item : childNodes) {
218 | stack.add(item);
219 | }
220 | }
221 |
222 | StringBuffer compareTempBuffer = new StringBuffer();
223 | Stack> stackThis = new Stack<>();
224 | NodeModel rootNodeThis = compareTemp.getRootNode();
225 | stackThis.add(rootNodeThis);
226 | while (!stackThis.isEmpty()) {
227 | NodeModel pop = stackThis.pop();
228 | compareTempBuffer.append(pop.value);
229 | LinkedList> childNodes = pop.getChildNodes();
230 | for (NodeModel item : childNodes) {
231 | stackThis.add(item);
232 | }
233 | }
234 |
235 | if (compareTempBuffer.toString().equals(tempBuffer.toString())) {
236 | equals = true;
237 | }
238 | return equals;
239 | }
240 |
241 | @Override
242 | public void doSaveFile(String fileName) {
243 | OwantFileCreate owantFileCreate = new OwantFileCreate();
244 | owantFileCreate.createOwantMapsDirectory();
245 | owantFileCreate.createTempDirectory();
246 |
247 | Conf conf = new Conf();
248 | Date time = Calendar.getInstance().getTime();
249 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
250 | conf.date = simpleDateFormat.format(time);
251 | conf.app_version = mView.getAppVersion();
252 | conf.android_version = AndroidUtil.getAndroidSystemVersion();
253 | conf.map_name = mTreeModel.getRootNode().getValue();
254 | owantFileCreate.writeConf(conf);
255 |
256 | owantFileCreate.writeContent(mTreeModel);
257 |
258 | // //如果是创建模式
259 | // if (mIsCreate) {
260 | // owantFileCreate.makeOwantFile(mTreeModel.getRootNode().getValue());
261 | // } else {
262 | // owantFileCreate.makeOwantFile(mFileName);
263 | // }
264 | owantFileCreate.makeOwantFile(fileName);
265 | owantFileCreate.deleteTemp();
266 | }
267 |
268 | @Override
269 | public void setTreeModel(TreeModel treeModel) {
270 | mTreeModel = treeModel;
271 | mView.setTreeViewData(mTreeModel);
272 | }
273 |
274 | @Override
275 | public TreeModel getTreeModel() {
276 | return mTreeModel;
277 | }
278 |
279 | @Override
280 | public List getOwantLists() {
281 | List list = new ArrayList();
282 | LOG.jLogi("isCreate=%s", mIsCreate);
283 | if (mOwantFilesArray != null) {
284 | for (String s : mOwantFilesArray) {
285 | list.add(s);
286 | LOG.jLogi("exist file=%s", s);
287 | }
288 | } else {
289 | LOG.jLogi("mOwantFilesArray is empty");
290 | }
291 | return list;
292 | }
293 |
294 | @Override
295 | public String getSaveInput() {
296 | if (mIsCreate) {
297 | return mTreeModel.getRootNode().getValue();
298 | } else {
299 | return mFileName;
300 | }
301 | }
302 |
303 | }
304 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/splash/SplashActivity.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui.splash;
2 |
3 | import android.content.Intent;
4 | import android.content.pm.PackageManager;
5 | import android.os.Bundle;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.app.ActivityCompat;
9 | import android.support.v4.content.ContextCompat;
10 | import android.widget.Toast;
11 |
12 | import com.owant.thinkmap.AppPermissions;
13 | import com.owant.thinkmap.R;
14 | import com.owant.thinkmap.base.BaseActivity;
15 | import com.owant.thinkmap.ui.workspace.WorkSpaceActivity;
16 | import com.owant.thinkmap.util.AndroidUtil;
17 |
18 | public class SplashActivity extends BaseActivity {
19 |
20 | @Override
21 | protected void onBaseIntent() {
22 |
23 | }
24 |
25 | @Override
26 | protected void onBasePreLayout() {
27 |
28 | }
29 |
30 | @Override
31 | protected int onBaseLayoutId(@Nullable Bundle savedInstanceState) {
32 | return R.layout.activity_splash;
33 | }
34 |
35 | @Override
36 | protected void onBaseBindView() {
37 |
38 | if (AndroidUtil.isMPermission()) {
39 | if (ContextCompat.checkSelfPermission(SplashActivity.this,
40 | AppPermissions.permission_storage[0]) != PackageManager.PERMISSION_GRANTED ||
41 | ContextCompat.checkSelfPermission(SplashActivity.this,
42 | AppPermissions.permission_storage[1]) != PackageManager.PERMISSION_GRANTED) {
43 |
44 | requestStoragePermission();
45 |
46 | } else {
47 | intentToWorkSpace();
48 | }
49 |
50 | } else {
51 | intentToWorkSpace();
52 | }
53 |
54 | }
55 |
56 | private void intentToWorkSpace() {
57 | new Thread(new Runnable() {
58 | @Override
59 | public void run() {
60 | try {
61 | Thread.sleep(1200);
62 | Intent intent = new Intent(SplashActivity.this, WorkSpaceActivity.class);
63 | startActivity(intent);
64 | SplashActivity.this.finish();
65 | } catch (InterruptedException e) {
66 | e.printStackTrace();
67 | }
68 | }
69 | }).start();
70 | }
71 |
72 | @Override
73 | protected void onLoadData() {
74 |
75 | }
76 |
77 | /**
78 | * 请求内存卡权限
79 | */
80 | private void requestStoragePermission() {
81 | ActivityCompat.requestPermissions(SplashActivity.this
82 | , AppPermissions.permission_storage,
83 | AppPermissions.request_permission_storage);
84 | }
85 |
86 | @Override
87 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
88 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
89 | if (requestCode == AppPermissions.request_permission_storage) {
90 | if (AndroidUtil.verifyPermissions(grantResults)) {
91 | intentToWorkSpace();
92 | } else {
93 | Toast.makeText(this, "the permission denied!", Toast.LENGTH_SHORT).show();
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/workspace/WorkSpaceContract.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui.workspace;
2 |
3 | import com.owant.thinkmap.base.BasePresenter;
4 | import com.owant.thinkmap.base.BaseView;
5 | import com.owant.thinkmap.model.CurrentFileModel;
6 |
7 | import java.io.InputStream;
8 | import java.util.ArrayList;
9 |
10 | /**
11 | * Created by owant on 24/03/2017.
12 | */
13 | public interface WorkSpaceContract {
14 |
15 | interface Presenter extends BasePresenter {
16 |
17 | /**
18 | * 空ListView的提示
19 | */
20 | void onEmptyView();
21 |
22 | /**
23 | * 加载owant的example示例
24 | *
25 | * @param inputStream
26 | */
27 | void onLoadExamples(InputStream inputStream);
28 |
29 | /**
30 | * 加载Owant文件
31 | */
32 | void onLoadOwantData();
33 |
34 | /**
35 | * 删除Item
36 | *
37 | * @param position
38 | */
39 | void removeItemFile(int position);
40 |
41 | String getItemFilePath(int position);
42 | }
43 |
44 | interface View extends BaseView {
45 |
46 | /**
47 | * 显示空的View
48 | */
49 | void showEmptyView();
50 |
51 | /**
52 | * 是否需要加载owant示例
53 | *
54 | * @return
55 | */
56 | boolean shouldLoadExample();
57 |
58 | /**
59 | * 重置owant示例不用加载示例
60 | */
61 | void changeExampleVersion(String version);
62 |
63 | /**
64 | * 设置ListView的数据
65 | *
66 | * @param listData
67 | */
68 | void setListData(ArrayList listData);
69 |
70 | /**
71 | * 刷新ListView的数据
72 | */
73 | void refreshListData();
74 |
75 | String getOwantDefaultPath();
76 |
77 | String getExampleVersion();
78 |
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/ui/workspace/WorkSpacePresenter.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.ui.workspace;
2 |
3 | import com.owant.thinkmap.AppConstants;
4 | import com.owant.thinkmap.file.ZipTool;
5 | import com.owant.thinkmap.model.CurrentFileModel;
6 | import com.owant.thinkmap.util.AndroidUtil;
7 | import com.owant.thinkmap.util.LOG;
8 |
9 | import java.io.File;
10 | import java.io.FileNotFoundException;
11 | import java.io.FileOutputStream;
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.util.ArrayList;
15 |
16 | /**
17 | * Created by owant on 24/03/2017.
18 | */
19 |
20 | public class WorkSpacePresenter implements WorkSpaceContract.Presenter {
21 |
22 | private WorkSpaceContract.View mView;
23 | private ArrayList mLists;
24 |
25 | private String mDefaultPath;
26 |
27 | public WorkSpacePresenter(WorkSpaceContract.View view) {
28 | mView = view;
29 | }
30 |
31 | @Override
32 | public void start() {
33 | mLists = new ArrayList<>();
34 | }
35 |
36 | @Override
37 | public void onRecycle() {
38 |
39 | }
40 |
41 | @Override
42 | public void onEmptyView() {
43 | mView.showEmptyView();
44 | }
45 |
46 | @Override
47 | public void onLoadExamples(InputStream ism) {
48 | boolean state = mView.shouldLoadExample();
49 | if (state) {
50 | new Thread(new CopOwantExamples(ism)).start();
51 | }
52 | }
53 |
54 | @Override
55 | public void onLoadOwantData() {
56 | if (mDefaultPath == null) {
57 | mDefaultPath = mView.getOwantDefaultPath();
58 | }
59 |
60 | File saveFileParent = new File(mDefaultPath);
61 | mLists.clear();
62 | if (saveFileParent.exists()) {
63 | File[] files = saveFileParent.listFiles();
64 | for (File v : files) {
65 | if (v.isFile() && v.getAbsolutePath().endsWith(".owant")) {
66 | CurrentFileModel model = new CurrentFileModel();
67 | model.filePath = v.getAbsolutePath();
68 | model.editTime = AndroidUtil.transferLongToDate("yyyy-MM-dd HH:mm:ss", v.lastModified());
69 | String fileName = v.getName();
70 | if (fileName.indexOf(".") > 0) {
71 | fileName = fileName.substring(0, fileName.indexOf("."));
72 | }
73 | model.mapRoot = fileName;
74 | mLists.add(model);
75 | }
76 | }
77 | }
78 | mView.setListData(mLists);
79 | }
80 |
81 | @Override
82 | public void removeItemFile(int position) {
83 | CurrentFileModel currentFileModel = mLists.get(position);
84 | File file = new File(currentFileModel.filePath);
85 | if (file.exists()) {
86 | file.delete();
87 | mLists.remove(currentFileModel);
88 | }
89 | }
90 |
91 | @Override
92 | public String getItemFilePath(int position) {
93 | return mLists.get(position).filePath;
94 | }
95 |
96 | /**
97 | * 拷贝raw下的示例文件到内存卡
98 | */
99 | private class CopOwantExamples implements Runnable {
100 |
101 | private InputStream mInputStream;
102 |
103 | public CopOwantExamples(InputStream is) {
104 | mInputStream = is;
105 | }
106 |
107 | @Override
108 | public void run() {
109 | try {
110 | FileOutputStream fos = null;
111 | InputStream inputStream = null;
112 | try {
113 | String sdCardPath = mView.getOwantDefaultPath();
114 | String saveExamplesPath = sdCardPath + AppConstants.examples_names;
115 | LOG.jLogi("copExamplesToStorage:%s", saveExamplesPath);
116 | File saveFile = new File(saveExamplesPath);
117 | if (!saveFile.exists()) {
118 | saveFile.getParentFile().mkdirs();
119 | saveFile.createNewFile();
120 | }
121 | fos = new FileOutputStream(saveFile);
122 | inputStream = mInputStream;
123 |
124 | byte[] buffer = new byte[1024];
125 | int count;
126 | while ((count = inputStream.read(buffer)) > 0) {
127 | fos.write(buffer, 0, count);
128 | fos.flush();
129 | }
130 |
131 | ZipTool.unZipFiles(
132 | saveExamplesPath,
133 | mView.getOwantDefaultPath());
134 |
135 | mView.changeExampleVersion(mView.getExampleVersion());
136 |
137 | onLoadOwantData();
138 |
139 | } catch (FileNotFoundException e) {
140 | e.printStackTrace();
141 | } catch (IOException e) {
142 | e.printStackTrace();
143 | } finally {
144 | if (fos != null) {
145 | try {
146 | fos.close();
147 | } catch (IOException e) {
148 | e.printStackTrace();
149 | }
150 | }
151 | if (inputStream != null) {
152 | try {
153 | inputStream.close();
154 | } catch (IOException e) {
155 | e.printStackTrace();
156 | }
157 | }
158 | }
159 |
160 | } catch (Exception e) {
161 | e.printStackTrace();
162 | }
163 | }
164 | }
165 |
166 |
167 | }
168 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/AndroidUtil.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.util;
2 |
3 | import android.app.Activity;
4 | import android.app.ActivityManager;
5 | import android.content.ComponentName;
6 | import android.content.Context;
7 | import android.content.DialogInterface;
8 | import android.content.Intent;
9 | import android.content.pm.PackageManager;
10 | import android.net.ConnectivityManager;
11 | import android.net.NetworkInfo;
12 | import android.net.wifi.WifiManager;
13 | import android.os.Build;
14 | import android.support.annotation.RequiresApi;
15 | import android.support.v7.app.AlertDialog;
16 | import android.text.TextUtils;
17 | import android.view.MotionEvent;
18 | import android.view.View;
19 | import android.view.inputmethod.InputMethodManager;
20 | import android.widget.EditText;
21 | import android.widget.Toast;
22 |
23 | import java.lang.reflect.InvocationTargetException;
24 | import java.lang.reflect.Method;
25 | import java.text.SimpleDateFormat;
26 | import java.util.Date;
27 | import java.util.List;
28 | import java.util.Locale;
29 |
30 | public class AndroidUtil {
31 |
32 | /**
33 | * 隐藏键盘
34 | */
35 | public static void hideKeyboard(Context context, View view) {
36 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
37 | imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
38 | }
39 |
40 | public static boolean isShouldHideInput(View inputView, MotionEvent event) {
41 | boolean should = false;
42 | if (inputView != null && (inputView instanceof EditText)) {
43 | int[] leftTop = {0, 0};
44 | inputView.getLocationInWindow(leftTop);
45 | int left = leftTop[0];
46 | int top = leftTop[1];
47 |
48 | int bottom = top + inputView.getHeight();
49 | int right = left + inputView.getWidth();
50 |
51 | if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
52 | should = false;
53 | } else {
54 | should = true;
55 | }
56 | }
57 | return should;
58 | }
59 |
60 |
61 | /**
62 | * 显示Toast的信息
63 | *
64 | * @param mContext
65 | * @param toastInfo
66 | */
67 | public static void showToast(Context mContext, String toastInfo) {
68 | Toast mToast = Toast.makeText(mContext, toastInfo, Toast.LENGTH_SHORT);
69 | mToast.show();
70 | }
71 |
72 | /**
73 | * 判断网络是否可用
74 | */
75 | public static boolean isNetworkAvailable(Context context) {
76 | boolean netStatus = false;
77 | ConnectivityManager connectManager = (ConnectivityManager) context
78 | .getSystemService(Context.CONNECTIVITY_SERVICE);
79 | NetworkInfo networkInfo = connectManager.getActiveNetworkInfo();
80 |
81 | if (networkInfo != null) {
82 | netStatus = networkInfo.isAvailable();
83 | }
84 | return netStatus;
85 | }
86 |
87 | /**
88 | * 打开设置网络
89 | *
90 | * @param mContext
91 | */
92 | public static void openSettingsConn(Context mContext, Integer requestCode) {
93 | Intent settings = null;
94 | // SDK>15,就是3.0以上的版本
95 | if (Build.VERSION.SDK_INT >= 15) {
96 | settings = new Intent(android.provider.Settings.ACTION_SETTINGS);
97 | } else {
98 | settings = new Intent();
99 | ComponentName component = new ComponentName("com.android.settings",
100 | "com.android.setttins.WirelessSettings");
101 | settings.setAction("android.intent.action.VIEW");
102 |
103 | }
104 |
105 | if (requestCode == null) {
106 | mContext.startActivity(settings);
107 | } else {
108 | ((Activity) mContext).startActivityForResult(settings, requestCode);
109 | }
110 | }
111 |
112 | public static void openSettingsConn(Context mContext) {
113 | openSettingsConn(mContext, null);
114 | }
115 |
116 |
117 | public static String getCurrentSSID(Context context) {
118 | String ssid = "";
119 | WifiManager wifiManager = (WifiManager) context.getApplicationContext()
120 | .getSystemService(Context.WIFI_SERVICE);
121 | if (wifiManager.isWifiEnabled()) {
122 | ssid = wifiManager.getConnectionInfo().getSSID();
123 | ssid = ssid.replaceAll("\"", "");
124 | if (TextUtils.equals("", ssid)) {
125 | ssid = "";
126 | }
127 | }
128 | return ssid;
129 | }
130 |
131 | /**
132 | * 创建并显示一个只包含“是”与“否”按钮简单对话框
133 | *
134 | * @param context
135 | * @param title
136 | * @param callback
137 | */
138 | public static void showAlertDialog(final Context context, final String title, final DialogCallback callback) {
139 | new AlertDialog.Builder(context)
140 | .setTitle(title)
141 | .setPositiveButton("是", new DialogInterface.OnClickListener() {
142 | @Override
143 | public void onClick(DialogInterface dialog, int which) {
144 | callback.onPositive();
145 | }
146 | })
147 | .setNegativeButton("否", new DialogInterface.OnClickListener() {
148 | @Override
149 | public void onClick(DialogInterface dialog, int which) {
150 | dialog.dismiss();
151 | }
152 | }).show();
153 | }
154 |
155 | /**
156 | * 点击对话框确定按钮后的回调接口
157 | */
158 | public interface DialogCallback {
159 | void onPositive();
160 | }
161 |
162 | /**
163 | * 检测当前App是否在前台运行
164 | *
165 | * @param context
166 | * @return true 前台运行,false 后台运行
167 | */
168 | public static boolean isAppForeground(Context context) {
169 | ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
170 | List runningTasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
171 |
172 | // 正在运行的应用
173 | ActivityManager.RunningTaskInfo foregroundTask = runningTasks.get(0);
174 | String packageName = foregroundTask.topActivity.getPackageName();
175 | String myPackageName = context.getPackageName();
176 |
177 | // 比较包名
178 | return packageName.equals(myPackageName);
179 | }
180 |
181 | public static String getAppVersion(Context context) {
182 | String myVersion = "v ";
183 | try {
184 | myVersion = myVersion + context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
185 | } catch (PackageManager.NameNotFoundException e) {
186 | e.printStackTrace();
187 | }
188 | return myVersion;
189 | }
190 |
191 | public static String getAndroidSystemVersion() {
192 | return "android " + Build.VERSION.SDK_INT;
193 | }
194 |
195 | public static String transferLongToDate(String dateFormat, Long millSec) {
196 | SimpleDateFormat sdf = new SimpleDateFormat(dateFormat, Locale.CHINA);
197 | Date date = new Date(millSec);
198 | return sdf.format(date);
199 | }
200 |
201 | /**
202 | * 判断是否为android 6.0
203 | *
204 | * @return true or false
205 | */
206 | public static boolean isMPermission() {
207 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
208 | return true;
209 | } else {
210 | return false;
211 | }
212 | }
213 |
214 | /**
215 | * Check that all given permissions have been granted by verifying that each entry in the
216 | * given array is of the value {@link PackageManager#PERMISSION_GRANTED}.
217 | *
218 | * @see Activity#onRequestPermissionsResult(int, String[], int[])
219 | */
220 | public static boolean verifyPermissions(int[] grantResults) {
221 | // At least one result must be checked.
222 | if (grantResults.length < 1) {
223 | return false;
224 | }
225 |
226 | // Verify that each required permission has been granted, otherwise return false.
227 | for (int result : grantResults) {
228 | if (result != PackageManager.PERMISSION_GRANTED) {
229 | return false;
230 | }
231 | }
232 | return true;
233 | }
234 |
235 | }
236 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/DensityUtils.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.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 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/LOG.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.util;
2 |
3 | import com.owant.thinkmap.AppConstants;
4 |
5 | /**
6 | * Created by owant on 22/03/2017.
7 | */
8 |
9 | public class LOG {
10 |
11 | public static void jLogi(String format, Object... args) {
12 | if (AppConstants.CONFIG_DEBUG) {
13 | StringBuffer ft = new StringBuffer(format);
14 | if (!ft.toString().endsWith("\n")) {
15 | ft.append("\n");
16 | }
17 | System.out.printf(ft.toString(), args);
18 | }
19 | }
20 |
21 | public static void jLoge(String format, Object... args) {
22 | if (AppConstants.CONFIG_DEBUG) {
23 | StringBuffer ft = new StringBuffer(format);
24 | if (!ft.toString().endsWith("\n")) {
25 | ft.append("\n");
26 | }
27 | System.err.printf(ft.toString(), args);
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/LooperFlag.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.util;
2 |
3 | /**
4 | * Created by OlaWang on 2017/7/12.
5 | */
6 |
7 | /**
8 | * This util support the looper sate callback.
9 | * if you input the {@link LooperFlag#loopBody} value of {1,2,3}
10 | * you call the {@link LooperFlag#next()}
11 | * the callback will return the 1,2,3,1,2,3,1,2,3....
12 | *
13 | * @param
14 | */
15 | public class LooperFlag {
16 |
17 | private T[] loopBody;
18 | private LooperListener mListener;
19 | private int point = 0;
20 |
21 | public LooperFlag(T[] loopBody, LooperListener listener) {
22 | this.loopBody = loopBody;
23 | mListener = listener;
24 | }
25 |
26 | public T next() {
27 | point += 1;
28 | if (point == loopBody.length) {
29 | point = 0;
30 | }
31 |
32 | if (mListener != null) {
33 | mListener.onLooper(loopBody[point]);
34 | }
35 |
36 | return loopBody[point];
37 | }
38 |
39 | public void setLooperListener(LooperListener listener) {
40 | mListener = listener;
41 | }
42 |
43 | public interface LooperListener {
44 | void onLooper(T item);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/MakeZipClient.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.util;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileNotFoundException;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.zip.ZipEntry;
11 | import java.util.zip.ZipOutputStream;
12 |
13 | /**
14 | * Created by owant on 2016/9/1.
15 | */
16 | public class MakeZipClient {
17 |
18 | private List arrayFiles;
19 | private String sourcePath;
20 | private File saveFilePath;
21 |
22 | public void create(String sourcePath, File savePath) {
23 | arrayFiles = new ArrayList<>();
24 | this.sourcePath = sourcePath;
25 | this.saveFilePath = savePath;
26 |
27 | //遍历文件下文件
28 | findAllFiles(sourcePath);
29 | //生产.owant
30 | makeZipFile(arrayFiles.toArray(new File[arrayFiles.size()]), saveFilePath);
31 | }
32 |
33 | /**
34 | * 找到所有输入文件夹路径下的所有文件
35 | *
36 | * @param filePath
37 | */
38 | private void findAllFiles(String filePath) {
39 | if (filePath == null || filePath.trim().length() == 0) {
40 | System.out.println("请输入文件路径!");
41 | return;
42 | }
43 |
44 | File sourceFile = new File(filePath);
45 | if (!sourceFile.exists()) {
46 | System.out.println("输入的文件路径不存在!");
47 | return;
48 | } else {//遍历该目录下所有的文件
49 | if (sourceFile.isDirectory()) {//文件夹
50 | File[] subFiles = sourceFile.listFiles();
51 | for (File f : subFiles) {
52 | findAllFiles(f.getAbsolutePath());
53 | }
54 | } else {//文件
55 | System.out.println("找到文件:\t" + sourceFile.getAbsolutePath());
56 | arrayFiles.add(sourceFile);
57 | }
58 | }
59 | }
60 |
61 | private void makeZipFile(File[] files, File zipNameFile) {
62 | //建立一个写入流
63 | FileOutputStream fos;
64 | try {
65 | fos = new FileOutputStream(zipNameFile);
66 | //建立一个写入压缩流
67 | ZipOutputStream zos = new ZipOutputStream(fos);
68 | byte[] buffer = new byte[1024];
69 | for (File file : files) {
70 | //截取掉前面的字符
71 | String cutPath = file.getAbsolutePath().substring(sourcePath.length());
72 | System.out.println("entry:" + cutPath);
73 | ZipEntry entry = new ZipEntry(cutPath);
74 | FileInputStream fis = new FileInputStream(file);
75 | zos.putNextEntry(entry);
76 | int read = 0;
77 | while ((read = fis.read(buffer)) != -1) {
78 | zos.write(buffer, 0, read);
79 | }
80 |
81 | zos.closeEntry();
82 | fis.close();
83 | }
84 | zos.close();
85 | fos.close();
86 | } catch (FileNotFoundException e) {
87 | e.printStackTrace();
88 | } catch (IOException e) {
89 | e.printStackTrace();
90 | }
91 | }
92 |
93 |
94 | public static void main(String[] arg) {
95 | // String sourcePath = "/Users/owant/Desktop/create_file";
96 | // MakeZipClient client = new MakeZipClient();
97 | // File saveFile = new File("/Users/owant/Desktop/myplan.owant");
98 | // client.create(sourcePath, saveFile);
99 | }
100 |
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/SharePreUtil.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.util;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.os.Build;
6 |
7 | /**
8 | * Created by owant on 2016/9/1.
9 | */
10 | public class SharePreUtil {
11 | private static final String PREFRENCE_NAME = "base_pre";
12 | private SharedPreferences mSharedPrefs;
13 |
14 | private SharePreUtil() {
15 | }
16 |
17 | private static class InstanceHolder {
18 | public static SharePreUtil sInstance = new SharePreUtil();
19 | }
20 |
21 | public static SharePreUtil getInstance() {
22 | return InstanceHolder.sInstance;
23 | }
24 |
25 | public void init(Context context) {
26 | mSharedPrefs = context.getSharedPreferences(PREFRENCE_NAME, Context.MODE_PRIVATE);
27 | }
28 |
29 | public String getString(String key) {
30 | if (mSharedPrefs == null) return null;
31 | return mSharedPrefs.getString(key, "");
32 | }
33 |
34 | public void putString(String key, String value) {
35 | if (mSharedPrefs == null) return;
36 | SharedPreferences.Editor editor = mSharedPrefs.edit();
37 | editor.putString(key, value);
38 | if (Build.VERSION.SDK_INT >= 15)
39 | editor.apply();
40 | else
41 | editor.commit();
42 | }
43 |
44 | public void remove(String key) {
45 | SharedPreferences.Editor editor = mSharedPrefs.edit();
46 | editor.remove(key);
47 |
48 | if (Build.VERSION.SDK_INT >=15) {
49 | editor.apply();
50 | } else {
51 | editor.commit();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/StringTool.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.util;
2 |
3 | /**
4 | * Created by owant on 22/03/2017.
5 | * 脱开Android包
6 | */
7 |
8 | public class StringTool {
9 |
10 | /**
11 | * Returns true if the string is null or 0-length.
12 | *
13 | * @param str the string to be examined
14 | * @return true if str is null or zero length
15 | */
16 | public static boolean isEmpty(CharSequence str) {
17 | if (str == null || str.length() == 0)
18 | return true;
19 | else
20 | return false;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/code/BindView.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/java/com/owant/thinkmap/util/code/BindView.jar
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/util/code/BindViewTool.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.util.code;
2 |
3 | import org.xmlpull.v1.XmlPullParser;
4 | import org.xmlpull.v1.XmlPullParserException;
5 | import org.xmlpull.v1.XmlPullParserFactory;
6 |
7 | import java.io.File;
8 | import java.io.FileInputStream;
9 | import java.io.FileNotFoundException;
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.util.ArrayList;
13 |
14 | /**
15 | * Created by owant on 19/10/2016.
16 | * 查找XML布局下的控件,进行生产findViewById的代码
17 | */
18 |
19 | public class BindViewTool {
20 |
21 | final static String input_key_i = "-i";
22 | final static String input_key_f = "-f";
23 | final static String input_key_p = "-p";
24 |
25 | /**
26 | * private TextView info;
27 | */
28 | private static final String declare_format = "private {0} {1};";
29 |
30 | /**
31 | * info=(TextView)findViewById(R.id.text);
32 | * info=(TextView)getView().findViewById(R.id.text);
33 | */
34 | private static final String find_view_format = "{0} = ({1}){2}findViewById({3});";
35 |
36 | private static boolean isFragment = false;
37 | /**
38 | * 忽略的标识,默认表示为_
39 | */
40 | private static String ignoreMark = "_";
41 |
42 | //找到了需要绑定的View
43 | private static ArrayList bindViews = new ArrayList<>();
44 |
45 | public static void main(String[] arg) {
46 |
47 | if (arg.length >= 2) {
48 | boolean inp = false;
49 | InputMode mode = new InputMode();
50 | for (String str : arg) {
51 | if (mode.getState().equals(input_key_f)) {
52 | isFragment = Boolean.valueOf(str);
53 | } else if (mode.getState().equals(input_key_p)) {
54 | bindView(str, false);
55 | inp = true;
56 | } else if (mode.getState().equals(input_key_i)) {
57 | ignoreMark = str;
58 | }
59 | if (!inp) {
60 | mode.setState(str);
61 | }
62 | }
63 |
64 | } else if (arg.length == 1) {
65 | bindView(arg[0], false);
66 | }
67 |
68 | printfResult();
69 | }
70 |
71 | public static void bindView(String xmlPath, boolean includeState) {
72 | try {
73 |
74 | InputStream inputStream = new FileInputStream(new File(xmlPath));
75 |
76 | //bindView的集合
77 | if (!includeState)
78 | bindViews = new ArrayList<>();
79 |
80 | XmlPullParser xmlPullParser = XmlPullParserFactory.newInstance().newPullParser();
81 | xmlPullParser.setInput(inputStream, "utf-8");
82 |
83 | //xml pull parser是以事件触发为设计的代码
84 | int eventType = xmlPullParser.getEventType();
85 | while (eventType != XmlPullParser.END_DOCUMENT) {//文档结束
86 | switch (eventType) {
87 | case XmlPullParser.START_DOCUMENT://文档开始
88 | break;
89 | case XmlPullParser.START_TAG://标签开始
90 | xmlTagBusiness(xmlPath, xmlPullParser);
91 | break;
92 | case XmlPullParser.END_TAG://标签结束
93 | break;
94 | }
95 |
96 | eventType = xmlPullParser.next();
97 | }
98 |
99 | } catch (XmlPullParserException e) {
100 | e.printStackTrace();
101 | } catch (FileNotFoundException e) {
102 | e.printStackTrace();
103 | } catch (IOException e) {
104 | e.printStackTrace();
105 | }
106 |
107 | }
108 |
109 | private static void printfResult() {
110 | //打印需要BindView的控件
111 | //打印变量声明
112 | System.out.println("\n\n");
113 | for (Model m : bindViews) {
114 | String declare = declare_format.replace("{0}", m.mType);
115 | declare = declare.replace("{1}", m.mName);
116 | System.out.println(declare);
117 | }
118 |
119 | System.out.println("\n\n");
120 |
121 | System.out.println("public void bindViews(){\n");
122 | for (Model m : bindViews) {
123 | String find = find_view_format.replace("{0}", m.mName);
124 | find = find.replace("{1}", m.mType);
125 | if (isFragment) {
126 | find = find.replace("{2}", "getView().");
127 | } else {
128 | find = find.replace("{2}", "");
129 | }
130 | find = find.replace("{3}", "R.id." + m.mId);
131 | System.out.println("\t" + find);
132 | }
133 | System.out.println("}\n");
134 | }
135 |
136 | private static void xmlTagBusiness(String path, XmlPullParser xmlPullParser) {
137 | //对于这个情况需要进行com.owant.examples.view.DivView
138 | String type = xmlPullParser.getName();
139 | int pointExist = type.lastIndexOf(".");
140 | if (pointExist != -1) {
141 | type = type.substring(pointExist + 1, type.length());
142 | }
143 |
144 | if (type.equals("include")) {
145 |
146 | /**
147 |
150 | */
151 | int count = xmlPullParser.getAttributeCount();
152 | for (int i = 0; i < count; i++) {
153 | if (xmlPullParser.getAttributeName(i).startsWith("layout")) {
154 | //查找到另一个布局
155 | String layoutFormat = xmlPullParser.getAttributeValue(i);
156 | layoutFormat = layoutFormat.substring(layoutFormat.indexOf("/"), layoutFormat.length());
157 |
158 | bindView(path.substring(0, path.lastIndexOf("/")) + layoutFormat + ".xml", true);
159 | return;
160 | }
161 | }
162 |
163 | }
164 |
165 | String androidIdValue = null;
166 | int count = xmlPullParser.getAttributeCount();
167 | for (int i = 0; i < count; i++) {
168 | String androidIdTag = xmlPullParser.getAttributeName(i);
169 |
170 | if (androidIdTag.equals("android:id")) {
171 | String androidIdTagValue = xmlPullParser.getAttributeValue(i);
172 | if (androidIdTagValue.startsWith("@+id/")) {
173 | androidIdValue = androidIdTagValue.replace("@+id/", "");
174 |
175 | //ignore
176 | if (androidIdValue.startsWith(ignoreMark)) {
177 | continue;
178 | }
179 |
180 | if (androidIdValue != null) {
181 | Model model = new Model();
182 | model.mId = androidIdValue;
183 | String name = translationName(model.mId);
184 | model.mName = name;
185 | model.mType = type;
186 | bindViews.add(model);
187 | }
188 | continue;
189 | }
190 | }
191 | }
192 | }
193 |
194 | /**
195 | * edit_map_tree_view转化为editMapTreeView
196 | *
197 | * @param idValue
198 | * @return
199 | */
200 | private static String translationName(String idValue) {
201 | boolean shouldUp = false;
202 | char[] chars = idValue.toCharArray();
203 | StringBuffer buffer = new StringBuffer();
204 | for (char ch : chars) {
205 |
206 | if (shouldUp) {
207 | ch = Character.toUpperCase(ch);
208 | buffer.append(ch);
209 | shouldUp = false;
210 |
211 | } else {
212 | if (ch == '_') {
213 | shouldUp = true;
214 | } else {
215 | shouldUp = false;
216 | buffer.append(ch);
217 | }
218 | }
219 | }
220 | return buffer.toString();
221 | }
222 |
223 | public static class Model {
224 | public String mType;
225 | public String mName;
226 | public String mId;
227 | }
228 |
229 | public static class InputMode {
230 |
231 | public String state = "";
232 |
233 | public void setState(String input) {
234 | if (input.equals(input_key_f)) {
235 | state = input_key_f;
236 | } else if (input.equals(input_key_i)) {
237 | state = input_key_i;
238 | } else if (input.equals(input_key_p)) {
239 | state = input_key_p;
240 | } else {
241 | state = "";
242 | }
243 | }
244 |
245 | public String getState() {
246 | return state;
247 | }
248 | }
249 | }
250 |
251 |
252 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/view/NodeView.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.view;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Color;
6 | import android.graphics.drawable.Drawable;
7 | import android.util.AttributeSet;
8 | import android.widget.TextView;
9 |
10 | import com.owant.thinkmap.R;
11 | import com.owant.thinkmap.model.NodeModel;
12 |
13 |
14 | /**
15 | * Created by owant on 09/02/2017.
16 | */
17 | @SuppressLint("AppCompatCustomView")
18 | public class NodeView extends TextView{
19 |
20 | public NodeModel treeNode = null;
21 |
22 | public NodeView(Context context) {
23 | this(context, null, 0);
24 | }
25 |
26 | public NodeView(Context context, AttributeSet attrs) {
27 | this(context, attrs, 0);
28 | }
29 |
30 | public NodeView(Context context, AttributeSet attrs, int defStyleAttr) {
31 | super(context, attrs, defStyleAttr);
32 |
33 | setTextColor(Color.WHITE);
34 | setPadding(12, 10, 12, 10);
35 |
36 | Drawable drawable = context.getResources().getDrawable(R.drawable.node_view_bg);
37 | setBackgroundDrawable(drawable);
38 | }
39 |
40 | public NodeModel getTreeNode() {
41 | return treeNode;
42 | }
43 |
44 | public void setTreeNode(NodeModel treeNode) {
45 | this.treeNode = treeNode;
46 | setSelected(treeNode.isFocus());
47 | setText(treeNode.getValue());
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/view/RecycleItemClickListener.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.view;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Created by owant on 2016/7/29.
7 | */
8 | public interface RecycleItemClickListener {
9 | void onItemClick(View view, int position);
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/view/RecycleItemLongClickListener.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.view;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Created by owant on 07/09/2017.
7 | */
8 |
9 | public interface RecycleItemLongClickListener {
10 | void onItemLongClick(View view, int position);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/view/RightTreeLayoutManager.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.view;
2 |
3 | import android.util.Log;
4 | import android.view.View;
5 |
6 | import com.owant.thinkmap.model.ForTreeItem;
7 | import com.owant.thinkmap.model.NodeModel;
8 | import com.owant.thinkmap.model.TreeModel;
9 |
10 | import java.io.Serializable;
11 | import java.util.ArrayDeque;
12 | import java.util.ArrayList;
13 | import java.util.Deque;
14 | import java.util.LinkedList;
15 |
16 | /**
17 | * Created by owant on 08/03/2017.
18 | */
19 | public class RightTreeLayoutManager implements TreeLayoutManager {
20 |
21 | final int msg_standard_layout = 1;
22 | final int msg_correct_layout = 2;
23 | final int msg_box_call_back = 3;
24 |
25 | private ViewBox mViewBox;
26 | private int mDy;
27 | private int mDx;
28 | private int mHeight;
29 |
30 | public RightTreeLayoutManager(int dx, int dy, int height) {
31 | mViewBox = new ViewBox();
32 |
33 | this.mDx = dx;
34 | this.mDy = dy;
35 | this.mHeight = height;
36 | }
37 |
38 | @Override
39 | public void onTreeLayout(final TreeView treeView) {
40 |
41 | final TreeModel mTreeModel = treeView.getTreeModel();
42 | if (mTreeModel != null) {
43 |
44 | View rootView = treeView.findNodeViewFromNodeModel(mTreeModel.getRootNode());
45 | if (rootView != null) {
46 |
47 | //根节点位置
48 | rootTreeViewLayout((NodeView) rootView);
49 | }
50 |
51 | mTreeModel.addForTreeItem(new ForTreeItem>() {
52 | @Override
53 | public void next(int msg, NodeModel next) {
54 | doNext(msg, next, treeView);
55 | }
56 | });
57 |
58 | //基本布局
59 | mTreeModel.ergodicTreeInWith(msg_standard_layout);
60 |
61 | //纠正
62 | mTreeModel.ergodicTreeInWith(msg_correct_layout);
63 |
64 | mViewBox.clear();
65 | mTreeModel.ergodicTreeInDeep(msg_box_call_back);
66 | }
67 | }
68 |
69 |
70 | @Override
71 | public ViewBox onTreeLayoutCallBack() {
72 | if (mViewBox != null) {
73 | return mViewBox;
74 | } else {
75 | return null;
76 | }
77 | }
78 |
79 | private void doNext(int msg, NodeModel next, TreeView treeView) {
80 | View view = treeView.findNodeViewFromNodeModel(next);
81 |
82 | if (msg == msg_standard_layout) {
83 | //标准分布
84 | standardLayout(treeView, (NodeView) view);
85 | } else if (msg == msg_correct_layout) {
86 | //纠正
87 | correctLayout(treeView, (NodeView) view);
88 | } else if (msg == msg_box_call_back) {
89 |
90 | //View的大小变化
91 | int left = view.getLeft();
92 | int top = view.getTop();
93 | int bottom = view.getBottom();
94 | int right = view.getRight();
95 |
96 | // *******
97 | // * *
98 | // * *
99 | // *******
100 |
101 | if (left < mViewBox.left) {
102 | mViewBox.left = left;
103 | }
104 | if (top < mViewBox.top) {
105 | mViewBox.top = top;
106 | }
107 | if (bottom > mViewBox.bottom) {
108 | mViewBox.bottom = bottom;
109 | }
110 | if (right > mViewBox.right) {
111 | mViewBox.right = right;
112 | }
113 | }
114 | }
115 |
116 | /**
117 | * 布局纠正
118 | *
119 | * @param treeView
120 | * @param next
121 | */
122 | public void correctLayout(TreeView treeView, NodeView next) {
123 |
124 | TreeModel mTree = treeView.getTreeModel();
125 | int count = next.getTreeNode().getChildNodes().size();
126 |
127 | if (next.getParent() != null && count >= 2) {
128 | NodeModel tn = next.getTreeNode().getChildNodes().get(0);
129 | NodeModel bn = next.getTreeNode().getChildNodes().get(count - 1);
130 | Log.i("see fc", next.getTreeNode().getValue() + ":" + tn.getValue() + "," + bn.getValue());
131 |
132 | int topDr = next.getTop() - treeView.findNodeViewFromNodeModel(tn).getBottom() + mDy;
133 | int bnDr = treeView.findNodeViewFromNodeModel(bn).getTop() - next.getBottom() + mDy;
134 |
135 | //上移动
136 | ArrayList> allLowNodes = mTree.getAllLowNodes(bn);
137 | ArrayList> allPreNodes = mTree.getAllPreNodes(tn);
138 |
139 | for (NodeModel low : allLowNodes) {
140 | NodeView view = (NodeView) treeView.findNodeViewFromNodeModel(low);
141 | moveNodeLayout(treeView, view, bnDr);
142 | }
143 |
144 | for (NodeModel pre : allPreNodes) {
145 | NodeView view = (NodeView) treeView.findNodeViewFromNodeModel(pre);
146 | moveNodeLayout(treeView, view, -topDr);
147 | }
148 | }
149 | }
150 |
151 | /**
152 | * 标准分布
153 | *
154 | * @param treeView
155 | * @param rootView
156 | */
157 | private void standardLayout(TreeView treeView, NodeView rootView) {
158 | NodeModel treeNode = rootView.getTreeNode();
159 | if (treeNode != null) {
160 | //所有的子节点
161 | LinkedList> childNodes = treeNode.getChildNodes();
162 | int size = childNodes.size();
163 | int mid = size / 2;
164 | int r = size % 2;
165 |
166 | //基线
167 | // b
168 | // a-------
169 | // c
170 | //
171 | int left = rootView.getRight() + mDx;
172 | int top = rootView.getTop() + rootView.getMeasuredHeight() / 2;
173 |
174 | int right = 0;
175 | int bottom = 0;
176 |
177 | if (size == 0) {
178 | return;
179 | } else if (size == 1) {
180 | NodeView midChildNodeView = (NodeView) treeView.findNodeViewFromNodeModel(childNodes.get(0));
181 |
182 | top = top - midChildNodeView.getMeasuredHeight() / 2;
183 | right = left + midChildNodeView.getMeasuredWidth();
184 | bottom = top + midChildNodeView.getMeasuredHeight();
185 | midChildNodeView.layout(left, top, right, bottom);
186 | } else {
187 |
188 | int topLeft = left;
189 | int topTop = top;
190 | int topRight = 0;
191 | int topBottom = 0;
192 |
193 | int bottomLeft = left;
194 | int bottomTop = top;
195 | int bottomRight = 0;
196 | int bottomBottom = 0;
197 |
198 | if (r == 0) {//偶数
199 | for (int i = mid - 1; i >= 0; i--) {
200 | NodeView topView = (NodeView) treeView.findNodeViewFromNodeModel(childNodes.get(i));
201 | NodeView bottomView = (NodeView) treeView.findNodeViewFromNodeModel(childNodes.get(size - i - 1));
202 |
203 |
204 | if (i == mid - 1) {
205 | topTop = topTop - mDy / 2 - topView.getMeasuredHeight();
206 | topRight = topLeft + topView.getMeasuredWidth();
207 | topBottom = topTop + topView.getMeasuredHeight();
208 |
209 | bottomTop = bottomTop + mDy / 2;
210 | bottomRight = bottomLeft + bottomView.getMeasuredWidth();
211 | bottomBottom = bottomTop + bottomView.getMeasuredHeight();
212 | } else {
213 | topTop = topTop - mDy - topView.getMeasuredHeight();
214 | topRight = topLeft + topView.getMeasuredWidth();
215 | topBottom = topTop + topView.getMeasuredHeight();
216 |
217 | bottomTop = bottomTop + mDy;
218 | bottomRight = bottomLeft + bottomView.getMeasuredWidth();
219 | bottomBottom = bottomTop + bottomView.getMeasuredHeight();
220 | }
221 |
222 | topView.layout(topLeft, topTop, topRight, topBottom);
223 | bottomView.layout(bottomLeft, bottomTop, bottomRight, bottomBottom);
224 |
225 | bottomTop = bottomView.getBottom();
226 | }
227 |
228 | } else {
229 | NodeView midView = (NodeView) treeView.findNodeViewFromNodeModel(childNodes.get(mid));
230 | midView.layout(left, top - midView.getMeasuredHeight() / 2, left + midView.getMeasuredWidth(),
231 | top - midView.getMeasuredHeight() / 2 + midView.getMeasuredHeight());
232 |
233 | topTop = midView.getTop();
234 | bottomTop = midView.getBottom();
235 |
236 | for (int i = mid - 1; i >= 0; i--) {
237 | NodeView topView = (NodeView) treeView.findNodeViewFromNodeModel(childNodes.get(i));
238 | NodeView bottomView = (NodeView) treeView.findNodeViewFromNodeModel(childNodes.get(size - i - 1));
239 |
240 | topTop = topTop - mDy - topView.getMeasuredHeight();
241 | topRight = topLeft + topView.getMeasuredWidth();
242 | topBottom = topTop + topView.getMeasuredHeight();
243 |
244 | bottomTop = bottomTop + mDy;
245 | bottomRight = bottomLeft + bottomView.getMeasuredWidth();
246 | bottomBottom = bottomTop + bottomView.getMeasuredHeight();
247 |
248 | topView.layout(topLeft, topTop, topRight, topBottom);
249 | bottomView.layout(bottomLeft, bottomTop, bottomRight, bottomBottom);
250 | bottomTop = bottomView.getBottom();
251 | }
252 | }
253 | }
254 | }
255 | }
256 |
257 | /**
258 | * 移动
259 | *
260 | * @param rootView
261 | * @param dy
262 | */
263 | private void moveNodeLayout(TreeView superTreeView, NodeView rootView, int dy) {
264 |
265 | Deque> queue = new ArrayDeque<>();
266 | NodeModel rootNode = rootView.getTreeNode();
267 | queue.add(rootNode);
268 | while (!queue.isEmpty()) {
269 | rootNode = queue.poll();
270 | rootView = (NodeView) superTreeView.findNodeViewFromNodeModel(rootNode);
271 | int l = rootView.getLeft();
272 | int t = rootView.getTop() + dy;
273 | rootView.layout(l, t, l + rootView.getMeasuredWidth(), t + rootView.getMeasuredHeight());
274 |
275 | LinkedList> childNodes = rootNode.getChildNodes();
276 | for (NodeModel item : childNodes) {
277 | queue.add(item);
278 | }
279 | }
280 | }
281 |
282 |
283 | /**
284 | * root节点的定位
285 | *
286 | * @param rootView
287 | */
288 | private void rootTreeViewLayout(NodeView rootView) {
289 | int lr = mDy;
290 | int tr = mDx;
291 | int rr = lr + rootView.getMeasuredWidth();
292 | int br = tr + rootView.getMeasuredHeight();
293 | rootView.layout(lr, tr, rr, br);
294 | }
295 | }
296 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/view/TreeLayoutManager.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.view;
2 |
3 | /**
4 | * Created by owant on 07/03/2017.
5 | */
6 |
7 | public interface TreeLayoutManager {
8 | /**
9 | * 进行树形结构的位置计算
10 | */
11 | void onTreeLayout(TreeView treeView);
12 |
13 | /**
14 | * 位置分布好后的回调,用于确认ViewGroup的大小
15 | */
16 | ViewBox onTreeLayoutCallBack();
17 |
18 | /**
19 | * 修正位置
20 | *
21 | * @param treeView
22 | * @param next
23 | */
24 | void correctLayout(TreeView treeView, NodeView next);
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/view/TreeViewItemClick.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.view;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Created by owant on 18/02/2017.
7 | */
8 |
9 | public interface TreeViewItemClick {
10 | void onItemClick(View item);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/view/TreeViewItemLongClick.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.view;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Created by owant on 24/02/2017.
7 | */
8 |
9 | public interface TreeViewItemLongClick {
10 | void onLongClick(View view);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/owant/thinkmap/view/ViewBox.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.view;
2 |
3 | /**
4 | * Created by owant on 06/03/2017.
5 | * 用于记录当前树形图的大小
6 | */
7 | public class ViewBox {
8 |
9 | public int top;
10 | public int left;
11 | public int right;
12 | public int bottom;
13 |
14 | public void clear() {
15 | this.top = 0;
16 | this.left = 0;
17 | this.right = 0;
18 | this.bottom = 0;
19 | }
20 |
21 | @Override
22 | public String toString() {
23 | return "ViewBox{" +
24 | "top=" + top +
25 | ", left=" + left +
26 | ", right=" + right +
27 | ", bottom=" + bottom +
28 | '}';
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/alpha_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/alpha_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/big_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/right_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/color/tab_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/box.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dialog_edit_input_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edit_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/enter_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 | -
12 |
13 |
14 |
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/node_view_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | -
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/selector_purple.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/tab_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v21/div_edit_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
22 |
23 |
31 |
32 |
40 |
41 |
49 |
50 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v21/item_current_file.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_about_us.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_code_model.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_edit_think_map.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
23 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
28 |
29 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_support.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_work_space_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
29 |
30 |
31 |
32 |
36 |
37 |
38 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_edit_input.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
19 |
20 |
26 |
27 |
37 |
38 |
44 |
45 |
61 |
62 |
70 |
71 |
72 |
73 |
77 |
78 |
92 |
93 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/div_action_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/div_edit_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
21 |
22 |
30 |
31 |
39 |
40 |
48 |
49 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_current_file.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
21 |
22 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/scroll_item_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
41 |
42 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/test_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/test_gv.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/work_space_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-hdpi/ic_launcher_app.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/support_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-hdpi/support_code.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/clear_input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xhdpi/clear_input.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xhdpi/ic_back.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xhdpi/ic_launcher_app.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/menu_moreoverflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xhdpi/menu_moreoverflow.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/ic_launcher_app.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/introduce.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/introduce.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/iv_add_node.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/iv_add_node.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/iv_add_sub_node.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/iv_add_sub_node.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/iv_code_mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/iv_code_mode.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/iv_front_view.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/iv_front_view.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/menu_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/menu_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxhdpi/search.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/raw/examples.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/app/src/main/res/raw/examples.zip
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 | #94B55A
8 | #5E703D
9 |
10 | #FFFFFF
11 | #F9F9F9
12 | #F8F2F2
13 | #DDDBDD
14 | #E0DEE0
15 |
16 | #22313f
17 | #E4E2E4
18 | #3C3F41
19 | #EFEFEF
20 | #BB0F23
21 | #bb0f45
22 | #2B2B2B
23 |
24 | #BFD49A
25 | #A8C474
26 | #778D4E
27 |
28 | #E794B55A
29 |
30 | #9932CC
31 | #9F79EE
32 | #00000000
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
7 | 48dp
8 | 240dp
9 |
10 |
11 | 56dp
12 | 48dp
13 | 24dp
14 |
15 |
16 | 104dp
17 |
18 |
19 | 40dp
20 | 56dp
21 | 40dp
22 |
23 |
24 | 16dp
25 | 16dp
26 | 1dp
27 | 5dp
28 | 10dp
29 | 15dp
30 | 5dp
31 | 10dp
32 | 15dp
33 | 5dp
34 | 10dp
35 | 15dp
36 | 5dp
37 | 10dp
38 | 15dp
39 |
40 |
41 | 10dp
42 | 1dp
43 | 5dp
44 | 8dp
45 | 15dp
46 |
47 |
48 |
49 | 14sp
50 | 14sp
51 | 12sp
52 | 14sp
53 | 16sp
54 | 16sp
55 | 20sp
56 | 24sp
57 | 34sp
58 | 45sp
59 | 56sp
60 | 112sp
61 |
62 |
63 | 75dp
64 | 60dp
65 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ThinkMap
4 | ThinkMap 让思维更有趣
5 |
6 | Think Map
7 | My Plan
8 | Add a same floor node.
9 | null_node
10 | Add a sub node.
11 | Edit Node
12 | add SubNode
13 | input a new node
14 | Enter
15 |
16 |
17 | SubNode
18 | Node
19 | FrontView
20 | CodeMode
21 | Delete
22 | You can not add a peer node to a root node!
23 | Save File
24 | NO
25 | Save
26 | File has been destroyed,Please delete!
27 | You have denied access to WRITE_EXTERNAL_STORAGE!
28 | trans_item
29 |
30 | My Plan
31 | unknow error!
32 | you denied read storage permission!
33 | Sorry, we need the Storage Permission to do that!
34 | Have the same name file!
35 | The file name is empty!
36 | OWANT FILE IS EMPTY !
37 | About
38 | Quit
39 | Do something interesting. \n\nzhongowant@gmail.com
40 | /OwantMaps/android.owant
41 | New Map
42 | About us
43 |
44 | Cancel
45 | Yes
46 | Note:\tRemove the file ?
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
21 |
22 |
23 |
28 |
29 |
38 |
39 |
45 |
46 |
47 |
62 |
63 |
64 |
67 |
68 |
69 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/app/src/test/java/com/owant/thinkmap/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap;
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 |
14 | @Test
15 | public void addition_isCorrect() throws Exception {
16 | assertEquals(4, 2 + 2);
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/test/java/com/owant/thinkmap/model/TreeModelTest.java:
--------------------------------------------------------------------------------
1 | package com.owant.thinkmap.model;
2 |
3 | import org.junit.After;
4 | import org.junit.Before;
5 | import org.junit.Test;
6 |
7 | /**
8 | * Created by owant on 14/04/2017.
9 | */
10 | public class TreeModelTest {
11 |
12 | TreeModel mTreeModel;
13 |
14 | @Before
15 | public void setUp() throws Exception {
16 | NodeModel root = new NodeModel<>("root");
17 | mTreeModel = new TreeModel<>(root);
18 | }
19 |
20 | @After
21 | public void tearDown() throws Exception {
22 |
23 | }
24 |
25 | @Test
26 | public void addNode() throws Exception {
27 | NodeModel addNode = new NodeModel<>("add note");
28 | mTreeModel.addNode(mTreeModel.getRootNode(), addNode);
29 |
30 | mTreeModel.addForTreeItem(new ForTreeItem>() {
31 | @Override
32 | public void next(int msg, NodeModel next) {
33 | System.out.printf("%s>>", next.getValue());
34 | }
35 | });
36 | mTreeModel.ergodicTreeInWith(1);
37 | }
38 |
39 | @Test
40 | public void removeNode() throws Exception {
41 |
42 | }
43 |
44 | @Test
45 | public void inTree() throws Exception {
46 |
47 | }
48 |
49 | @Test
50 | public void getRootNode() throws Exception {
51 |
52 | }
53 |
54 | @Test
55 | public void setRootNode() throws Exception {
56 |
57 | }
58 |
59 | @Test
60 | public void getLowNode() throws Exception {
61 |
62 | }
63 |
64 | @Test
65 | public void getPreNode() throws Exception {
66 |
67 | }
68 |
69 | @Test
70 | public void getAllLowNodes() throws Exception {
71 |
72 | }
73 |
74 | @Test
75 | public void getAllPreNodes() throws Exception {
76 |
77 | }
78 |
79 | @Test
80 | public void getNodeChildNodes() throws Exception {
81 |
82 | }
83 |
84 | @Test
85 | public void ergodicTreeInDeep() throws Exception {
86 |
87 | }
88 |
89 | @Test
90 | public void ergodicTreeInWith() throws Exception {
91 |
92 | }
93 |
94 | @Test
95 | public void addForTreeItem() throws Exception {
96 |
97 | }
98 |
99 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:2.3.1'
11 |
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Feb 02 13:38:32 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/info2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owant/ThinkMap/80be866bb34fd4acb44204192e4a564f3de7e60f/info2.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------