This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Doric/doric-js/lib/src/ui/view.js
2020-01-03 17:05:24 +08:00

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);
}
}