Files
AutoJs6/autojs/src/main/assets/modules/__ui__.js
2018-11-10 16:41:53 +08:00

371 lines
13 KiB
JavaScript

module.exports = function (runtime, global) {
require("object-observe-lite.min")();
require("array-observe.min")();
var J = util.java;
var ui = {};
ui.__widgets__ = {};
ui.__defineGetter__("emitter", ()=> activity ? activity.getEventEmitter() : null);
ui.layout = function (xml) {
if(!activity){
throw new Error("需要在ui模式下运行才能使用该函数");
}
runtime.ui.layoutInflater.setContext(activity);
var view = runtime.ui.layoutInflater.inflate(xml, activity.window.decorView, false);
ui.setContentView(view);
}
ui.layoutFile = function(file) {
ui.layout(files.read(file));
}
ui.inflate = function(xml, parent, attachToParent){
if(!activity){
throw new Error("需要在ui模式下运行才能使用该函数");
}
if(typeof(xml) == 'xml'){
xml = xml.toXMLString();
}
parent = parent || null;
attachToParent = !!attachToParent;
runtime.ui.layoutInflater.setContext(activity);
return runtime.ui.layoutInflater.inflate(xml.toString(), parent, attachToParent);
}
ui.__inflate__ = function(ctx, xml, parent, attachToParent){
if(typeof(xml) == 'xml'){
xml = xml.toXMLString();
}
parent = parent || null;
attachToParent = !!attachToParent;
return runtime.ui.layoutInflater.inflate(ctx, xml.toString(), parent, attachToParent);
}
ui.registerWidget = function(name, widget){
if(typeof(widget) !== 'function'){
throw new TypeError('widget should be a class-like function');
}
ui.__widgets__[name] = widget;
}
ui.setContentView = function (view) {
ui.view = view;
ui.run(function () {
activity.setContentView(view);
});
}
ui.findById = function (id) {
if (!ui.view)
return null;
return ui.findByStringId(ui.view, id);
}
ui.findView = function(id) {
return ui.findById(id);
}
ui.isUiThread = function () {
let Looper = android.os.Looper;
return Looper.myLooper() == Looper.getMainLooper();
}
ui.run = function (action) {
if (ui.isUiThread()) {
return action();
}
var err = null;
var result;
var disposable = global.threads.disposable();
runtime.uiHandler.post(function () {
try {
result = action();
disposable.setAndNotify(true);
} catch (e) {
err = e;
disposable.setAndNotify(true);
}
});
disposable.blockedGet();
if (err) {
throw err;
}
return result;
}
ui.post = function (action, delay) {
if(delay == undefined){
runtime.getUiHandler().post(wrapUiAction(action));
}else{
runtime.getUiHandler().postDelayed(wrapUiAction(action), delay);
}
}
ui.statusBarColor = function (color) {
if (typeof (color) == 'string') {
color = android.graphics.Color.parseColor(color);
}
if (android.os.Build.VERSION.SDK_INT >= 21) {
ui.run(function () {
activity.getWindow().setStatusBarColor(color);
});
}
}
ui.finish = function () {
ui.run(function () {
activity.finish();
});
}
ui.findByStringId = function (view, id) {
return com.stardust.autojs.core.ui.JsViewHelper.findViewByStringId(view, id);
}
runtime.ui.bindingContext = global;
var layoutInflater = runtime.ui.layoutInflater;
layoutInflater.setLayoutInflaterDelegate({
beforeConvertXml: function (context, xml) {
return null;
},
afterConvertXml: function (context, xml) {
return xml;
},
afterInflation: function (context, result, xml, parent) {
return result;
},
beforeInflation: function (context, xml, parent) {
return null;
},
beforeInflateView: function (context, node, parent, attachToParent) {
return null;
},
afterInflateView: function (context, view, node, parent, attachToParent) {
let widget = view.widget;
if(widget && context.get("root") != widget){
widget.notifyAfterInflation(view);
}
return view;
},
beforeCreateView: function (context, node, viewName, parent, attrs) {
if(ui.__widgets__.hasOwnProperty(viewName)){
let Widget = ui.__widgets__[viewName];
let widget = new Widget();
let ctx = layoutInflater.newInflateContext();
ctx.put("root", widget);
ctx.put("widget", widget);
let view = ui.__inflate__(ctx, widget.renderInternal(), parent, false);
return view;
};
return null;
},
afterCreateView: function (context, view, node, viewName, parent, attrs) {
if (view.getClass().getName() == "com.stardust.autojs.core.ui.widget.JsListView" ||
view.getClass().getName() == "com.stardust.autojs.core.ui.widget.JsGridView") {
initListView(view);
}
var widget = context.get("widget");
if(widget != null){
widget.view = view;
view.widget = widget;
let viewAttrs = com.stardust.autojs.core.ui.ViewExtras.getViewAttributes(view, layoutInflater.resourceParser);
viewAttrs.setViewAttributeDelegate({
has: function(name) {
return widget.hasAttr(name);
},
get: function(view, name, getter){
return widget.getAttr(view, name, getter);
},
set: function(view, name, value, setter) {
widget.setAttr(view, name, value, setter);
}
});
widget.notifyViewCreated(view);
}
return view;
},
beforeApplyAttributes: function (context, view, inflater, attrs, parent) {
return false;
},
afterApplyAttributes: function (context, view, inflater, attrs, parent) {
context.remove("widget");
},
beforeInflateChildren: function (context, inflater, node, parent) {
return false;
},
afterInflateChildren: function (context, inflater, node, parent) {
},
afterApplyPendingAttributesOfChildren: function (context, inflater, view) {
},
beforeApplyPendingAttributesOfChildren: function (context, inflater, view) {
return false;
},
beforeApplyAttribute: function (context, inflater, view, ns, attrName, value, parent, attrs) {
var isDynamic = layoutInflater.isDynamicValue(value);
if ((isDynamic && layoutInflater.getInflateFlags() == layoutInflater.FLAG_IGNORES_DYNAMIC_ATTRS)
|| (!isDynamic && layoutInflater.getInflateFlags() == layoutInflater.FLAG_JUST_DYNAMIC_ATTRS)) {
return true;
}
value = bind(value);
let widget = context.get("widget");
if(widget != null && widget.hasAttr(attrName)){
widget.setAttr(view, attrName, value, (view, attrName, value)=>{
inflater.setAttr(view, ns, attrName, value, parent, attrs);
});
} else {
inflater.setAttr(view, ns, attrName, value, parent, attrs);
}
this.afterApplyAttribute(context, inflater, view, ns, attrName, value, parent, attrs);
return true;
},
afterApplyAttribute: function (context, inflater, view, ns, attrName, value, parent, attrs) {
}
});
function bind(value) {
var ctx = runtime.ui.bindingContext;
if (ctx == null)
return;
var i = -1;
while ((i = value.indexOf("{{", i + 1)) >= 0) {
var j = value.indexOf("}}", i + 1);
if (j < 0)
return value;
value = value.substring(0, i) + evalInContext(value.substring(i + 2, j), ctx) + value.substring(j + 2);
i = j + 1;
}
return value;
}
function evalInContext(expr, ctx) {
return global.__exitIfError__(function() {
with(ctx) {
return (function(){
return eval(expr);
}).call(ctx);
}
});
}
function initListView(list) {
list.setDataSourceAdapter({
getItemCount: function (data) {
return data.length;
},
getItem: function (data, i) {
return data[i];
},
setDataSource: function (data) {
var adapter = list.getAdapter();
Array.observe(data, function (changes) {
changes.forEach(change => {
if (change.type == 'splice') {
if (change.removed && change.removed.length > 0) {
adapter.notifyItemRangeRemoved(change.index, change.removed.length);
}
if (change.addedCount > 0) {
adapter.notifyItemRangeInserted(change.index, change.addedCount);
}
} else if (change.type == 'update') {
try{
adapter.notifyItemChanged(parseInt(change.name));
}catch(e){}
}
});
});
}
});
}
function wrapUiAction(action, defReturnValue) {
if (typeof (activity) != 'undefined') {
return function () { return action(); };
}
return function () {
return __exitIfError__(action, defReturnValue);
}
}
ui.Widget = (function(){
function Widget(){
this.__attrs__ = {};
}
Widget.prototype.renderInternal = function(){
if(typeof(this.render) === 'function'){
return this.render();
}
return (< />)
};
Widget.prototype.defineAttr = function(attrName, getter, setter){
var attrAlias = attrName;
var applier = null;
if(typeof(arguments[1]) == 'string'){
attrAlias = arguments[1];
if(arguments.length >= 3){
applier = arguments[2];
}
} else if(typeof(arguments[1]) == 'function' && typeof(arguments[2]) != 'function'){
applier = arguments[1];
}
if(!(typeof(arguments[1]) == 'function' && typeof(arguments[2]) == 'function')){
getter = ()=> {
return this[attrAlias];
};
setter = (view, attrName, value, setter)=> {
this[attrAlias] = value;
applier && applier(view, attrName, value, setter);
};
}
this.__attrs__[attrName] = {
getter: getter,
setter: setter
};
};
Widget.prototype.hasAttr = function(attrName){
return this.__attrs__.hasOwnProperty(attrName);
};
Widget.prototype.setAttr = function(view, attrName, value, setter){
this.__attrs__[attrName].setter(view, attrName, value, setter);
};
Widget.prototype.getAttr = function(view, attrName, getter){
return this.__attrs__[attrName].getter(view, attrName, getter);
};
Widget.prototype.notifyViewCreated = function(view){
if(typeof(this.onViewCreated) == 'function'){
this.onViewCreated(view);
}
};
Widget.prototype.notifyAfterInflation = function(view){
if(typeof(this.onFinishInflation) == 'function'){
this.onFinishInflation(view);
}
}
return Widget;
})();
var proxy = runtime.ui;
proxy.__proxy__ = {
set: function (name, value) {
ui[name] = value;
},
get: function (name) {
if (!ui[name] && ui.view) {
let v = ui.findById(name);
if (v) {
return v;
}
}
return ui[name];
}
};
return proxy;
}