move dir
This commit is contained in:
69
doric-js/src/pattern/candies.ts
Normal file
69
doric-js/src/pattern/candies.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export function take<T>(target: T) {
|
||||
return (block: (p: T) => void) => {
|
||||
block(target)
|
||||
}
|
||||
}
|
||||
|
||||
export function takeNonNull<T, R>(target?: T) {
|
||||
return (block: (p: T) => R) => {
|
||||
if (target !== undefined) {
|
||||
return block(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function takeNull<T, R>(target?: T) {
|
||||
return (block: () => R) => {
|
||||
if (target === undefined) {
|
||||
return block()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function takeLet<T, R>(target: T) {
|
||||
return (block: (p: T) => R | undefined) => {
|
||||
return block(target)
|
||||
}
|
||||
}
|
||||
|
||||
export function takeAlso<T>(target: T) {
|
||||
return (block: (p: T) => void) => {
|
||||
block(target)
|
||||
return target
|
||||
}
|
||||
}
|
||||
|
||||
export function takeIf<T>(target: T) {
|
||||
return (predicate: (t: T) => boolean) => {
|
||||
return predicate(target) ? target : undefined
|
||||
}
|
||||
}
|
||||
|
||||
export function takeUnless<T>(target: T) {
|
||||
return (predicate: (t: T) => boolean) => {
|
||||
return predicate(target) ? undefined : target
|
||||
}
|
||||
}
|
||||
|
||||
export function repeat(action: (count: number) => void) {
|
||||
return (times: number) => {
|
||||
for (let i = 0; i < times; i++) {
|
||||
action(i)
|
||||
}
|
||||
}
|
||||
}
|
18
doric-js/src/pattern/index.pattern.ts
Normal file
18
doric-js/src/pattern/index.pattern.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export * from './candies'
|
||||
export * from './provider'
|
||||
export * from './mvvm'
|
78
doric-js/src/pattern/mvvm.ts
Normal file
78
doric-js/src/pattern/mvvm.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Group } from "../ui/view"
|
||||
import { Panel } from "../ui/panel"
|
||||
|
||||
export abstract class ViewHolder {
|
||||
abstract build(root: Group): void
|
||||
}
|
||||
|
||||
export type Setter<M> = (state: M) => void
|
||||
|
||||
export abstract class ViewModel<M extends Object, V extends ViewHolder> {
|
||||
private state: M
|
||||
private viewHolder: V
|
||||
|
||||
constructor(obj: M, v: V) {
|
||||
this.state = obj
|
||||
this.viewHolder = v
|
||||
}
|
||||
|
||||
getState() {
|
||||
return this.state
|
||||
}
|
||||
|
||||
updateState(setter: Setter<M>) {
|
||||
setter(this.state)
|
||||
this.onBind(this.state, this.viewHolder)
|
||||
}
|
||||
|
||||
attach(view: Group) {
|
||||
this.viewHolder.build(view)
|
||||
this.onAttached(this.state, this.viewHolder)
|
||||
this.onBind(this.state, this.viewHolder)
|
||||
}
|
||||
|
||||
abstract onAttached(state: M, vh: V): void
|
||||
|
||||
abstract onBind(state: M, vh: V): void
|
||||
}
|
||||
export type ViewModelClass<M, V extends ViewHolder> = new (m: M, v: V) => ViewModel<M, V>
|
||||
|
||||
export type ViewHolderClass<V> = new () => V
|
||||
|
||||
export abstract class VMPanel<M extends Object, V extends ViewHolder> extends Panel {
|
||||
|
||||
private vm?: ViewModel<M, V>
|
||||
private vh?: V
|
||||
|
||||
abstract getViewModelClass(): ViewModelClass<M, V>
|
||||
|
||||
abstract getState(): M
|
||||
|
||||
abstract getViewHolderClass(): ViewHolderClass<V>
|
||||
|
||||
getViewModel() {
|
||||
return this.vm
|
||||
}
|
||||
|
||||
build(root: Group): void {
|
||||
this.vh = new (this.getViewHolderClass())
|
||||
this.vm = new (this.getViewModelClass())(this.getState(), this.vh)
|
||||
this.vm.attach(root)
|
||||
}
|
||||
}
|
||||
|
99
doric-js/src/pattern/provider.ts
Normal file
99
doric-js/src/pattern/provider.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export type Observer<T> = (v: T) => void
|
||||
export type Updater<T> = (v: T) => T
|
||||
|
||||
export interface IObservable<T> {
|
||||
|
||||
addObserver(observer: Observer<T | undefined>): void
|
||||
|
||||
removeObserver(observer: Observer<T | undefined>): void
|
||||
|
||||
update(updater: Updater<T | undefined>): void
|
||||
}
|
||||
|
||||
export class Observable<M> implements IObservable<M>{
|
||||
private provider: IProvider
|
||||
|
||||
private clz: { new(...args: any[]): M }
|
||||
|
||||
private observers: Set<Observer<M | undefined>> = new Set
|
||||
constructor(provider: IProvider, clz: { new(...args: any[]): M }) {
|
||||
this.provider = provider
|
||||
this.clz = clz
|
||||
}
|
||||
|
||||
addObserver(observer: Observer<M | undefined>): void {
|
||||
this.observers.add(observer)
|
||||
}
|
||||
|
||||
removeObserver(observer: Observer<M | undefined>): void {
|
||||
this.observers.delete(observer)
|
||||
}
|
||||
|
||||
update(updater: Updater<M | undefined>): void {
|
||||
const oldV = this.provider.acquire(this.clz)
|
||||
const newV = updater(oldV)
|
||||
if (newV !== undefined) {
|
||||
this.provider.provide(newV)
|
||||
}
|
||||
for (let observer of this.observers) {
|
||||
observer(newV)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export interface IProvider {
|
||||
provide(obj: Object): void
|
||||
acquire<T>(clz: { new(...args: any[]): T }): T | undefined
|
||||
remove<T>(clz: { new(...args: any[]): T }): void
|
||||
clear(): void
|
||||
observe<T>(clz: { new(...args: any[]): T }): Observable<T>
|
||||
}
|
||||
|
||||
export class Provider implements IProvider {
|
||||
|
||||
private provision: Map<Function, Object> = new Map
|
||||
private observableMap: Map<Function, Observable<any>> = new Map
|
||||
|
||||
provide(obj: Object) {
|
||||
this.provision.set(obj.constructor, obj)
|
||||
}
|
||||
|
||||
acquire<T>(clz: { new(...args: any[]): T }): T | undefined {
|
||||
const ret = this.provision.get(clz)
|
||||
return ret as T | undefined
|
||||
}
|
||||
|
||||
remove<T>(clz: new (...args: any[]) => T): void {
|
||||
this.provision.delete(clz)
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.provision.clear()
|
||||
}
|
||||
|
||||
observe<T>(clz: new (...args: any[]) => T): Observable<T> {
|
||||
let observable = this.observableMap.get(clz)
|
||||
if (observable === undefined) {
|
||||
observable = new Observable(this, clz)
|
||||
this.observableMap.set(clz, observable)
|
||||
}
|
||||
return observable
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user