From b7565f75deb994b295ddf6a2de25756f4be45800 Mon Sep 17 00:00:00 2001 From: Damiano Di Vincenzo Date: Fri, 29 Sep 2023 04:25:47 +0200 Subject: [PATCH] fixed size after view change, edge outline --- src/App.scss | 3 + src/common/DV.tsx | 8 ++- src/graph/vertex/Vertex.tsx | 2 +- src/joiner/classes.ts | 3 +- src/model/dataStructure/GraphDataElements.tsx | 5 ++ src/model/logicWrapper/LModelElement.tsx | 72 +++++++++++-------- src/redux/action/action.ts | 2 +- src/redux/selectors/selectors.ts | 2 +- 8 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/App.scss b/src/App.scss index c22c94b0c..f3c485656 100644 --- a/src/App.scss +++ b/src/App.scss @@ -116,6 +116,9 @@ body .ui-icon{ // override jqueryui fixed resizable handles at 16px, making drag //////////// edge paths path{ pointer-events: stroke; + &:focus{ + outline: none; + } } /* .hoverable>.preview, .hoverable>svg>.preview{ diff --git a/src/common/DV.tsx b/src/common/DV.tsx index 5c1bd2976..ceb740b29 100644 --- a/src/common/DV.tsx +++ b/src/common/DV.tsx @@ -168,13 +168,15 @@ class DefaultView { true && data.suggestedEdges.extend && data.suggestedEdges.extend.map( se => (!se.vertexOverlaps) - && )] + && )] } - {data && data.packages.map((pkg, index) => { + {data && data["$default"] && } + {data && data.packages.map((pkg) => { + if (pkg.name === "default") return undefined; return })} - {data && data.allSubObjects.map((child, index) => { + {data && data.allSubObjects.map((child) => { return })} `; diff --git a/src/graph/vertex/Vertex.tsx b/src/graph/vertex/Vertex.tsx index df382d6f8..9c201db68 100644 --- a/src/graph/vertex/Vertex.tsx +++ b/src/graph/vertex/Vertex.tsx @@ -276,7 +276,7 @@ export class VertexComponent { - return this.props.node.size; + return this.props.node.getSize(false, !this.props.node.isResized && this.props.view.adaptWidth); /*console.log('get_size('+(this.props?.data as any).name+')', { view:this.props.view.getSize(this.props.dataid || this.props.nodeid as string), node:this.props.node?.size, diff --git a/src/joiner/classes.ts b/src/joiner/classes.ts index fa49d595f..e464903ab 100644 --- a/src/joiner/classes.ts +++ b/src/joiner/classes.ts @@ -1139,7 +1139,8 @@ export class Pointers{ return typeof data === "string" ? data : (data as any).id; } - static isPointer(val: any): val is Pointer { + static isPointer(val: any, state?: DState): val is Pointer { + if (state) return !!state.idlookup[val]; // todo: must refine this in a safer way return typeof val === "string" ? val.includes("Pointer") : false; } diff --git a/src/model/dataStructure/GraphDataElements.tsx b/src/model/dataStructure/GraphDataElements.tsx index 04942f872..d6fa2ff99 100644 --- a/src/model/dataStructure/GraphDataElements.tsx +++ b/src/model/dataStructure/GraphDataElements.tsx @@ -314,6 +314,11 @@ export class LGraphElement = any, C __info_of__innerSize: Info = {type:"GraphSize", txt:"the size of the current element relative to the last (most nested) graph level."}; __info_of__size: Info = {type:"GraphSize", txt: "same as innerSize."}; + + getSize(outer: boolean = false, canTriggerSet: boolean = true): Readonly { return this.wrongAccessMessage("getSize()"); } + get_getSize(c: Context): ((outer?: boolean, canTriggerSet?: boolean) => Readonly) { + return (outer: boolean = true, canTriggerSet: boolean = true) => this.get_innerSize(c, canTriggerSet, outer); } + get_outerSize(context: Context, canTriggerSet: boolean = true): Readonly { return this.get_innerSize(context, canTriggerSet, true); } diff --git a/src/model/logicWrapper/LModelElement.tsx b/src/model/logicWrapper/LModelElement.tsx index 08c2425d3..3df44caa8 100644 --- a/src/model/logicWrapper/LModelElement.tsx +++ b/src/model/logicWrapper/LModelElement.tsx @@ -3330,12 +3330,12 @@ export class EdgeStarter{ // = any, C extends Contex allSubAnnotations!: LAnnotation[]; allSubPackages!: LPackage[]; allSubObjects!: LObject[]; + allSubValues!: LValue[]; suggestedEdges!: {extend: EdgeStarter[], reference:EdgeStarter[], packageDependencies: EdgeStarter[]}; //, model: EdgeStarter[], package:EdgeStarter[], class:EdgeStarter[]}; __info_of__suggestedEdges: Info = {type: 'Dictionary<"extend" | "reference" | "packageDependencies" | DmodelName, EdgeStarter[]>', txt: "A map to access all possible kind of edges based on model data." + "
extend and reference are the most commonly used for horizontal references (outside the containment tree schema)." + @@ -3453,21 +3454,40 @@ export class LModel = any, C extends Contex let ret: this["suggestedEdges"]; if (context.data.isMetamodel) ret = this.get_suggestedEdgesM2(context); else ret = this.get_suggestedEdgesM1(context); - /* - ret.extend = ret.extend || []; - ret.packageDependencies = ret.packageDependencies || []; - ret.reference = ret.reference || []; - - console.log("suggested edges, pre filter", {...ret}); - ret.extend = ret.extend.filter( r => !r.startNode.size.isOverlapping(r.endNode.size)); - ret.packageDependencies = ret.packageDependencies.filter( r => !r.startNode.size.isOverlapping(r.endNode.size)); - ret.reference = ret.reference.filter( r => !r.startNode.size.isOverlapping(r.endNode.size)); + return ret; + } - console.log("suggested edges, post filter", {...ret});*/ + private get_suggestedEdgesM1(context: Context, state?: DState): this["suggestedEdges"]{ + let ret: this["suggestedEdges"] = {extend: [], reference: [], packageDependencies: []}; + let s: DState = store.getState(); + let values: LValue[] = this.get_allSubValues(context, s); + let map: Dictionary, EdgeStarter[]> = {}; + if (!state) state = store.getState(); + outer: + for (let lval of values) { + if (!lval) continue; + let dval = lval.__raw; + // NB: ELiterals can be pointers in L, but string or ordinal numbers in D, but they won't make edges, so i use .__raw + inner: + for (let v of (dval.values || [])) { + if (!Pointers.isPointer(v, state)) continue inner; + let snode = lval.node; + if (!snode) continue outer; + if (v === dval.id) continue inner; // pointing to itself + let ltarget: undefined | LEnumLiteral | LObject = LPointerTargetable.fromPointer(v, state); + if (!ltarget) continue; + if (ltarget.className !== DObject.cname) continue inner; + let enode = ltarget.node; + if (!enode) continue inner; + if (!map[dval.id]) map[dval.id] = []; + map[dval.id].push(new EdgeStarter(lval, ltarget, snode, enode, undefined)); + } + } + ret.reference = Object.values(map).flat(); return ret; } private get_suggestedEdgesM2(context: Context): this["suggestedEdges"]{ - let ret: this["suggestedEdges"] = {} as any; + let ret: this["suggestedEdges"] = {extend: [], reference: [], packageDependencies: []}; let s: DState = store.getState(); let classes: LClass[] = this.get_classes(context, s); let references: LReference[] = classes.flatMap(c=>c.references); @@ -3528,10 +3548,6 @@ export class LModel = any, C extends Contex ret.packageDependencies = pkgdependencies.flatMap( pd => ( Object.values(pd.ends).map((end) => new EdgeStarter(pd.src, end.end, pd.sn, end.en)))); // todo: check return ret; } - private get_suggestedEdgesM1(context: Context): this["suggestedEdges"]{ - let ret: this["suggestedEdges"] = {todo:true} as any; - return ret;// todo - } protected get_models(context: Context): LModel[] { return LModel.fromPointer(context.data.models); @@ -3660,9 +3676,17 @@ export class LModel = any, C extends Contex } return LPointerTargetable.from(Object.keys(checked), state); } + + protected get_allSubValues(context: Context, state?: DState): this["allSubValues"] { + state = state || store.getState(); + return (Selectors.getAll(DValue, undefined, state, true, true) as LValue[]) + .filter( (o: LValue) => o.model.id === context.data.id); + } + protected get_allSubObjects(context: Context, state?: DState): this["allSubObjects"] { state = state || store.getState(); - return (Selectors.getAll(DObject, undefined, state, true, true) as LObject[]).filter( (o: LObject) => o.model.id === context.data.id); + return (Selectors.getAll(DObject, undefined, state, true, true) as LObject[]) + .filter( (o: LObject) => o.model.id === context.data.id); /* let tocheck: Pointer[] = context.data.objects || []; let checked: Dictionary = {}; @@ -4276,7 +4300,6 @@ export class LValue = any, C extends Contex let ret: any[] = [...context.data.values] as []; let meta: LAttribute | LReference | undefined = shapeless ? undefined : context.proxyObject.instanceof; let dmeta: undefined | DAttribute | DReference = meta?.__raw; - console.trace("$gval 0", {v: {...ret}, v0:context.data.values, meta}); // if (meta && meta.className === DReference.name) ret = LPointerTargetable.fromArr(ret as DObject[]); let typestr: string = meta ? meta.typeToShortString() : "shapeless"; @@ -4292,7 +4315,6 @@ export class LValue = any, C extends Contex // console.log("get_values sizefixed", {fitSize, arguments, upperbound:dmeta?.upperBound, lowerbound: dmeta?.lowerBound, len: ret.length, len0: context.data.values.length}); let numbermax = 0, numbermin = 0, round = true; // ret is always an array of raw values before this point, eventually padded with lowerbound or trimmed at upperbound - console.log("$gval 1", {v: {...ret}, v0:context.data.values, typestr, meta}); let index = 0; if (withmetainfo) { ret = ret.map(r => {return {value:r, rawValue: r, index: index++, hidden: false} as ValueDetail}); } @@ -4328,7 +4350,6 @@ export class LValue = any, C extends Contex default: // it's a reference or enum let lenum: LEnumerator = undefined as any; let type: LClassifier = (meta as LStructuralFeature)?.type; - console.log("$gval 2", {v: {...ret}, v0:context.data.values, type, typestr, meta}); if (type?.className === DEnumerator.cname) { lenum = type as LEnumerator; mapperfunc = (r: any) => { @@ -4350,7 +4371,6 @@ export class LValue = any, C extends Contex else mapperfunc = (r: any) => r; if (withmetainfo) ret.forEach((struct: ValueDetail) => { struct.value = mapperfunc(struct.value); }); else ret = ret.map(mapperfunc); - console.log("$gval 3", {v: {...ret}, v0:context.data.values, type, typestr, meta, solveLiterals}); // now ret is pointed DEnumLiteral or DObject or MetaInfoStructure<> if (type?.className === DEnumerator.cname) { @@ -4371,13 +4391,11 @@ export class LValue = any, C extends Contex else ret = ret.filter(filterfunc); // todo: questo comportamento implica che quando importo un literal come testo da .ecore, devo assegnargli // il puntatore al suo literal se trovato, altrimenti resta val[i] di tipo string/shapeless - console.log("$gval 4", {v: {...ret}, namedPointers, v0:context.data.values, type, typestr, meta}); if (namedPointers) { mapperfunc = (lit?: LEnumLiteral) => lit?.name; if (withmetainfo) ret.forEach((struct: ValueDetail) => { struct.value = mapperfunc(struct.value); }); else ret = ret.map(mapperfunc); } - console.log("$gval 5", {v: {...ret}, namedPointers, v0:context.data.values, type, typestr, meta}); break; } // is reference with assigned shape (and type) -> filter correct typed targets @@ -4615,10 +4633,8 @@ export class LValue = any, C extends Contex protected set_values(val: orArr, context: Context): boolean { const list: D["values"] = ((Array.isArray(val)) ? val : [val]) as D["values"]; let modified = false; - console.log("$sval", {list, modified}); for (let i = 0; i < list.length; i++) { modified = this.get_setValueAtPosition(context)(i, list[i], {setMirage: false} as any).success || modified; - console.log("$sval loop "+i, {i, v:list[i], list, modified}); } if (modified) context.data.isMirage && SetFieldAction.new(context.data, 'isMirage', false, '', false); return true; diff --git a/src/redux/action/action.ts b/src/redux/action/action.ts index 1ace9371f..b6666a92e 100644 --- a/src/redux/action/action.ts +++ b/src/redux/action/action.ts @@ -169,7 +169,7 @@ export class Action extends RuntimeAccessibleClass { this.field = field; this.value = value; this.type = (this.constructor as any).type; - // this.src = new Error().stack?.split('\n').splice( 4); + this.stack = new Error().stack?.split('\n').splice( 4); this.subType = subType; this.className = (this.constructor as typeof RuntimeAccessibleClass).cname || this.constructor.name; } diff --git a/src/redux/selectors/selectors.ts b/src/redux/selectors/selectors.ts index 7a2dd25c5..3afadf5f9 100644 --- a/src/redux/selectors/selectors.ts +++ b/src/redux/selectors/selectors.ts @@ -265,7 +265,7 @@ export class Selectors{ W extends undefined | true | false = false, RP extends undefined | true | false = true, RET = W extends false ? (RP extends false ? Pointer : D) : L> (Classe?: DT, condition?: (e:RET) => boolean, state?: DState, resolvePointers?: RP /**/, wrap?: W /* = true */): RET[] { if (!state) state = store.getState(); - let GClass = (Classe as GObject) || {name:"idlookup"}; + let GClass = (Classe as GObject) || {name:"idlookup", cname:"idlookup"}; const className: string = (GClass?.staticClassName || GClass.cname).toLowerCase(); const allIdByClassName: Pointer[] = (state as GObject)[className]