rxValue.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { HistoryController } from "./history";
  2. import {BehaviorSubject} from "rxjs";
  3. import { reactive, toRaw } from "vue";
  4. export class ValueSnap {
  5. Id:string;
  6. Value: any;
  7. OldValue: any;
  8. Rx: BehaviorSubject<any>;
  9. constructor(id:string, value:any, oldValue:any, rx: BehaviorSubject<any>) {
  10. this.Id = id;
  11. this.Value = value;
  12. this.OldValue = oldValue;
  13. this.Rx = rx
  14. }
  15. redo() {
  16. this.Rx.next({value: this.Value, _hstry:false});
  17. }
  18. undo() {
  19. this.Rx.next({value: this.OldValue, _hstry:false});
  20. }
  21. clone() {
  22. return new ValueSnap(this.Id, this.Value,this.OldValue, this.Rx);
  23. }
  24. }
  25. export type RxValueType<T> = {
  26. value: T,
  27. _hstry?: boolean
  28. }
  29. function createRxValue<T>(value: T, histry:boolean) {
  30. return new BehaviorSubject< RxValueType<T> >({value:value, _hstry: histry})
  31. }
  32. let _valueIndex = 0;
  33. export function createValueSnap(value:any, oldValue:any, rx:BehaviorSubject<any>) {
  34. let i = _valueIndex + 1;
  35. _valueIndex +=1;
  36. return new ValueSnap(i+"", value, oldValue, rx);
  37. }
  38. class RxValue {
  39. static create<T extends {[key:string]: any}>(_fields:T, histroy?: HistoryController ) {
  40. let obj = {} as any;
  41. obj._historySnap = {} as any;
  42. obj._historySub = {} as any;
  43. obj._rxs = {} as any;
  44. obj._fields = _fields;
  45. obj._history = histroy;
  46. obj._refs = {} as any;
  47. const names = Object.keys(_fields);
  48. names.forEach(name=>{
  49. const currName = name;
  50. const initValue = _fields[currName]
  51. const f = createRxValue(initValue, !!histroy);
  52. obj._rxs[name] = f;
  53. const snap = createValueSnap(initValue, initValue, f);
  54. obj._historySnap[name] = snap;
  55. const rxc = reactive({value: initValue});
  56. Object.defineProperty(obj, currName, {
  57. get: function(){
  58. return rxc.value;
  59. },
  60. set: function(v) {
  61. f.next({value: v});
  62. },
  63. configurable: true,
  64. enumerable: true
  65. })
  66. const CamName = currName.slice(0,1).toUpperCase() +currName.slice(1);
  67. obj["set"+CamName] = function(value:T, nohistory = false){
  68. f.next({value, _hstry: !nohistory});
  69. }
  70. obj["on"+CamName + "Changed"] = function(subscribe: (value:T, oldValue:T)=>void){
  71. return f.subscribe((v:any)=>{
  72. if (CamName == "Transform") console.log("history 2222222222222222222222222222")
  73. subscribe(v.value, snap.OldValue)
  74. }
  75. )
  76. }
  77. obj._historySub[name] = f.subscribe((v)=>{
  78. if (CamName == "Transform") console.log("history 11111111111111111111111111")
  79. snap.OldValue = rxc.value;
  80. rxc.value = v.value;
  81. if (obj._history && obj._history.enable) {
  82. if (!v._hstry) return;
  83. const s = snap.clone();
  84. s.Value = v.value;
  85. obj._history.record(s);
  86. }
  87. })
  88. });
  89. obj["setHistory"] = function(h: HistoryController){
  90. obj._history = h;
  91. }
  92. obj["toJson"] = function() {
  93. const out:any = {};
  94. const names = Object.keys(_fields);
  95. names.forEach(name=>{
  96. out[name] = obj._rxs[name].getValue().value;
  97. })
  98. return out;
  99. }
  100. obj["fromJson"] = function(json:any) {
  101. const out:any = {};
  102. const names = Object.keys(_fields);
  103. names.forEach(name=>{
  104. obj._rxs[name].next({value: json[name], _hstry: false})
  105. })
  106. return out;
  107. }
  108. return obj as typeof _fields & {
  109. [K in keyof typeof _fields as `set${Capitalize<string & K>}`]: (value: typeof _fields[K], nohistory?:boolean) => void;
  110. } & {
  111. [K in keyof typeof _fields as `on${Capitalize<string & K>}Changed`]: (subscribe: (value: typeof _fields[K], oldValue:typeof _fields[K])=>void) => void;
  112. } &
  113. // {
  114. // [K in keyof typeof _fields as `ref${Capitalize<string & K>}`]: () => typeof _fields[K];
  115. // } &
  116. {
  117. setHistory: (history: HistoryController)=>void
  118. toJson:()=>typeof _fields
  119. fromJson:(json:typeof _fields)=>void
  120. }
  121. }
  122. }
  123. export {RxValue};