329 lines
9.1 KiB
JavaScript
329 lines
9.1 KiB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
};
|
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
};
|
|
import { obj2Model } from "../util/types";
|
|
import { uniqueId } from "../util/uniqueId";
|
|
import { loge } from "../util/log";
|
|
export function Property(target, propKey) {
|
|
Reflect.defineMetadata(propKey, true, target);
|
|
}
|
|
export class View {
|
|
constructor() {
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.viewId = uniqueId('ViewId');
|
|
this.callbacks = new Map;
|
|
/** Anchor end*/
|
|
this.__dirty_props__ = {};
|
|
this.nativeViewModel = {
|
|
id: this.viewId,
|
|
type: this.constructor.name,
|
|
props: this.__dirty_props__,
|
|
};
|
|
return new Proxy(this, {
|
|
get: (target, p, receiver) => {
|
|
return Reflect.get(target, p, receiver);
|
|
},
|
|
set: (target, p, v, receiver) => {
|
|
const oldV = Reflect.get(target, p, receiver);
|
|
const ret = Reflect.set(target, p, v, receiver);
|
|
if (Reflect.getMetadata(p, target) && oldV !== v) {
|
|
receiver.onPropertyChanged(p.toString(), oldV, v);
|
|
}
|
|
return ret;
|
|
}
|
|
});
|
|
}
|
|
callback2Id(f) {
|
|
const id = uniqueId('Function');
|
|
this.callbacks.set(id, f);
|
|
return id;
|
|
}
|
|
id2Callback(id) {
|
|
let f = this.callbacks.get(id);
|
|
if (f === undefined) {
|
|
f = Reflect.get(this, id);
|
|
}
|
|
return f;
|
|
}
|
|
/** Anchor start*/
|
|
get left() {
|
|
return this.x;
|
|
}
|
|
set left(v) {
|
|
this.x = v;
|
|
}
|
|
get right() {
|
|
return this.x + this.width;
|
|
}
|
|
set right(v) {
|
|
this.x = v - this.width;
|
|
}
|
|
get top() {
|
|
return this.y;
|
|
}
|
|
set top(v) {
|
|
this.y = v;
|
|
}
|
|
get bottom() {
|
|
return this.y + this.height;
|
|
}
|
|
set bottom(v) {
|
|
this.y = v - this.height;
|
|
}
|
|
get centerX() {
|
|
return this.x + this.width / 2;
|
|
}
|
|
get centerY() {
|
|
return this.y + this.height / 2;
|
|
}
|
|
set centerX(v) {
|
|
this.x = v - this.width / 2;
|
|
}
|
|
set centerY(v) {
|
|
this.y = v - this.height / 2;
|
|
}
|
|
get dirtyProps() {
|
|
return this.__dirty_props__;
|
|
}
|
|
onPropertyChanged(propKey, oldV, newV) {
|
|
if (newV instanceof Function) {
|
|
newV = this.callback2Id(newV);
|
|
}
|
|
else {
|
|
newV = obj2Model(newV);
|
|
}
|
|
this.__dirty_props__[propKey] = newV;
|
|
}
|
|
clean() {
|
|
for (const key in this.__dirty_props__) {
|
|
if (Reflect.has(this.__dirty_props__, key)) {
|
|
Reflect.deleteProperty(this.__dirty_props__, key);
|
|
}
|
|
}
|
|
}
|
|
isDirty() {
|
|
return Reflect.ownKeys(this.__dirty_props__).length !== 0;
|
|
}
|
|
responseCallback(id, ...args) {
|
|
const f = this.id2Callback(id);
|
|
if (f instanceof Function) {
|
|
const argumentsList = [];
|
|
for (let i = 1; i < arguments.length; i++) {
|
|
argumentsList.push(arguments[i]);
|
|
}
|
|
return Reflect.apply(f, this, argumentsList);
|
|
}
|
|
else {
|
|
loge(`Cannot find callback:${id} for ${JSON.stringify(this.toModel())}`);
|
|
}
|
|
}
|
|
toModel() {
|
|
return this.nativeViewModel;
|
|
}
|
|
let(block) {
|
|
block(this);
|
|
}
|
|
also(block) {
|
|
block(this);
|
|
return this;
|
|
}
|
|
apply(config) {
|
|
for (let key in config) {
|
|
Reflect.set(this, key, Reflect.get(config, key, config), this);
|
|
}
|
|
return this;
|
|
}
|
|
in(group) {
|
|
group.addChild(this);
|
|
return this;
|
|
}
|
|
nativeChannel(context, name) {
|
|
let thisView = this;
|
|
return function (args = undefined) {
|
|
const func = context.shader.command;
|
|
const viewIds = [];
|
|
while (thisView != undefined) {
|
|
viewIds.push(thisView.viewId);
|
|
thisView = thisView.superview;
|
|
}
|
|
const params = {
|
|
viewIds: viewIds.reverse(),
|
|
name,
|
|
args,
|
|
};
|
|
return Reflect.apply(func, undefined, [params]);
|
|
};
|
|
}
|
|
getWidth(context) {
|
|
return this.nativeChannel(context, 'getWidth')();
|
|
}
|
|
getHeight(context) {
|
|
return this.nativeChannel(context, 'getHeight')();
|
|
}
|
|
getLocationOnScreen(context) {
|
|
return this.nativeChannel(context, "getLocationOnScreen")();
|
|
}
|
|
/**----------transform----------*/
|
|
doAnimation(context, animation) {
|
|
return this.nativeChannel(context, "doAnimation")(animation.toModel()).then((args) => {
|
|
for (let key in args) {
|
|
Reflect.set(this, key, Reflect.get(args, key, args), this);
|
|
Reflect.deleteProperty(this.__dirty_props__, key);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "width", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "height", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "x", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "y", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Object)
|
|
], View.prototype, "backgroundColor", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Object)
|
|
], View.prototype, "corners", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Object)
|
|
], View.prototype, "border", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Object)
|
|
], View.prototype, "shadow", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "alpha", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Boolean)
|
|
], View.prototype, "hidden", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Object)
|
|
], View.prototype, "viewId", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Object)
|
|
], View.prototype, "padding", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Object)
|
|
], View.prototype, "layoutConfig", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Function)
|
|
], View.prototype, "onClick", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "translationX", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "translationY", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "scaleX", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "scaleY", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "pivotX", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "pivotY", void 0);
|
|
__decorate([
|
|
Property,
|
|
__metadata("design:type", Number)
|
|
], View.prototype, "rotation", void 0);
|
|
export class Superview extends View {
|
|
subviewById(id) {
|
|
for (let v of this.allSubviews()) {
|
|
if (v.viewId === id) {
|
|
return v;
|
|
}
|
|
}
|
|
}
|
|
isDirty() {
|
|
if (super.isDirty()) {
|
|
return true;
|
|
}
|
|
else {
|
|
for (const v of this.allSubviews()) {
|
|
if (v.isDirty()) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
clean() {
|
|
for (let v of this.allSubviews()) {
|
|
v.clean();
|
|
}
|
|
super.clean();
|
|
}
|
|
toModel() {
|
|
const subviews = [];
|
|
for (let v of this.allSubviews()) {
|
|
if (v != undefined) {
|
|
v.superview = this;
|
|
if (v.isDirty()) {
|
|
subviews.push(v.toModel());
|
|
}
|
|
}
|
|
}
|
|
this.dirtyProps.subviews = subviews;
|
|
return super.toModel();
|
|
}
|
|
}
|
|
export class Group extends Superview {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.children = new Proxy([], {
|
|
set: (target, index, value) => {
|
|
const ret = Reflect.set(target, index, value);
|
|
// Let getDirty return true
|
|
this.dirtyProps.children = this.children.map(e => e.viewId);
|
|
return ret;
|
|
}
|
|
});
|
|
}
|
|
allSubviews() {
|
|
return this.children;
|
|
}
|
|
addChild(view) {
|
|
this.children.push(view);
|
|
}
|
|
}
|