save works

This commit is contained in:
hyb1996 2018-10-12 16:25:24 +08:00
parent 9b1daa6567
commit 7fe204c44f
11 changed files with 306 additions and 372 deletions

View File

@ -71,14 +71,9 @@ runtime.init();
Canvas = com.stardust.autojs.core.graphics.ScriptCanvas;
Image = com.stardust.autojs.core.image.ImageWrapper;
//重定向require以便支持相对路径
(function(){
var loadAssets = function(path){
eval(files.readAssets(path));
}
loadAssets("jvm-npm.js");
})();
//重定向require以便支持相对路径和npm模块
Module = require("jvm-npm.js");
require = Module.require;
})();

View File

@ -4,10 +4,7 @@ module.exports = function (runtime, global) {
require("array-observe.min")();
var J = util.java;
var ui = {};
ui.__view_cache__ = {};
ui.__defineGetter__("emitter", ()=> activity ? activity.getEventEmitter() : null);
@ -34,7 +31,6 @@ module.exports = function (runtime, global) {
ui.setContentView = function (view) {
ui.view = view;
ui.__view_cache__ = {};
ui.run(function () {
activity.setContentView(view);
});
@ -43,15 +39,11 @@ module.exports = function (runtime, global) {
ui.findById = function (id) {
if (!ui.view)
return null;
var v = ui.findByStringId(ui.view, id);
if (v) {
v = decorate(v);
}
return v;
return ui.findByStringId(ui.view, id);
}
ui.isUiThread = function () {
importClass(android.os.Looper);
let Looper = android.os.Looper;
return Looper.myLooper() == Looper.getMainLooper();
}
@ -192,111 +184,8 @@ module.exports = function (runtime, global) {
}).call(ctx);
}
});
}
function decorate(view) {
return view;
var javaObject = view;
var view = global.events.__asEmitter__(Object.create(view));
view.__javaObject__ = javaObject;
if (view.getClass().getName() == "com.stardust.autojs.core.ui.widget.JsListView"
|| view.getClass().getName() == "com.stardust.autojs.core.ui.widget.JsGridView") {
view = decorateList(view);
}
var gestureDetector = new android.view.GestureDetector(context, {
onDown: function (e) {
e = wrapMotionEvent(e);
emit("touch_down", e, view);
return e.consumed;
},
onShowPress: function (e) {
e = wrapMotionEvent(e);
emit("show_press", e, view);
},
onSingleTapUp: function (e) {
e = wrapMotionEvent(e);
emit("single_tap", e, view);
return e.consumed;
},
onScroll: function (e1, e2, distanceX, distanceY) {
e1 = wrapMotionEvent(e1);
e2 = wrapMotionEvent(e2);
emit("scroll", e1, e2, distanceX, distanceY, view);
return e1.consumed || e2.consumed;
},
onLongPress: function (e) {
e = wrapMotionEvent(e);
emit("long_press", e, view);
},
onFling: function (e1, e2, velocityX, velocityY) {
e1 = wrapMotionEvent(e1);
e2 = wrapMotionEvent(e2);
emit("fling", e1, e2, velocityX, velocityY, view);
return e1.consumed || e2.consumed;
}
});
view.setOnTouchListener(function (v, event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
event = wrapMotionEvent(event);
event.consumed = false;
emit("touch", event, view);
return event.consumed;
});
if(!J.instanceOf(view, "android.widget.AdapterView")){
view.setOnLongClickListener(function (v) {
var event = {};
event.consumed = false;
emit("long_click", event, view);
return event.consumed;
});
view.setOnClickListener(function (v) {
emit("click", view);
});
}
view.setOnKeyListener(function (v, keyCode, event) {
event = wrapMotionEvent(event);
emit("key", keyCode, event, v);
return event.consumed;
});
if (typeof (view.setOnCheckedChangeListener) == 'function') {
view.setOnCheckedChangeListener(function (v, isChecked) {
emit("check", isChecked == true ? true : false, view);
});
}
view._id = function (id) {
return ui.findByStringId(view, id);
}
view.click = function (listener) {
if (listener) {
view.setOnClickListener(new android.view.View.OnClickListener(wrapUiAction(listener)));
} else {
view.performClick();
}
}
view.longClick = function (listener) {
if (listener) {
view.setOnLongClickListener(wrapUiAction(listener, false));
} else {
view.performLongClick();
}
}
function emit() {
var args = arguments;
global.__exitIfError__(function () {
//不支持使用apply的原因是rhino会把参数中的primitive变成object
functionApply(view, view.emit, args);
//view.emit.apply(view, args);
});
}
return view;
}
function initListView(list) {
list.setDataSourceAdapter({
getItemCount: function (data) {
@ -327,31 +216,6 @@ module.exports = function (runtime, global) {
});
}
function decorateList(list) {
list.setOnItemTouchListener({
onItemClick: function(listView, itemView, item, pos){
emit("item_click", item, pos, itemView, listView);
},
onItemLongClick: function(listView, itemView, item, pos){
var event = {};
event.consumed = false;
emit("item_long_click", event, item, pos, itemView, listView);
return event.consumed;
}
});
function emit() {
var args = arguments;
global.__exitIfError__(function () {
//不支持使用apply的原因是rhino会把参数中的primitive变成object
functionApply(list, list.emit, args);
//view.emit.apply(view, args);
});
}
return list;
}
ui.__decorate__ = decorate;
function wrapUiAction(action, defReturnValue) {
if (typeof (activity) != 'undefined') {
return function () { return action(); };
@ -361,30 +225,6 @@ module.exports = function (runtime, global) {
}
}
function wrapMotionEvent(e) {
e = Object.create(e);
e.consumed = false;
return e;
}
function functionApply(obj, func, args) {
if (args.length == 0)
return func.call(obj);
if (args.length == 1)
return func.call(obj, args[0]);
if (args.length == 2)
return func.call(obj, args[0], args[1]);
if (args.length == 3)
return func.call(obj, args[0], args[1], args[2]);
if (args.length == 4)
return func.call(obj, args[0], args[1], args[2], args[3]);
if (args.length == 5)
return func.call(obj, args[0], args[1], args[2], args[3], args[4]);
if (args.length == 6)
return func.call(obj, args[0], args[1], args[2], args[3], args[4], args[5]);
throw new Error("too many arguments: " + args.length);
}
var proxy = runtime.ui;
proxy.__proxy__ = {
set: function (name, value) {
@ -392,14 +232,9 @@ module.exports = function (runtime, global) {
},
get: function (name) {
if (!ui[name] && ui.view) {
var cache = ui.__view_cache__[name];
if (cache) {
return cache;
}
cache = ui.findById(name);
if (cache) {
ui.__view_cache__[name] = cache;
return cache;
let v = ui.findById(name);
if (v) {
return v;
}
}
return ui[name];

View File

@ -196,6 +196,7 @@ module = (typeof module === 'undefined') ? {} : module;
Require.extensions = {};
require = Require;
Module.require = require;
module.exports = Module;
function loadJSON (file) {

View File

@ -6,21 +6,21 @@ import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
public class JsEvent extends NativeJavaObjectWithPrototype {
public class BaseEvent extends NativeJavaObjectWithPrototype {
private boolean mConsumed = false;
public JsEvent(Scriptable scope, Object javaObject, Class<?> staticType) {
public BaseEvent(Scriptable scope, Object javaObject, Class<?> staticType) {
super(scope, javaObject, staticType);
}
public JsEvent(Scriptable scope, Object javaObject, Class<?> staticType, boolean isAdapter) {
public BaseEvent(Scriptable scope, Object javaObject, Class<?> staticType, boolean isAdapter) {
super(scope, javaObject, staticType, isAdapter);
}
public JsEvent(Scriptable scope, Object javaObject) {
public BaseEvent(Scriptable scope, Object javaObject) {
super(scope, javaObject, javaObject.getClass());
}

View File

@ -1,4 +1,4 @@
package com.stardust.autojs.core.ui.xview;
package com.stardust.autojs.core.ui.attribute;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
@ -15,7 +15,6 @@ import com.stardust.autojs.core.ui.inflater.util.Dimensions;
import com.stardust.autojs.core.ui.inflater.util.Drawables;
import com.stardust.autojs.core.ui.inflater.util.Gravities;
import com.stardust.autojs.core.ui.inflater.util.Ids;
import com.stardust.autojs.core.ui.widget.NativeView;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

View File

@ -0,0 +1,92 @@
package com.stardust.autojs.core.ui.nativeview;
import android.annotation.SuppressLint;
import android.os.Build;
import android.view.View;
import android.widget.CompoundButton;
import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.ui.BaseEvent;
import com.stardust.autojs.core.ui.attribute.ViewAttributes;
import com.stardust.autojs.core.ui.widget.JsListView;
import com.stardust.autojs.rhino.NativeJavaObjectWithPrototype;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import java.util.HashSet;
public class NativeView extends NativeJavaObjectWithPrototype {
private static final String LOG_TAG = "NativeView";
public static class ScrollEvent {
public int scrollX;
public int scrollY;
public int oldScrollX;
public int oldScrollY;
public ScrollEvent(int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
this.scrollX = scrollX;
this.scrollY = scrollY;
this.oldScrollX = oldScrollX;
this.oldScrollY = oldScrollY;
}
}
public static class LongClickEvent {
public final View view;
public LongClickEvent(View view) {
this.view = view;
}
}
private final ViewAttributes mViewAttributes;
private final View mView;
public NativeView(Scriptable scope, View javaObject, Class<?> staticType, com.stardust.autojs.runtime.ScriptRuntime runtime) {
super(scope, javaObject, staticType);
mViewAttributes = ViewAttributes.fromView(runtime.ui.getResourceParser(), javaObject);
mView = javaObject;
ViewPrototype viewPrototype = new ViewPrototype(mView, scope, runtime);
prototype = new NativeJavaObject(scope, viewPrototype, viewPrototype.getClass());
}
@Override
public boolean has(String name, Scriptable start) {
if (mViewAttributes.contains(name)) {
return true;
}
return super.has(name, start);
}
@Override
public void put(String name, Scriptable start, Object value) {
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
if (attribute != null) {
attribute.set(ScriptRuntime.toString(value));
return;
}
super.put(name, start, value);
}
@Override
public Object get(String name, Scriptable start) {
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
if (attribute != null) {
return attribute.get();
}
return super.get(name, start);
}
@Override
public View unwrap() {
return mView;
}
}

View File

@ -0,0 +1,190 @@
package com.stardust.autojs.core.ui.nativeview;
import android.annotation.SuppressLint;
import android.os.Build;
import android.view.View;
import android.widget.CompoundButton;
import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.ui.BaseEvent;
import com.stardust.autojs.core.ui.widget.JsListView;
import com.stardust.autojs.runtime.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import java.util.HashSet;
public class ViewPrototype {
private final EventEmitter mEventEmitter;
private final View mView;
private final HashSet<String> mRegisteredEvents = new HashSet<>();
private final Scriptable mScope;
public ViewPrototype(View view, Scriptable scope, ScriptRuntime runtime) {
mView = view;
mEventEmitter = runtime.events.emitter();
mScope = scope;
}
public void click() {
mView.performClick();
}
public void longClick() {
mView.performLongClick();
}
public void click(Object listener) {
on("click", listener);
}
public void longClick(Object listener) {
on("long_click", listener);
}
public EventEmitter once(String eventName, Object listener) {
registerEventIfNeeded(eventName);
return mEventEmitter.once(eventName, listener);
}
public EventEmitter on(String eventName, Object listener) {
registerEventIfNeeded(eventName);
return mEventEmitter.on(eventName, listener);
}
public EventEmitter addListener(String eventName, Object listener) {
registerEventIfNeeded(eventName);
return mEventEmitter.addListener(eventName, listener);
}
private void registerEventIfNeeded(String eventName) {
if (mRegisteredEvents.contains(eventName)) {
return;
}
if (registerEvent(eventName)) {
mRegisteredEvents.add(eventName);
}
}
@SuppressLint("ClickableViewAccessibility")
private boolean registerEvent(String eventName) {
switch (eventName) {
case "touch": {
mView.setOnTouchListener((v, event) -> {
BaseEvent e = new BaseEvent(mScope, event, event.getClass());
//Log.d(LOG_TAG, "this = " + NativeView.this + ", emitter = " + mEventEmitter + ", view = " + mView);
emit("touch", e, v);
return e.isConsumed();
});
}
return true;
case "click": {
mView.setOnClickListener(v -> emit("click", v));
}
return true;
case "long_click": {
mView.setOnLongClickListener(v -> {
BaseEvent e = new BaseEvent(mScope, new NativeView.LongClickEvent(v));
emit("long_click", e, v);
return e.isConsumed();
});
}
return true;
case "key": {
mView.setOnKeyListener((v, keyCode, event) -> {
BaseEvent e = new BaseEvent(mScope, event, event.getClass());
emit("key", e, keyCode, v);
return e.isConsumed();
});
}
return true;
case "scroll_change": {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
BaseEvent e = new BaseEvent(mScope, new NativeView.ScrollEvent(scrollX, scrollY, oldScrollX, oldScrollY));
emit("scroll_change", e, v);
});
return true;
}
}
break;
case "check": {
if (mView instanceof CompoundButton) {
((CompoundButton) mView).setOnCheckedChangeListener((buttonView, isChecked) ->
emit("check", isChecked, buttonView));
}
}
case "item_click":
case "item_long_click": {
if (mView instanceof JsListView) {
((JsListView) mView).setOnItemTouchListener(new JsListView.OnItemTouchListener() {
@Override
public void onItemClick(JsListView listView, View itemView, Object item, int pos) {
emit("item_click", item, pos, itemView, listView);
}
@Override
public boolean onItemLongClick(JsListView listView, View itemView, Object item, int pos) {
BaseEvent e = new BaseEvent(mScope, new NativeView.LongClickEvent(itemView));
emit("item_long_click", e, item, pos, itemView, listView);
return e.isConsumed();
}
});
return true;
}
}
break;
}
return false;
}
public boolean emit(String eventName, Object... args) {
return mEventEmitter.emit(eventName, args);
}
public String[] eventNames() {
return mEventEmitter.eventNames();
}
public int listenerCount(String eventName) {
return mEventEmitter.listenerCount(eventName);
}
public Object[] listeners(String eventName) {
return mEventEmitter.listeners(eventName);
}
public EventEmitter prependListener(String eventName, Object listener) {
return mEventEmitter.prependListener(eventName, listener);
}
public EventEmitter prependOnceListener(String eventName, Object listener) {
return mEventEmitter.prependOnceListener(eventName, listener);
}
public EventEmitter removeAllListeners() {
return mEventEmitter.removeAllListeners();
}
public EventEmitter removeAllListeners(String eventName) {
return mEventEmitter.removeAllListeners(eventName);
}
public EventEmitter removeListener(String eventName, Object listener) {
return mEventEmitter.removeListener(eventName, listener);
}
public EventEmitter setMaxListeners(int n) {
return mEventEmitter.setMaxListeners(n);
}
public int getMaxListeners() {
return mEventEmitter.getMaxListeners();
}
public static int defaultMaxListeners() {
return EventEmitter.defaultMaxListeners();
}
}

View File

@ -1,174 +0,0 @@
package com.stardust.autojs.core.ui.widget;
import android.annotation.SuppressLint;
import android.os.Build;
import android.view.View;
import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.ui.JsEvent;
import com.stardust.autojs.core.ui.xview.ViewAttributes;
import com.stardust.autojs.rhino.NativeJavaObjectWithPrototype;
import org.mozilla.javascript.NativeJavaMethod;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
public class NativeView extends NativeJavaObjectWithPrototype {
public static class ScrollEvent {
public int scrollX;
public int scrollY;
public int oldScrollX;
public int oldScrollY;
public ScrollEvent(int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
this.scrollX = scrollX;
this.scrollY = scrollY;
this.oldScrollX = oldScrollX;
this.oldScrollY = oldScrollY;
}
}
private final ViewAttributes mViewAttributes;
private final View mView;
private final EventEmitter mEventEmitter;
private final NativeJavaObject mNativeEventEmitter;
public NativeView(Scriptable scope, View javaObject, Class<?> staticType, com.stardust.autojs.runtime.ScriptRuntime runtime) {
super(scope, javaObject, staticType);
mViewAttributes = ViewAttributes.fromView(runtime.ui.getResourceParser(), javaObject);
mEventEmitter = runtime.events.emitter();
mView = javaObject;
mNativeEventEmitter = new NativeJavaObject(scope, mEventEmitter, mEventEmitter.getClass());
init();
}
@SuppressLint("ClickableViewAccessibility")
private void init() {
mView.setOnTouchListener((v, event) -> {
JsEvent e = new JsEvent(getParentScope(), event, event.getClass());
emit("touch", e, v);
return e.isConsumed();
});
mView.setOnClickListener(v -> emit("click", v));
mView.setOnLongClickListener(v -> {
emit("long_click", v);
return false;
});
mView.setOnKeyListener((v, keyCode, event) -> {
JsEvent e = new JsEvent(getParentScope(), event, event.getClass());
emit("key", e, keyCode, v);
return e.isConsumed();
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) ->
emit("scroll_change", new ScrollEvent(scrollX, scrollY, oldScrollX, oldScrollY), v)
);
}
}
@Override
public boolean has(String name, Scriptable start) {
if (mViewAttributes.contains(name)) {
return true;
}
return super.has(name, start) || mNativeEventEmitter.has(name, start);
}
@Override
public void put(String name, Scriptable start, Object value) {
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
if (attribute != null) {
attribute.set(ScriptRuntime.toString(value));
return;
}
if (mNativeEventEmitter.has(name, start)) {
mNativeEventEmitter.put(name, start, value);
} else {
super.put(name, start, value);
}
}
@Override
public Object get(String name, Scriptable start) {
ViewAttributes.Attribute attribute = mViewAttributes.get(name);
if (attribute != null) {
return attribute.get();
}
Object o = mNativeEventEmitter.get(name, start);
if (o != Scriptable.NOT_FOUND) {
return o;
}
return super.get(name, start);
}
@Override
public View unwrap() {
return mView;
}
public EventEmitter once(String eventName, Object listener) {
return mEventEmitter.once(eventName, listener);
}
public EventEmitter on(String eventName, Object listener) {
return mEventEmitter.on(eventName, listener);
}
public EventEmitter addListener(String eventName, Object listener) {
return mEventEmitter.addListener(eventName, listener);
}
public boolean emit(String eventName, Object... args) {
return mEventEmitter.emit(eventName, args);
}
public String[] eventNames() {
return mEventEmitter.eventNames();
}
public int listenerCount(String eventName) {
return mEventEmitter.listenerCount(eventName);
}
public Object[] listeners(String eventName) {
return mEventEmitter.listeners(eventName);
}
public EventEmitter prependListener(String eventName, Object listener) {
return mEventEmitter.prependListener(eventName, listener);
}
public EventEmitter prependOnceListener(String eventName, Object listener) {
return mEventEmitter.prependOnceListener(eventName, listener);
}
public EventEmitter removeAllListeners() {
return mEventEmitter.removeAllListeners();
}
public EventEmitter removeAllListeners(String eventName) {
return mEventEmitter.removeAllListeners(eventName);
}
public EventEmitter removeListener(String eventName, Object listener) {
return mEventEmitter.removeListener(eventName, listener);
}
public EventEmitter setMaxListeners(int n) {
return mEventEmitter.setMaxListeners(n);
}
public int getMaxListeners() {
return mEventEmitter.getMaxListeners();
}
public static int defaultMaxListeners() {
return EventEmitter.defaultMaxListeners();
}
}

View File

@ -6,10 +6,8 @@ import android.view.View;
import com.stardust.app.GlobalAppContext;
import com.stardust.autojs.BuildConfig;
import com.stardust.autojs.core.ui.widget.NativeView;
import com.stardust.autojs.core.ui.nativeview.NativeView;
import com.stardust.autojs.rhino.AndroidContextFactory;
import com.stardust.autojs.rhino.NativeJavaClassWithPrototype;
import com.stardust.autojs.rhino.NativeJavaObjectWithPrototype;
import com.stardust.autojs.rhino.RhinoAndroidHelper;
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
import com.stardust.autojs.script.JavaScriptSource;
@ -18,13 +16,9 @@ import com.stardust.automator.UiObjectCollection;
import com.stardust.pio.PFiles;
import com.stardust.pio.UncheckedIOException;
import org.mozilla.javascript.Callable;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.ImporterTopLevel;
import org.mozilla.javascript.NativeJavaClass;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.commonjs.module.RequireBuilder;
@ -33,12 +27,9 @@ import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptPr
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
@ -184,6 +175,8 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
private class WrapFactory extends org.mozilla.javascript.WrapFactory {
private final WeakHashMap<Object, Scriptable> mWrapCache = new WeakHashMap<>();
@Override
public Object wrap(Context cx, Scriptable scope, Object obj, Class<?> staticType) {
if (obj instanceof String) {
@ -198,7 +191,12 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
@Override
public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class<?> staticType) {
if (javaObject instanceof View) {
return new NativeView(scope, (View) javaObject, staticType, getRuntime());
Scriptable wrap = mWrapCache.get(javaObject);
if(wrap == null){
wrap = new NativeView(scope, (View) javaObject, staticType, getRuntime());
mWrapCache.put(javaObject, wrap);
}
return wrap;
}
return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
}

View File

@ -1,6 +1,5 @@
package com.stardust.autojs.rhino;
import org.mozilla.javascript.JavaMembers;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.Scriptable;
@ -26,7 +25,6 @@ public class BindingNativeJavaObject extends NativeJavaObject {
dynamicType = this.staticType;
}
this.members.
}
}