From b42e440fffbfee4ee036a77303992bc8a67e12e1 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Thu, 11 Oct 2018 16:15:40 +0800 Subject: [PATCH] save works --- autojs/src/main/assets/modules/__ui__.js | 1 + .../autojs/core/http/MutableOkHttp.java | 4 + .../com/stardust/autojs/core/ui/JsEvent.java | 51 +++- .../inflater/inflaters/BaseViewInflater.java | 6 +- .../autojs/core/ui/widget/NativeView.java | 233 +++++++++++++++++- .../autojs/engine/RhinoJavaScriptEngine.java | 11 +- 6 files changed, 287 insertions(+), 19 deletions(-) diff --git a/autojs/src/main/assets/modules/__ui__.js b/autojs/src/main/assets/modules/__ui__.js index e96a4b96..1235ee8c 100644 --- a/autojs/src/main/assets/modules/__ui__.js +++ b/autojs/src/main/assets/modules/__ui__.js @@ -196,6 +196,7 @@ module.exports = function (runtime, global) { } function decorate(view) { + return view; var javaObject = view; var view = global.events.__asEmitter__(Object.create(view)); view.__javaObject__ = javaObject; diff --git a/autojs/src/main/java/com/stardust/autojs/core/http/MutableOkHttp.java b/autojs/src/main/java/com/stardust/autojs/core/http/MutableOkHttp.java index 1ff74f45..d57f86d4 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/http/MutableOkHttp.java +++ b/autojs/src/main/java/com/stardust/autojs/core/http/MutableOkHttp.java @@ -71,6 +71,10 @@ public class MutableOkHttp extends OkHttpClient { muteClient(); } + public synchronized void muteClient(Builder builder) { + mOkHttpClient = newClient(builder); + } + protected synchronized void muteClient() { mOkHttpClient = newClient(mOkHttpClient.newBuilder()); } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/JsEvent.java b/autojs/src/main/java/com/stardust/autojs/core/ui/JsEvent.java index d656cad0..a6d848b2 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/JsEvent.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/JsEvent.java @@ -1,4 +1,53 @@ package com.stardust.autojs.core.ui; -public class JsEvent { +import com.stardust.autojs.rhino.NativeJavaObjectWithPrototype; + +import org.mozilla.javascript.NativeJavaObject; +import org.mozilla.javascript.ScriptRuntime; +import org.mozilla.javascript.Scriptable; + +public class JsEvent extends NativeJavaObjectWithPrototype { + + private boolean mConsumed = false; + + public JsEvent(Scriptable scope, Object javaObject, Class staticType) { + super(scope, javaObject, staticType); + } + + public JsEvent(Scriptable scope, Object javaObject, Class staticType, boolean isAdapter) { + super(scope, javaObject, staticType, isAdapter); + } + + + + public JsEvent(Scriptable scope, Object javaObject) { + super(scope, javaObject, javaObject.getClass()); + } + + + @Override + public boolean has(String name, Scriptable start) { + return super.has(name, start) || "consumed".equals(name); + } + + @Override + public Object get(String name, Scriptable start) { + if ("consumed".equals(name)) { + return mConsumed; + } + return super.get(name, start); + } + + @Override + public void put(String name, Scriptable start, Object value) { + if ("consumed".equals(name)) { + mConsumed = ScriptRuntime.toBoolean(value); + return; + } + super.put(name, start, value); + } + + public boolean isConsumed() { + return mConsumed; + } } diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java index e212f488..8a4a8b88 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/inflater/inflaters/BaseViewInflater.java @@ -149,16 +149,16 @@ public class BaseViewInflater implements ViewInflater { } break; case "layout_gravity": - if (parent != null && parent instanceof LinearLayout) { + if (parent instanceof LinearLayout) { ((LinearLayout.LayoutParams) layoutParams).gravity = Gravities.parse(value); - } else if (parent != null && parent instanceof FrameLayout) { + } else if (parent instanceof FrameLayout) { ((FrameLayout.LayoutParams) layoutParams).gravity = Gravities.parse(value); } else { return setLayoutGravity(parent, view, Gravities.parse(value)); } break; case "layout_weight": - if (parent != null && parent instanceof LinearLayout) { + if (parent instanceof LinearLayout) { ((LinearLayout.LayoutParams) layoutParams).weight = Float.parseFloat(value); } break; diff --git a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/NativeView.java b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/NativeView.java index c35e2094..317849c4 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/ui/widget/NativeView.java +++ b/autojs/src/main/java/com/stardust/autojs/core/ui/widget/NativeView.java @@ -1,16 +1,32 @@ package com.stardust.autojs.core.ui.widget; +import android.annotation.SuppressLint; import android.graphics.drawable.Drawable; +import android.os.Build; import android.support.annotation.CallSuper; +import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import com.stardust.autojs.core.eventloop.EventEmitter; +import com.stardust.autojs.core.ui.JsEvent; +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.rhino.NativeJavaObjectWithPrototype; +import org.mozilla.javascript.NativeJavaObject; import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.Undefined; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; @@ -77,47 +93,95 @@ 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 Map mAttributes = new HashMap<>(); private final com.stardust.autojs.runtime.ScriptRuntime mRuntime; private final Drawables mDrawables; 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); mRuntime = runtime; mDrawables = mRuntime.ui.getResourceParser().getDrawables(); + mEventEmitter = runtime.events.emitter(); mView = javaObject; + mNativeEventEmitter = new NativeJavaObject(scope, mEventEmitter, mEventEmitter.getClass()); init(); } - public NativeView(Scriptable scope, View javaObject, Class staticType, boolean isAdapter, com.stardust.autojs.runtime.ScriptRuntime runtime) { - super(scope, javaObject, staticType, isAdapter); - mRuntime = runtime; - mDrawables = mRuntime.ui.getResourceParser().getDrawables(); - mView = javaObject; - init(); - } - + @SuppressLint("ClickableViewAccessibility") private void init() { onRegisterAttrs(); + 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) + ); + } } @CallSuper protected void onRegisterAttrs() { registerAttr("id", Ids::parse, mView::setId); - registerDrawableAttr("bg", mView::setBackground); - - + registerAttr("gravity", Gravities::parse, this::setGravity); + registerAttrs(new String[]{"width", "layout_width", "w"}, this::parseDimension, this::setWidth); + registerAttrs(new String[]{"height", "layout_height", "h"}, this::parseDimension, this::setHeight); + registerDrawableAttrs(new String[]{"bg", "background"}, mView::setBackground); + registerAttr("layout_gravity", Gravities::parse, this::setLayoutGravity); + registerAttr("layout_weight", Float::parseFloat, this::setLayoutWeight); } + + private int parseDimension(String dim) { + switch (dim) { + case "wrap_content": + return ViewGroup.LayoutParams.WRAP_CONTENT; + case "fill_parent": + case "match_parent": + return ViewGroup.LayoutParams.MATCH_PARENT; + default: + return Dimensions.parseToPixel(dim, mView.getResources().getDisplayMetrics(), (ViewGroup) mView.getParent(), true); + } + } + + @Override public boolean has(String name, Scriptable start) { if (mAttributes.containsKey(name)) { return true; } - return super.has(name, start); + return super.has(name, start) || mNativeEventEmitter.has(name, start); } @Override @@ -127,7 +191,11 @@ public class NativeView extends NativeJavaObjectWithPrototype { attribute.set(ScriptRuntime.toString(value)); return; } - super.put(name, start, value); + if (mNativeEventEmitter.has(name, start)) { + mNativeEventEmitter.put(name, start, value); + } else { + super.put(name, start, value); + } } @Override @@ -136,6 +204,10 @@ public class NativeView extends NativeJavaObjectWithPrototype { if (attribute != null) { return attribute.get(); } + Object o = mNativeEventEmitter.get(name, start); + if(o != Scriptable.NOT_FOUND){ + return o; + } return super.get(name, start); } @@ -165,18 +237,153 @@ public class NativeView extends NativeJavaObjectWithPrototype { mAttributes.put(name, new BaseAttribute(new MappingAttributeSetter<>(converter, applier))); } + protected void registerAttrs(String[] names, ValueConverter converter, ValueApplier applier) { + registerAttrs(names, new MappingAttributeSetter<>(converter, applier)); + } + + protected void registerAttrs(String[] names, AttributeSetter setter) { + registerAttrs(names, new BaseAttribute(setter)); + } + + protected void registerAttrs(String[] names, Attribute attribute) { + for (String name : names) { + mAttributes.put(name, attribute); + } + } + protected void registerDrawableAttr(String name, ValueApplier applier) { mAttributes.put(name, new BaseAttribute(new MappingAttributeSetter<>( this::parseDrawable, applier))); } + private void registerDrawableAttrs(String[] names, ValueApplier applier) { + registerAttrs(names, new BaseAttribute(new MappingAttributeSetter<>( + this::parseDrawable, applier))); + } + + protected Drawable parseDrawable(String value) { return mDrawables.parse(mView, value); } + private boolean setGravity(int g) { + try { + Method setGravity = mView.getClass().getMethod("setGravity", int.class); + setGravity.invoke(mView, g); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + private void setLayoutGravity(int gravity) { + ViewParent parent = mView.getParent(); + ViewGroup.LayoutParams layoutParams = mView.getLayoutParams(); + if (parent instanceof LinearLayout) { + ((LinearLayout.LayoutParams) layoutParams).gravity = gravity; + mView.setLayoutParams(layoutParams); + } else if (parent instanceof FrameLayout) { + ((FrameLayout.LayoutParams) layoutParams).gravity = gravity; + mView.setLayoutParams(layoutParams); + } else { + try { + Field field = layoutParams.getClass().getField("gravity"); + field.set(layoutParams, gravity); + mView.setLayoutParams(layoutParams); + } catch (Exception e) { + e.printStackTrace(); + //TODO throw or ? + } + } + } + + private void setLayoutWeight(float weight) { + ViewParent parent = mView.getParent(); + ViewGroup.LayoutParams layoutParams = mView.getLayoutParams(); + if (parent instanceof LinearLayout) { + ((LinearLayout.LayoutParams) layoutParams).weight = weight; + mView.setLayoutParams(layoutParams); + } + } + + + private void setWidth(int width) { + ViewGroup.LayoutParams layoutParams = mView.getLayoutParams(); + layoutParams.width = width; + mView.setLayoutParams(layoutParams); + } + + + private void setHeight(int height) { + ViewGroup.LayoutParams layoutParams = mView.getLayoutParams(); + layoutParams.height = height; + mView.setLayoutParams(layoutParams); + } + @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(); + } } diff --git a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java index 1457471d..98ebc1f5 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/RhinoJavaScriptEngine.java @@ -2,9 +2,11 @@ package com.stardust.autojs.engine; import android.os.Looper; import android.util.Log; +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.rhino.AndroidContextFactory; import com.stardust.autojs.rhino.NativeJavaClassWithPrototype; import com.stardust.autojs.rhino.NativeJavaObjectWithPrototype; @@ -182,7 +184,6 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { private class WrapFactory extends org.mozilla.javascript.WrapFactory { - @Override public Object wrap(Context cx, Scriptable scope, Object obj, Class staticType) { if (obj instanceof String) { @@ -194,6 +195,13 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { return super.wrap(cx, scope, obj, staticType); } + @Override + public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class staticType) { + if (javaObject instanceof View) { + return new NativeView(scope, (View) javaObject, staticType, getRuntime()); + } + return super.wrapAsJavaObject(cx, scope, javaObject, staticType); + } } private static class InterruptibleAndroidContextFactory extends AndroidContextFactory { @@ -206,7 +214,6 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine { @Override protected void observeInstructionCount(Context cx, int instructionCount) { if (Thread.currentThread().isInterrupted() && Looper.myLooper() != Looper.getMainLooper()) { - Log.d("DDDDD", "thread interrupt: " + Thread.currentThread()); throw new ScriptInterruptedException(); } }