diff --git a/app/build.gradle b/app/build.gradle index 10d0535a..09a772d1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -92,7 +92,6 @@ dependencies { exclude group: 'com.afollestad.material-dialogs' exclude group: 'com.android.support' }) - // compile 'com.github.hyb1996:android-multi-level-listview:1.1' compile 'de.psdev.licensesdialog:licensesdialog:1.8.1' compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1' diff --git a/app/src/main/assets/indices/all.json b/app/src/main/assets/indices/all.json new file mode 100644 index 00000000..be065fe3 --- /dev/null +++ b/app/src/main/assets/indices/all.json @@ -0,0 +1,1036 @@ +[ + { + "name": "app", + "url": "app.html", + "summary": "应用", + "properties": [ + { + "key": "uninstall", + "url": "app.html#app_app_uninstall_packagename", + "summary": "卸载" + }, + { + "key": "viewFile", + "url": "app.html#app_app_viewfile_path", + "summary": "查看文件" + }, + { + "key": "editFile", + "url": "app.html#app_app_editfile_path", + "summary": "编辑文件" + }, + { + "key": "openUrl", + "url": "app.html#app_app_openurl_url", + "summary": "打开链接" + }, + { + "key": "launchPackage", + "url": "app.html#app_app_takephoto_path", + "summary": "启动包名" + }, + { + "key": "launch", + "url": "globals.html#globals_launchpackage_packagename", + "summary": "启动", + "global": true + }, + { + "key": "launchApp", + "url": "globals.html#globals_launchapp_appname", + "summary": "启动应用", + "global": true + }, + { + "key": "getPackageName", + "url": "globals.html#globals_getpackagename_appname", + "summary": "获取包名" + }, + { + "key": "openAppSetting", + "url": "globals.html#globals_getappname_packagename", + "summary": "应用设置页" + } + ] + }, + { + "name": "automator", + "url": "widgets-based-automation.html", + "summary": "自动操作", + "properties": [ + { + "key": "click", + "url": "widgets-based-automation.html#widgets_based_automation_click_text_i", + "summary": "点击", + "global": true + }, + { + "key": "longClick", + "url": "widgets-based-automation.html#widgets_based_automation_longclick_text_i", + "summary": "长按", + "global": true + }, + { + "key": "press", + "url": "", + "summary": "按住", + "global": true + }, + { + "key": "swipe", + "url": "", + "summary": "滑动", + "global": true + }, + { + "key": "gesture", + "url": "", + "summary": "手势", + "global": true + }, + { + "key": "gestures", + "url": "", + "summary": "异步手势", + "global": true + }, + { + "key": "gestureAsync", + "url": "", + "summary": "多手势", + "global": true + }, + { + "key": "gesturesAsync", + "url": "", + "summary": "异步多手势", + "global": true + }, + { + "key": "scrollDown", + "url": "widgets-based-automation.html#widgets_based_automation_scrollup_i", + "summary": "下滑", + "global": true + }, + { + "key": "scrollUp", + "url": "widgets-based-automation.html#widgets_based_automation_scrollup_i", + "summary": "上滑", + "global": true + }, + { + "key": "input", + "url": "widgets-based-automation.html#widgets_based_automation_input_i_text", + "summary": "输入文本", + "global": true + }, + { + "key": "setText", + "url": "widgets-based-automation.html#widgets_based_automation_settext_i_text", + "summary": "设置文本", + "global": true + } + ] + }, + { + "name": "console", + "url": "console.html", + "summary": "控制台", + "properties": [ + { + "key": "show", + "url": "console.html#console_console_show", + "summary": "显示" + }, + { + "key": "hide", + "url": "", + "summary": "隐藏" + }, + { + "key": "clear", + "url": "console.html#console_console_clear", + "summary": "清空" + }, + { + "key": "verbose", + "url": "console.html#console_console_verbose_data_args", + "summary": "不重要日志" + }, + { + "key": "info", + "url": "console.html#console_console_info_data_args", + "summary": "打印信息" + }, + { + "key": "log", + "url": "console.html#console_console_log_data_args", + "summary": "打印日志" + }, + { + "key": "warn", + "url": "console.html#console_console_warn_data_args", + "summary": "打印警告" + }, + { + "key": "error", + "url": "console.html#console_console_error_data_args", + "summary": "打印错误" + }, + { + "key": "assert", + "url": "console.html#console_console_assert_value_message", + "summary": "断言" + } + ] + }, + { + "name": "dialogs", + "url": "dialogs.html", + "summary": "对话框", + "properties": [ + { + "key": "select", + "url": "", + "summary": "选择" + }, + { + "key": "singleChoice", + "url": "", + "summary": "单选" + }, + { + "key": "multiChoice", + "url": "", + "summary": "多选" + }, + { + "key": "rawInput", + "url": "", + "summary": "输入字符串" + }, + { + "key": "input", + "url": "", + "summary": "输入" + }, + { + "key": "alert", + "url": "", + "summary": "消息框" + }, + { + "key": "confirm", + "url": "", + "summary": "确认框" + }, + { + "key": "prompt", + "url": "", + "summary": "输入字符串" + } + ] + }, + { + "name": "images", + "url": "images.html", + "summary": "图色", + "properties": [ + { + "key": "saveImage", + "url": "images.html#images_images_saveimage_image_path", + "summary": "保存图片" + }, + { + "key": "pixel", + "url": "images.html#images_images_pixel_image_x_y", + "summary": "取色" + }, + { + "key": "read", + "url": "", + "summary": "读取图片" + }, + { + "key": "requestScreenCapture", + "url": "images.html#images_requestscreencapture_width_height", + "summary": "请求截屏", + "global": true + }, + { + "key": "captureScreen", + "url": "images.html#images_capturescreen", + "summary": "截屏", + "global": true + }, + { + "key": "findColor", + "url": "images.html#images_images_findcolor_image_color_options", + "summary": "找色", + "global": true + }, + { + "key": "findColorInRegion", + "url": "images.html#images_images_findcolorinregion_img_color_x_y_width_height_threads_algorithm_threshold", + "summary": "区域找色", + "global": true + }, + { + "key": "findColorEquals", + "url": "images.html#images_images_findcolorequals_img_color_x_y_width_height_threads", + "summary": "精确找色", + "global": true + } + ] + }, + { + "name": "colors", + "url": "colors.html", + "summary": "颜色", + "properties": [ + { + "key": "red", + "url": "images.html#images_colors_red_color", + "summary": "R值" + }, + { + "key": "green", + "url": "images.html#images_colors_green_color", + "summary": "G值" + }, + { + "key": "blue", + "url": "images.html#images_colors_blue_color", + "summary": "B值" + }, + { + "key": "alpha", + "url": "images.html#images_colors_alpha_color", + "summary": "透明度" + }, + { + "key": "toString", + "url": "images.html#images_colors_tostring_color", + "summary": "颜色转字符串" + }, + { + "key": "rgb", + "url": "images.html#images_colors_rgb_red_green_blue", + "summary": "" + }, + { + "key": "argb", + "url": "images.html#images_colors_argb_alpha_red_green_blue", + "summary": "" + } + ] + }, + { + "name": "events", + "url": "events.html", + "summary": "事件", + "properties": [ + { + "key": "emitter", + "url": "events.html#events_events_emitter", + "summary": "" + }, + { + "key": "observeKey", + "url": "events.html#events_events_observekey", + "summary": "监听按键" + }, + { + "key": "observeTouch", + "url": "events.html#events_events_observetouch", + "summary": "监听触摸" + }, + { + "key": "observeNotification", + "url": "events.html#events_obversenotification", + "summary": "监听通知" + }, + { + "key": "onKeyDown", + "url": "events.html#events_events_onkeydown_keyname_listener", + "summary": "按键按下事件" + }, + { + "key": "onKeyUp", + "url": "events.html#events_events_onkeyup_keyname_listener", + "summary": "按键弹起事件" + }, + { + "key": "onceKeyDown", + "url": "events.html#events_events_oncekeydown_keyname_listener", + "summary": "" + }, + { + "key": "onceKeyUp", + "url": "events.html#events_events_oncekeyup_keyname_listener", + "summary": "" + }, + { + "key": "onToast", + "url": "events.html#events_toast", + "summary": "toast事件" + }, + { + "key": "onNotification", + "url": "events.html#events_notification", + "summary": "通知事件" + }, + { + "key": "removeAllKeyDownListeners", + "url": "events.html#events_events_removeallkeydownlisteners_keyname", + "summary": "" + }, + { + "key": "removeAllKeyUpListeners", + "url": "events.html#events_events_removeallkeyuplisteners_keyname", + "summary": "" + }, + { + "key": "onTouch", + "url": "events.html#events_events_ontouch_listener", + "summary": "触摸事件" + }, + { + "key": "removeAllTouchListeners", + "url": "events.html#events_events_removealltouchlisteners", + "summary": "" + }, + { + "key": "getTouchEventTimeout", + "url": "events.html#events_events_gettoucheventtimeout", + "summary": "" + }, + { + "key": "setTouchEventTimeout", + "url": "events.html#events_events_settoucheventtimeout_timeout", + "summary": "" + }, + { + "key": "on", + "url": "events.html#events_eventemitter_on_eventname_listener", + "summary": "" + }, + { + "key": "once", + "url": "events.html#events_eventemitter_once_eventname_listener", + "summary": "" + }, + { + "key": "emit", + "url": "events.html#events_eventemitter_emit_eventname_args", + "summary": "" + }, + { + "key": "getListeners", + "url": "", + "summary": "" + }, + { + "key": "addListener", + "url": "events.html#events_eventemitter_addlistener_eventname_listener", + "summary": "" + }, + { + "key": "eventNames", + "url": "events.html#events_eventemitter_eventnames", + "summary": "" + }, + { + "key": "listenerCount", + "url": "events.html#events_eventemitter_listenercount_eventname", + "summary": "" + }, + { + "key": "listeners", + "url": "events.html#events_eventemitter_listeners_eventname", + "summary": "" + }, + { + "key": "prependListener", + "url": "events.html#events_eventemitter_prependlistener_eventname_listener", + "summary": "" + }, + { + "key": "prependOnceListener", + "url": "events.html#events_eventemitter_prependoncelistener_eventname_listener", + "summary": "" + }, + { + "key": "removeAllListeners", + "url": "events.html#events_eventemitter_removealllisteners_eventname", + "summary": "" + }, + { + "key": "removeListener", + "url": "events.html#events_eventemitter_removelistener_eventname_listener", + "summary": "" + }, + { + "key": "setMaxListeners", + "url": "events.html#events_eventemitter_setmaxlisteners_n", + "summary": "" + }, + { + "key": "getMaxListeners", + "url": "events.html#events_eventemitter_getmaxlisteners", + "summary": "" + }, + { + "key": "defaultMaxListeners", + "url": "events.html#events_eventemitter_defaultmaxlisteners", + "summary": "" + } + ] + }, + { + "name": "files", + "url": "files.html", + "summary": "文件", + "properties": [ + { + "key": "open", + "url": "", + "summary": "打开文件", + "global": true + }, + { + "key": "isFile", + "url": "files.html#files_files_isfile_path", + "summary": "文件判断" + }, + { + "key": "isDir", + "url": "files.html#files_files_isdir_path", + "summary": "文件夹判断" + }, + { + "key": "isEmptyDir", + "url": "files.html#files_files_isemptydir_path", + "summary": "空文件夹判断" + }, + { + "key": "join", + "url": "files.html#files_files_join_parent_child", + "summary": "连接路径" + }, + { + "key": "create", + "url": "files.html#files_files_create_path", + "summary": "创建文件" + }, + { + "key": "createIfNotExists", + "url": "files.html#files_files_createifnotexists_path", + "summary": "创建文件" + }, + { + "key": "exists", + "url": "files.html#files_files_exists_path", + "summary": "判断文件存在" + }, + { + "key": "ensureDir", + "url": "files.html#files_files_ensuredir_path", + "summary": "确保文件夹" + }, + { + "key": "read", + "url": "files.html#files_files_read_path_encoding_utf_8", + "summary": "读取文本" + }, + { + "key": "write", + "url": "files.html#files_files_write_path_text_encoding_utf_8", + "summary": "写入文本" + }, + { + "key": "copy", + "url": "files.html#files_files_copy_frompath_topath", + "summary": "复制" + }, + { + "key": "move", + "url": "files.html#files_files_move_frompath_topath", + "summary": "移动" + }, + { + "key": "rename", + "url": "files.html#files_files_rename_path_newname", + "summary": "重命名" + }, + { + "key": "renameWithoutExtension", + "url": "files.html#files_files_renamewithoutextension_path_newname", + "summary": "重命名" + }, + { + "key": "getName", + "url": "files.html#files_files_getname_path", + "summary": "获取文件名" + }, + { + "key": "getExtension", + "url": "files.html#files_files_getextension_path", + "summary": "获取拓展名" + }, + { + "key": "getNameWithoutExtension", + "url": "files.html#files_files_getnamewithoutextension_path", + "summary": "获取文件名" + }, + { + "key": "remove", + "url": "files.html#files_files_remove_path", + "summary": "删除" + }, + { + "key": "removeDir", + "url": "files.html#files_files_removedir_path", + "summary": "删除文件夹" + }, + { + "key": "getSdcardPath", + "url": "files.html#files_files_getsdcardpath", + "summary": "SD卡路径" + }, + { + "key": "listDir", + "url": "files.html#files_files_listdir_path_filter", + "summary": "列表文件夹" + } + ] + }, + { + "name": "timers", + "url": "timers.html", + "summary": "定时器", + "properties": [ + { + "key": "setTimeout", + "url": "timers.html#timers_settimeout_callback_delay_args", + "summary": "定时执行", + "global": true + }, + { + "key": "clearTimeout", + "url": "timers.html#timers_cleartimeout_id", + "summary": "取消定时", + "global": true + }, + { + "key": "setInterval", + "url": "timers.html#timers_setinterval_callback_delay_args", + "summary": "循环执行", + "global": true + }, + { + "key": "clearInterval", + "url": "timers.html#timers_clearinterval_id", + "summary": "清除循环", + "global": true + }, + { + "key": "setImmediate", + "url": "timers.html#timers_setimmediate_callback_args", + "summary": "\"立即\"执行", + "global": true + }, + { + "key": "clearImmediate", + "url": "timers.html#timers_clearimmediate_id", + "summary": "清除\"立即\"", + "global": true + } + ] + }, + { + "name": "selector", + "url": "widgets-based-automation.html", + "summary": "选择器", + "properties": [ + { + "key": "id", + "url": "", + "summary": "", + "global": true + }, + { + "key": "idContains", + "url": "", + "summary": "", + "global": true + }, + { + "key": "idStartsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "idEndsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "idMatches", + "url": "", + "summary": "", + "global": true + }, + { + "key": "text", + "url": "", + "summary": "", + "global": true + }, + { + "key": "textContains", + "url": "", + "summary": "", + "global": true + }, + { + "key": "textStartsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "textEndsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "textMatches", + "url": "", + "summary": "", + "global": true + }, + { + "key": "desc", + "url": "", + "summary": "", + "global": true + }, + { + "key": "descContains", + "url": "", + "summary": "", + "global": true + }, + { + "key": "descStartsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "descEndsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "descMatches", + "url": "", + "summary": "", + "global": true + }, + { + "key": "className", + "url": "", + "summary": "", + "global": true + }, + { + "key": "classNameContains", + "url": "", + "summary": "", + "global": true + }, + { + "key": "classNameStartsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "classNameEndsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "classNameMatches", + "url": "", + "summary": "", + "global": true + }, + { + "key": "packageName", + "url": "", + "summary": "", + "global": true + }, + { + "key": "packageNameContains", + "url": "", + "summary": "", + "global": true + }, + { + "key": "packageNameStartsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "packageNameEndsWith", + "url": "", + "summary": "", + "global": true + }, + { + "key": "packageNameMatches", + "url": "", + "summary": "", + "global": true + }, + { + "key": "bounds", + "url": "", + "summary": "", + "global": true + }, + { + "key": "boundsInside", + "url": "", + "summary": "", + "global": true + }, + { + "key": "boundsContains", + "url": "", + "summary": "", + "global": true + }, + { + "key": "drawingOrder", + "url": "", + "summary": "", + "global": true + }, + { + "key": "checkable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "checked", + "url": "", + "summary": "", + "global": true + }, + { + "key": "focusable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "focused", + "url": "", + "summary": "", + "global": true + }, + { + "key": "visibleToUser", + "url": "", + "summary": "", + "global": true + }, + { + "key": "accessibilityFocused", + "url": "", + "summary": "", + "global": true + }, + { + "key": "selected", + "url": "", + "summary": "", + "global": true + }, + { + "key": "clickable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "longClickable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "enabled", + "url": "", + "summary": "", + "global": true + }, + { + "key": "password", + "url": "", + "summary": "", + "global": true + }, + { + "key": "scrollable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "editable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "contentInvalid", + "url": "", + "summary": "", + "global": true + }, + { + "key": "contextClickable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "multiLine", + "url": "", + "summary": "", + "global": true + }, + { + "key": "dismissable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "checkable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "checked", + "url": "", + "summary": "", + "global": true + }, + { + "key": "focusable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "focused", + "url": "", + "summary": "", + "global": true + }, + { + "key": "visibleToUser", + "url": "", + "summary": "", + "global": true + }, + { + "key": "accessibilityFocused", + "url": "", + "summary": "", + "global": true + }, + { + "key": "selected", + "url": "", + "summary": "", + "global": true + }, + { + "key": "clickable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "longClickable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "enabled", + "url": "", + "summary": "", + "global": true + }, + { + "key": "password", + "url": "", + "summary": "", + "global": true + }, + { + "key": "scrollable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "editable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "contentInvalid", + "url": "", + "summary": "", + "global": true + }, + { + "key": "contextClickable", + "url": "", + "summary": "", + "global": true + }, + { + "key": "multiLine", + "url": "", + "summary": "", + "global": true + }, + { + "key": "dismissable", + "url": "", + "summary": "", + "global": true + } + ] + } +] \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/model/indices/Module.java b/app/src/main/java/com/stardust/scriptdroid/model/indices/Module.java new file mode 100644 index 00000000..469f220a --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/model/indices/Module.java @@ -0,0 +1,56 @@ +package com.stardust.scriptdroid.model.indices; + +import com.google.gson.annotations.SerializedName; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Stardust on 2017/12/9. + */ + +public class Module { + + @SerializedName("properties") + + private List mProperties = new ArrayList<>(); + + @SerializedName("url") + private String mUrl; + @SerializedName("name") + private String mName; + @SerializedName("summary") + private String mSummary; + + public List getProperties() { + return mProperties; + } + + public void setProperties(List properties) { + mProperties = properties; + } + + public String getUrl() { + return mUrl; + } + + public void setUrl(String url) { + mUrl = url; + } + + public String getName() { + return mName; + } + + public void setName(String name) { + mName = name; + } + + public String getSummary() { + return mSummary; + } + + public void setSummary(String summary) { + mSummary = summary; + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/model/indices/Modules.java b/app/src/main/java/com/stardust/scriptdroid/model/indices/Modules.java new file mode 100644 index 00000000..a809353f --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/model/indices/Modules.java @@ -0,0 +1,50 @@ +package com.stardust.scriptdroid.model.indices; + +import android.content.Context; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.util.List; +import java.util.concurrent.Callable; + +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Consumer; +import io.reactivex.schedulers.Schedulers; + +/** + * Created by Stardust on 2017/12/9. + */ + +public class Modules { + + private static final Type MODULE_LIST_TYPE = new TypeToken>() { + + }.getType(); + private static final String MODULES_JSON_PATH = "indices/all.json"; + private static Modules sInstance = new Modules(); + + private List mModules; + + private List loadModulesFrom(InputStream inputStream) { + Gson gson = new Gson(); + return gson.fromJson(new InputStreamReader(inputStream), MODULE_LIST_TYPE); + } + + public Observable> getModules(Context context) { + if (mModules != null) + return Observable.just(mModules); + return Observable.fromCallable(() -> loadModulesFrom(context.getAssets().open(MODULES_JSON_PATH))) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(modules -> mModules = modules); + } + + public static Modules getInstance() { + return sInstance; + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/model/indices/Property.java b/app/src/main/java/com/stardust/scriptdroid/model/indices/Property.java new file mode 100644 index 00000000..b5a3e945 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/model/indices/Property.java @@ -0,0 +1,54 @@ +package com.stardust.scriptdroid.model.indices; + +import com.google.gson.annotations.SerializedName; + +/** + * Created by Stardust on 2017/12/9. + */ + +public class Property { + + @SerializedName("url") + private String mUrl; + + @SerializedName("key") + private String mKey; + + @SerializedName("summary") + private String mSummary; + + @SerializedName("global") + private boolean mGlobal; + + public String getUrl() { + return mUrl; + } + + public void setUrl(String url) { + mUrl = url; + } + + public String getKey() { + return mKey; + } + + public void setKey(String key) { + mKey = key; + } + + public String getSummary() { + return mSummary; + } + + public void setSummary(String summary) { + mSummary = summary; + } + + public boolean isGlobal() { + return mGlobal; + } + + public void setGlobal(boolean global) { + mGlobal = global; + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/tool/InputMethodTool.java b/app/src/main/java/com/stardust/scriptdroid/tool/InputMethodTool.java new file mode 100644 index 00000000..b0782dd0 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/tool/InputMethodTool.java @@ -0,0 +1,19 @@ +package com.stardust.scriptdroid.tool; + +import android.content.Context; +import android.view.View; +import android.view.inputmethod.InputMethodManager; + +/** + * Created by Stardust on 2017/12/9. + */ + +public class InputMethodTool { + + public static void dismissInputMethod(Context context, View view) { + InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm == null) + return; + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } +} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/edit/EditorView.java b/app/src/main/java/com/stardust/scriptdroid/ui/edit/EditorView.java index de2ad7cb..63a06f3a 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/edit/EditorView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/edit/EditorView.java @@ -1,5 +1,6 @@ package com.stardust.scriptdroid.ui.edit; +import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -8,6 +9,7 @@ import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.widget.DrawerLayout; +import android.text.TextUtils; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; @@ -21,15 +23,20 @@ import com.stardust.autojs.script.JavaScriptFileSource; import com.stardust.pio.PFiles; import com.stardust.scriptdroid.Pref; import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.model.indices.Module; +import com.stardust.scriptdroid.model.indices.Property; import com.stardust.scriptdroid.model.script.Scripts; import com.stardust.scriptdroid.ui.doc.ManualDialog; import com.stardust.scriptdroid.ui.edit.completion.CodeCompletions; import com.stardust.scriptdroid.ui.edit.completion.CodeCompletionBar; import com.stardust.scriptdroid.ui.edit.completion.InputMethodEnhancedBarColors; import com.stardust.scriptdroid.ui.edit.completion.Symbols; +import com.stardust.scriptdroid.ui.edit.keyboard.FunctionsKeyboardHelper; +import com.stardust.scriptdroid.ui.edit.keyboard.FunctionsKeyboardView; import com.stardust.scriptdroid.ui.log.LogActivity_; import com.stardust.scriptdroid.ui.widget.EWebView; import com.stardust.scriptdroid.ui.widget.ToolbarMenuItem; +import com.stardust.util.BackPressedHandler; import com.stardust.widget.ViewSwitcher; import org.androidannotations.annotations.AfterViews; @@ -50,7 +57,7 @@ import static com.stardust.scriptdroid.model.script.Scripts.ACTION_ON_EXECUTION_ * Created by Stardust on 2017/9/28. */ @EViewGroup(R.layout.editor_view) -public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintClickListener { +public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintClickListener, FunctionsKeyboardView.ClickCallback { public static final String EXTRA_PATH = "Still Love Eating 17.4.5"; public static final String EXTRA_NAME = "Still love you 17.6.29 But....(ಥ_ಥ)"; @@ -77,8 +84,11 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC @ViewById(R.id.symbol_bar) CodeCompletionBar mSymbolBar; - @ViewById(R.id.functions) - ImageView mFunctions; + @ViewById(R.id.properties) + ImageView mShowFunctionsButton; + + @ViewById(R.id.functions_keyboard) + FunctionsKeyboardView mFunctionsKeyboard; @ViewById(R.id.docs) EWebView mEWebView; @@ -94,6 +104,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC private ScriptExecution mScriptExecution; private boolean mTextChanged = false; + private FunctionsKeyboardHelper mFunctionsKeyboardHelper; private BroadcastReceiver mOnRunFinishedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -129,12 +140,18 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC protected void onAttachedToWindow() { super.onAttachedToWindow(); getContext().registerReceiver(mOnRunFinishedReceiver, new IntentFilter(ACTION_ON_EXECUTION_FINISHED)); + if (getContext() instanceof BackPressedHandler.HostActivity) { + ((BackPressedHandler.HostActivity) getContext()).getBackPressedObserver().registerHandler(mFunctionsKeyboardHelper); + } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); getContext().unregisterReceiver(mOnRunFinishedReceiver); + if (getContext() instanceof BackPressedHandler.HostActivity) { + ((BackPressedHandler.HostActivity) getContext()).getBackPressedObserver().unregisterHandler(mFunctionsKeyboardHelper); + } } public File getFile() { @@ -182,12 +199,23 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC void init() { setUpEditor(); setUpInputMethodEnhancedBar(); + setUpFunctionsKeyboard(); setMenuItemStatus(R.id.save, false); mEWebView.getWebView().getSettings().setDisplayZoomControls(true); mEWebView.getWebView().loadUrl(Pref.getDocumentationUrl() + "index.html"); } + private void setUpFunctionsKeyboard() { + mFunctionsKeyboardHelper = FunctionsKeyboardHelper.with((Activity) getContext()) + .setContent(mEditor) + .setFunctionsTrigger(mShowFunctionsButton) + .setFunctionsView(mFunctionsKeyboard) + .setEditView(mEditor.getWebView()) + .build(); + mFunctionsKeyboard.setClickCallback(this); + } + private void setUpInputMethodEnhancedBar() { mSymbolBar.setCodeCompletions(Symbols.getSymbols()); mCodeCompletionBar.setOnHintClickListener(this); @@ -226,13 +254,9 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC int textColor = InputMethodEnhancedBarColors.getTextColor(theme); mCodeCompletionBar.setTextColor(textColor); mSymbolBar.setTextColor(textColor); - mFunctions.setColorFilter(textColor); + mShowFunctionsButton.setColorFilter(textColor); } - @Click(R.id.functions) - void showFunctionList() { - - } @Click(R.id.run) public void runAndSaveFileIfNeeded() { @@ -369,7 +393,6 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC public void onHintClick(CodeCompletions completions, int pos) { if (completions.shouldBeInserted()) { mEditor.insert(completions.getHints().get(pos)); - showFunctionList(); return; } mEditor.replace(completions.getHints().get(pos), completions.getFrom().line, completions.getFrom().ch, @@ -381,9 +404,14 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC String url = completions.getUrltAt(pos); if (url == null) return; + showManual(url, completions.getHints().get(pos)); + + } + + private void showManual(String url, String title) { String absUrl = Pref.getDocumentationUrl() + url; new ManualDialog(getContext()) - .title(completions.getHints().get(pos)) + .title(title) .url(absUrl) .pinToLeft(v -> { mEWebView.getWebView().loadUrl(absUrl); @@ -391,4 +419,28 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC }) .show(); } + + @Override + public void onModuleLongClick(Module module) { + showManual(module.getUrl(), module.getName()); + } + + @Override + public void onPropertyClick(Module m, Property property) { + if (property.isGlobal()) { + mEditor.insert(property.getKey()); + } else { + mEditor.insert(m.getName() + "." + property.getKey()); + } + mFunctionsKeyboardHelper.hideFunctionsLayout(true); + } + + @Override + public void onPropertyLongClick(Module m, Property property) { + if (TextUtils.isEmpty(property.getUrl())) { + showManual(m.getUrl(), property.getKey()); + } else { + showManual(property.getUrl(), property.getKey()); + } + } } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/edit/keyboard/FunctionsKeyboardHelper.java b/app/src/main/java/com/stardust/scriptdroid/ui/edit/keyboard/FunctionsKeyboardHelper.java new file mode 100644 index 00000000..162607a8 --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/edit/keyboard/FunctionsKeyboardHelper.java @@ -0,0 +1,192 @@ +package com.stardust.scriptdroid.ui.edit.keyboard; + +/** + * Created by Stardust on 2017/12/9. + */ + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Rect; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.InputMethodManager; +import android.widget.LinearLayout; + +import com.stardust.util.BackPressedHandler; + +/** + * https://github.com/dss886/Android-FunctionsInputDetector + */ +public class FunctionsKeyboardHelper implements BackPressedHandler { + + private static final String SHARE_PREFERENCE_NAME = "FunctionsKeyboardHelper"; + private static final String SHARE_PREFERENCE_SOFT_INPUT_HEIGHT = "soft_input_height"; + private Activity mActivity; + private InputMethodManager mInputManager; + private SharedPreferences mPreferences; + private View mFunctionsLayout; + private View mEditView; + private View mContentView; + + private FunctionsKeyboardHelper(Activity activity) { + mActivity = activity; + mInputManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + mPreferences = activity.getSharedPreferences(SHARE_PREFERENCE_NAME, Context.MODE_PRIVATE); + } + + public static FunctionsKeyboardHelper with(Activity activity) { + return new FunctionsKeyboardHelper(activity); + } + + public FunctionsKeyboardHelper setContent(View contentView) { + mContentView = contentView; + return this; + } + + public void onSoftKeyboardShown() { + if (mFunctionsLayout.isShown()) { + lockContentHeight(); + hideFunctionsLayout(false); + mEditView.postDelayed(FunctionsKeyboardHelper.this::unlockContentHeightDelayed, 200L); + } + } + + @SuppressLint("ClickableViewAccessibility") + public FunctionsKeyboardHelper setEditView(View editView) { + mEditView = editView; + mEditView.requestFocus(); + editView.setOnTouchListener((v, event) -> { + if (event.getAction() == MotionEvent.ACTION_DOWN) + onSoftKeyboardShown(); + return false; + }); + return this; + } + + + public FunctionsKeyboardHelper setFunctionsTrigger(View triggerButton) { + triggerButton.setOnClickListener(v -> { + if (mFunctionsLayout.isShown()) { + lockContentHeight(); + hideFunctionsLayout(true); + unlockContentHeightDelayed(); + } else { + if (isSoftInputShown()) { + lockContentHeight(); + showFunctionsLayout(); + unlockContentHeightDelayed(); + } else { + showFunctionsLayout();//两者都没显示,直接显示表情布局 + } + } + }); + return this; + } + + public FunctionsKeyboardHelper setFunctionsView(View FunctionsView) { + mFunctionsLayout = FunctionsView; + return this; + } + + public FunctionsKeyboardHelper build() { + mActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN | + WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + hideSoftInput(); + return this; + } + + private void showFunctionsLayout() { + int softInputHeight = getSupportSoftInputHeight(); + if (softInputHeight == 0) { + softInputHeight = mPreferences.getInt(SHARE_PREFERENCE_SOFT_INPUT_HEIGHT, 400); + } + hideSoftInput(); + mFunctionsLayout.getLayoutParams().height = softInputHeight; + mFunctionsLayout.setVisibility(View.VISIBLE); + } + + + public void hideFunctionsLayout(boolean showSoftInput) { + if (mFunctionsLayout.isShown()) { + mFunctionsLayout.setVisibility(View.GONE); + if (showSoftInput) { + showSoftInput(); + } + } + } + + + private void lockContentHeight() { + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mContentView.getLayoutParams(); + params.height = mContentView.getHeight(); + params.weight = 0.0F; + } + + + private void unlockContentHeightDelayed() { + mEditView.postDelayed(() -> ((LinearLayout.LayoutParams) mContentView.getLayoutParams()).weight = 1.0F, 200L); + } + + private void showSoftInput() { + mEditView.requestFocus(); + mEditView.post(() -> mInputManager.showSoftInput(mEditView, InputMethodManager.SHOW_FORCED)); + } + + + private void hideSoftInput() { + mInputManager.hideSoftInputFromWindow(mEditView.getWindowToken(), 0); + } + + + private boolean isSoftInputShown() { + return getSupportSoftInputHeight() != 0; + } + + private int getSupportSoftInputHeight() { + Rect r = new Rect(); + mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r); + int screenHeight = mActivity.getWindow().getDecorView().getRootView().getHeight(); + int softInputHeight = screenHeight - r.bottom; + if (Build.VERSION.SDK_INT >= 20) { + // When SDK Level >= 20 (Android L), the softInputHeight will contain the height of softButtonsBar (if has) + softInputHeight = softInputHeight - getSoftKeyButtonsHeight(); + } + if (softInputHeight > 0) { + mPreferences.edit().putInt(SHARE_PREFERENCE_SOFT_INPUT_HEIGHT, softInputHeight).apply(); + } + return softInputHeight; + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) + private int getSoftKeyButtonsHeight() { + DisplayMetrics metrics = new DisplayMetrics(); + mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics); + int usableHeight = metrics.heightPixels; + mActivity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics); + int realHeight = metrics.heightPixels; + if (realHeight > usableHeight) { + return realHeight - usableHeight; + } else { + return 0; + } + } + + public int getKeyBoardHeight() { + return mPreferences.getInt(SHARE_PREFERENCE_SOFT_INPUT_HEIGHT, 400); + } + + @Override + public boolean onBackPressed(Activity activity) { + if (mFunctionsLayout.isShown()) { + hideFunctionsLayout(false); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/edit/keyboard/FunctionsKeyboardView.java b/app/src/main/java/com/stardust/scriptdroid/ui/edit/keyboard/FunctionsKeyboardView.java new file mode 100644 index 00000000..83e6f70f --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/edit/keyboard/FunctionsKeyboardView.java @@ -0,0 +1,306 @@ +package com.stardust.scriptdroid.ui.edit.keyboard; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.DividerItemDecoration; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.stardust.scriptdroid.R; +import com.stardust.scriptdroid.model.indices.Module; +import com.stardust.scriptdroid.model.indices.Modules; +import com.stardust.scriptdroid.model.indices.Property; +import com.stardust.scriptdroid.ui.widget.GridDividerDecoration; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import butterknife.BindView; +import butterknife.ButterKnife; +import io.reactivex.android.schedulers.AndroidSchedulers; + +/** + * Created by Stardust on 2017/12/9. + */ + +public class FunctionsKeyboardView extends FrameLayout { + + public interface ClickCallback { + void onModuleLongClick(Module module); + + void onPropertyClick(Module m, Property property); + + void onPropertyLongClick(Module m, Property property); + } + + private static final int SPAN_COUNT = 4; + @BindView(R.id.module_list) + RecyclerView mModulesView; + + @BindView(R.id.properties) + RecyclerView mPropertiesView; + + private List mModules; + private Map> mSpanSizes = new HashMap<>(); + private Module mSelectedModule; + private View mSelectedModuleView; + private Paint mPaint; + private ClickCallback mClickCallback; + + public FunctionsKeyboardView(@NonNull Context context) { + super(context); + init(); + } + + public FunctionsKeyboardView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(); + } + + public FunctionsKeyboardView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public FunctionsKeyboardView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + public void setClickCallback(ClickCallback clickCallback) { + mClickCallback = clickCallback; + } + + private void init() { + inflate(getContext(), R.layout.functions_keyboard_view, this); + ButterKnife.bind(this); + initModulesView(); + initPropertiesView(); + } + + private void initPropertiesView() { + GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), SPAN_COUNT); + mPropertiesView.setLayoutManager(gridLayoutManager); + mPropertiesView.setAdapter(new PropertiesAdapter()); + gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + + @Override + public int getSpanSize(int position) { + return mSpanSizes.get(mSelectedModule).get(position); + } + }); + Drawable divider = ContextCompat.getDrawable(getContext(), R.drawable.divider_functions_view); + GridDividerDecoration dividerItemDecoration = new GridDividerDecoration(getContext(), divider); + mPropertiesView.addItemDecoration(dividerItemDecoration); + + } + + private void initSpanSizes(Module module) { + if (mSpanSizes.containsKey(module)) + return; + if (getMeasuredWidth() == 0) + throw new IllegalStateException(); + List spanSizes = new ArrayList<>(); + //初始化spanSizes列表 + for (Property property : mSelectedModule.getProperties()) { + int width = Math.max(getTextWidth(property.getKey()), getTextWidth(property.getSummary())); + int spanSize = (int) Math.ceil(width / ((double) getMeasuredWidth() / 4)); + spanSizes.add(Math.min(spanSize, 2)); + } + //遍历这个列表,调整spanSize。例如以下这种情况时: + // [] [] [] + // [ ] [] [] + // [] [] [] [] + //把第一行的第三个元素的spanSize设置为2 + int column = 0; + for (int i = 0; i < spanSizes.size(); i++) { + int spanSize = spanSizes.get(i); + if (spanSize + column > SPAN_COUNT) { + spanSizes.set(i - 1, 2); + column = spanSize; + } else { + column += spanSize; + } + if (column == 4) { + column = 0; + } + } + mSpanSizes.put(module, spanSizes); + } + + private String getDisplayText(Property property) { + if (TextUtils.isEmpty(property.getSummary())) + return property.getKey(); + return property.getKey() + "\n" + property.getSummary(); + } + + private int getTextWidth(String text) { + if (mPaint == null) { + mPaint = new Paint(); + mPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen.textSize_item_property)); + } + Rect r = new Rect(); + mPaint.getTextBounds(text, 0, text.length(), r); + return r.width(); + } + + private void initModulesView() { + mModulesView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayout.HORIZONTAL, false)); + mModulesView.setAdapter(new ModulesAdapter()); + } + + private void loadModules() { + Modules.getInstance().getModules(getContext()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(modules -> { + mModules = modules; + if (modules.size() > 0) { + setSelectedModule(modules.get(0), null); + } + mModulesView.getAdapter().notifyDataSetChanged(); + mPropertiesView.getAdapter().notifyDataSetChanged(); + }); + } + + + private void setSelectedModule(Module module, @Nullable View moduleView) { + mSelectedModule = module; + if (mSelectedModuleView != null) { + mSelectedModuleView.setSelected(false); + } + mSelectedModuleView = moduleView; + if (mSelectedModuleView != null) + mSelectedModuleView.setSelected(true); + initSpanSizes(mSelectedModule); + mPropertiesView.getAdapter().notifyDataSetChanged(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (mModules == null) + loadModules(); + } + + private class ModuleViewHolder extends RecyclerView.ViewHolder { + + + private TextView mTextView; + private Module mModule; + + ModuleViewHolder(View itemView) { + super(itemView); + mTextView = (TextView) itemView; + mTextView.setOnClickListener(v -> { + if (mModule == null) + return; + setSelectedModule(mModule, mTextView); + }); + mTextView.setOnLongClickListener(v -> { + if (mClickCallback != null) { + mClickCallback.onModuleLongClick(mModule); + return true; + } + return false; + }); + } + + + void bind(Module module) { + mModule = module; + mTextView.setText(module.getSummary()); + mTextView.setSelected(module == mSelectedModule); + if (module == mSelectedModule) { + mSelectedModuleView = mTextView; + } + } + } + + + private class PropertyViewHolder extends RecyclerView.ViewHolder { + + private TextView mTextView; + private Property mProperty; + + PropertyViewHolder(View itemView) { + super(itemView); + mTextView = (TextView) itemView; + mTextView.setOnLongClickListener(v -> { + if (mClickCallback != null) { + mClickCallback.onPropertyLongClick(mSelectedModule, mProperty); + return true; + } + return false; + }); + mTextView.setOnClickListener(v -> { + if (mClickCallback != null) { + mClickCallback.onPropertyClick(mSelectedModule, mProperty); + } + }); + } + + void bind(Property property) { + mProperty = property; + mTextView.setText(getDisplayText(property)); + } + } + + private class ModulesAdapter extends RecyclerView.Adapter { + + @Override + public ModuleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new ModuleViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_module, parent, false)); + } + + @Override + public void onBindViewHolder(ModuleViewHolder holder, int position) { + holder.bind(mModules.get(position)); + } + + @Override + public int getItemCount() { + return mModules == null ? 0 : mModules.size(); + } + } + + private class PropertiesAdapter extends RecyclerView.Adapter { + + @Override + public PropertyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new PropertyViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_property, parent, false)); + } + + @Override + public void onBindViewHolder(PropertyViewHolder holder, int position) { + holder.bind(mSelectedModule.getProperties().get(position)); + } + + @Override + public int getItemCount() { + return mSelectedModule == null ? 0 : mSelectedModule.getProperties().size(); + } + } + + +} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/floating/EditorFloaty.java b/app/src/main/java/com/stardust/scriptdroid/ui/floating/EditorFloaty.java deleted file mode 100644 index 8a651b93..00000000 --- a/app/src/main/java/com/stardust/scriptdroid/ui/floating/EditorFloaty.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.stardust.scriptdroid.ui.floating; - -import android.content.Context; -import android.content.Intent; -import android.support.annotation.Nullable; -import android.view.ContextThemeWrapper; -import android.view.View; - -import com.stardust.enhancedfloaty.FloatyService; -import com.stardust.enhancedfloaty.ResizableFloaty; -import com.stardust.enhancedfloaty.ResizableFloatyWindow; -import com.stardust.scriptdroid.R; -import com.stardust.scriptdroid.model.script.ScriptFile; -import com.stardust.scriptdroid.ui.edit.EditActivity_; -import com.stardust.scriptdroid.ui.edit.EditorView; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; - -import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_NAME; -import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_PATH; - -/** - * Created by Stardust on 2017/9/29. - */ - -public class EditorFloaty implements ResizableFloaty { - - private Intent mIntent; - - @BindView(R.id.resizer) - View mResizeIcon; - @BindView(R.id.move_cursor) - View mMoveIcon; - - private ResizableFloatyWindow mWindow; - - public EditorFloaty(Intent intent) { - mIntent = intent; - } - - public static void floatingEdit(Context context, Intent intent) { - FloatyWindowManger.addWindow(context, new ResizableFloatyWindow(new EditorFloaty(intent))); - } - - public static void floatingEdit(Context context, String path) { - floatingEdit(context, null, path); - } - - public static void floatingEdit(Context context, String name, String path) { - floatingEdit(context, new Intent(context, EditActivity_.class) - .putExtra(EXTRA_PATH, path) - .putExtra(EXTRA_NAME, name)); - } - - public static void floatingEdit(Context context, ScriptFile file) { - floatingEdit(context, file.getSimplifiedName(), file.getPath()); - } - - @Override - public View inflateView(FloatyService floatyService, ResizableFloatyWindow resizableFloatyWindow) { - mWindow = resizableFloatyWindow; - View v = View.inflate(new ContextThemeWrapper(floatyService, R.style.AppTheme), R.layout.floating_editor, null); - setUpViews(v); - return v; - } - - private void setUpViews(View v) { - EditorView editorView = (EditorView) v.findViewById(R.id.editor_view); - editorView.handleIntent(mIntent); - ButterKnife.bind(this, v); - } - - @OnClick(R.id.move_or_resize) - void showOrHideMoveAndResizeIcon() { - if (mResizeIcon.getVisibility() == View.VISIBLE) { - mResizeIcon.setVisibility(View.GONE); - mMoveIcon.setVisibility(View.GONE); - } else { - mResizeIcon.setVisibility(View.VISIBLE); - mMoveIcon.setVisibility(View.VISIBLE); - } - } - - @OnClick(R.id.close) - void close() { - mWindow.close(); - } - - @Nullable - @Override - public View getResizerView(View view) { - return view.findViewById(R.id.resizer); - } - - @Nullable - @Override - public View getMoveCursorView(View view) { - return view.findViewById(R.id.move_cursor); - } - - -} diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java index a2d54f5b..ea8e75b8 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/scripts/ScriptListView.java @@ -24,7 +24,6 @@ import com.stardust.scriptdroid.model.script.Scripts; import com.stardust.scriptdroid.storage.file.StorageFileProvider; import com.stardust.scriptdroid.ui.common.ScriptLoopDialog; import com.stardust.scriptdroid.ui.common.ScriptOperations; -import com.stardust.scriptdroid.ui.floating.EditorFloaty; import com.stardust.scriptdroid.ui.viewmodel.ScriptList; import com.stardust.scriptdroid.ui.widget.BindableViewHolder; @@ -229,10 +228,6 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa .show(); notifyOperated(); break; - case R.id.floating_edit: - EditorFloaty.floatingEdit(getContext(), mSelectedScriptFile); - notifyOperated(); - break; case R.id.create_shortcut: new ScriptOperations(getContext(), this) .createShortcut(mSelectedScriptFile); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/widget/GridDividerDecoration.java b/app/src/main/java/com/stardust/scriptdroid/ui/widget/GridDividerDecoration.java new file mode 100644 index 00000000..455996ea --- /dev/null +++ b/app/src/main/java/com/stardust/scriptdroid/ui/widget/GridDividerDecoration.java @@ -0,0 +1,88 @@ +package com.stardust.scriptdroid.ui.widget; + +/** + * Created by Stardust on 2017/12/9. + */ + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.RecyclerView; +import android.util.TypedValue; +import android.view.View; + + +/** + * ItemDecoration implementation that applies and inset margin + * around each child of the RecyclerView. It also draws item dividers + * that are expected from a vertical list implementation, such as + * ListView. + */ +public class GridDividerDecoration extends RecyclerView.ItemDecoration { + + + private Drawable mDivider; + private int mInsets; + + public GridDividerDecoration(Context context, Drawable divider) { + mDivider = divider; + mInsets = divider.getIntrinsicWidth(); + } + + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + drawVertical(c, parent); + drawHorizontal(c, parent); + } + + /** + * Draw dividers at each expected grid interval + */ + public void drawVertical(Canvas c, RecyclerView parent) { + if (parent.getChildCount() == 0) return; + + final int childCount = parent.getChildCount(); + + for (int i = 0; i < childCount; i++) { + final View child = parent.getChildAt(i); + final RecyclerView.LayoutParams params = + (RecyclerView.LayoutParams) child.getLayoutParams(); + + final int left = child.getLeft() - params.leftMargin - mInsets; + final int right = child.getRight() + params.rightMargin + mInsets; + final int top = child.getBottom() + params.bottomMargin + mInsets; + final int bottom = top + mDivider.getIntrinsicHeight(); + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + /** + * Draw dividers to the right of each child view + */ + public void drawHorizontal(Canvas c, RecyclerView parent) { + final int childCount = parent.getChildCount(); + + for (int i = 0; i < childCount; i++) { + final View child = parent.getChildAt(i); + final RecyclerView.LayoutParams params = + (RecyclerView.LayoutParams) child.getLayoutParams(); + + final int left = child.getRight() + params.rightMargin + mInsets; + final int right = left + mDivider.getIntrinsicWidth(); + final int top = child.getTop() - params.topMargin - mInsets; + final int bottom = child.getBottom() + params.bottomMargin + mInsets; + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + //We can supply forced insets for each item view here in the Rect + outRect.set(mInsets, mInsets, mInsets, mInsets); + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_item_module.xml b/app/src/main/res/drawable/bg_item_module.xml new file mode 100644 index 00000000..66363e49 --- /dev/null +++ b/app/src/main/res/drawable/bg_item_module.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_item_property.xml b/app/src/main/res/drawable/bg_item_property.xml new file mode 100644 index 00000000..e57ca1f9 --- /dev/null +++ b/app/src/main/res/drawable/bg_item_property.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/divider_functions_view.xml b/app/src/main/res/drawable/divider_functions_view.xml new file mode 100644 index 00000000..067a88ff --- /dev/null +++ b/app/src/main/res/drawable/divider_functions_view.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/editor_view.xml b/app/src/main/res/layout/editor_view.xml index b4be7918..c81c7570 100644 --- a/app/src/main/res/layout/editor_view.xml +++ b/app/src/main/res/layout/editor_view.xml @@ -139,7 +139,7 @@ android:layout_alignParentBottom="true"/> + android:layout_toRightOf="@+id/properties"/> + + + - - \ No newline at end of file diff --git a/app/src/main/res/layout/functions_keyboard_view.xml b/app/src/main/res/layout/functions_keyboard_view.xml new file mode 100644 index 00000000..9a26c099 --- /dev/null +++ b/app/src/main/res/layout/functions_keyboard_view.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_module.xml b/app/src/main/res/layout/item_module.xml new file mode 100644 index 00000000..c9a3af42 --- /dev/null +++ b/app/src/main/res/layout/item_module.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_property.xml b/app/src/main/res/layout/item_property.xml new file mode 100644 index 00000000..4468021d --- /dev/null +++ b/app/src/main/res/layout/item_property.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 7349fbb0..a872500f 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -9,4 +9,5 @@ #99CC99 #9DA0A2 #282C2F + #f0f0f0 diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 4978a214..1f870f47 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -7,4 +7,6 @@ 0dp 0dp 16dp + 8dp + 14sp