Skip to content

Commit

Permalink
edgePoint autohide
Browse files Browse the repository at this point in the history
  • Loading branch information
DamianoNaraku committed Sep 22, 2023
1 parent ae9b4e5 commit 043241d
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 26 deletions.
22 changes: 17 additions & 5 deletions src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
.hoverable{
position: relative;
}
.hoverable:hover>.preview{ display: none; }
.hoverable:hover>.content{ display: block; position: absolute; z-index:1;}
.hoverable>.content{ display: none; }
.hoverable:hover>.preview, .hoverable:hover>svg>.preview{ display: none; }
.hoverable:hover>.content, .hoverable:hover>svg>.content{ display: block; position: absolute; z-index:1;}
.hoverable>.content, .hoverable>svg>.content{ display: none; }

[data-nodetype]{
position: relative;
Expand Down Expand Up @@ -109,7 +109,9 @@ body .ui-icon{ // override jqueryui fixed resizable handles at 16px, making drag
}*/

//////////// edge paths

.hoverable>.preview, .hoverable>svg>.preview{
pointer-events: all;
}
svg.hoverable {

path{
Expand All @@ -120,7 +122,8 @@ svg.hoverable {
&>.content { visibility: hidden; }
}

&:hover:has(path.clickable) {
&:hover:has(path.clickable),
&:focus-within:has(path.clickable) {
&>.preview { visibility: hidden; }
&>.content { visibility: visible; }
}
Expand All @@ -136,5 +139,14 @@ svg.hoverable {
// transform: scale(attr(hoverscale number, 1)); correct but unsupported yet. i'm forced to hardcode a number
}

[data-nodetype="Edge"]>.hide-ep [data-nodetype="EdgePoint"]{
display: none !important;
}

[data-nodetype="Edge"]>.hide-ep:hover [data-nodetype="EdgePoint"],
[data-nodetype="Edge"]>.hide-ep:focus-within [data-nodetype="EdgePoint"]{
display: block !important;
}

//.EdgePoint{ transform: translate(-50%, -50%); }

21 changes: 14 additions & 7 deletions src/common/DV.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class DV {
console.error("error in view:", {publicmsg, debuginfo:debughiddenmsg}); return DefaultView.error(visibleMessage); }

static edgePointView(): string { return beautify(
`<div className={"edgePoint"} tabIndex="-1" hoverscale={"hardcoded in css"} style={{borderRadius:"999px", border: "2px solid black", background:"inherit", width:"100%", height:"100%"}} />`
`<div className={"edgePoint"} tabIndex="-1" hoverscale={"hardcoded in css"} style={{borderRadius:"999px", border: "2px solid black", background:"white", width:"100%", height:"100%"}} />`
)}
static edgePointViewSVG(): string { return beautify(
`<ellipse stroke={"black"} fill={"red"} cx={"50"} cy={"50"} rx={"20"} ry={"20"} />`
Expand Down Expand Up @@ -83,11 +83,19 @@ export class DV {
// about label rotation in .edge > foreignObect > div (label)
// first transform is h-center. second is rotate, third adds [0, 50%] of 50% vertical offset AFTER rotation to take label out of edge. fourth is to add a margin.
static edgeView(modename: EdgeHead, head: DocString<"JSX">, tail: DocString<"JSX">, dashing: string | undefined): string { return beautify(
`<div className={"edge ` + modename + `"} style={{overflow: "visible", width:"100vw", height:"100vh", pointerEvents:"none"}}>
<svg className={"hoverable"} style={{width:"100vw", height:"100vh", pointerEvents:"none", overflow: "visible"}}>
{ /* edge full segment */ }
<path className={"preview"} strokeWidth={this.strokeWidth}
stroke={this.strokeColor} fill={"none"} d={this.edge.d} strokeDasharray="` + dashing + `"></path>
`<div className={"hoverable edge hide-ep ` + modename + `"} style={{overflow: "visible", width:"100vw", height:"100vh", pointerEvents:"none"}}>
<svg style={{width:"100vw", height:"100vh", pointerEvents:"none", overflow: "visible"}}>
{ /* edge full paths
first is preview path, normally seen
third (segmented) is path onHover
second is to enlarge the hover area of path.preview to the same as path.content, so i avoid hover loop enter-leave and graphical flashing
*/ }
<path className={"preview"} strokeWidth={this.strokeWidth} stroke={this.strokeColor}
fill={"none"} d={this.edge.d} strokeDasharray="` + dashing + `"></path>
<path className={"preview"} strokeWidth={this.strokeWidthHover} stroke={"transparent"}
fill={"none"} d={this.edge.d} strokeDasharray="` + dashing + `"></path>
{ /* edge separate segments */ }
{this.segments.all.flatMap(s => [
<path className={"clickable content"} style={{pointerEvents:"all"}} strokeWidth={this.strokeWidthHover}
Expand All @@ -109,7 +117,6 @@ export class DV {
{
edge.midPoints.map( m => <EdgePoint data={edge.father.model.id} initialSize={m} key={m.id} view={"Pointer_ViewEdgePoint"} /> )
}{
edge.end.model.attributes.map( (m, index, arr) => <EdgePoint data={m.id} initialSize={(parent) => {
let segs = parent.segments.segments;
let pos = segs[0].start.pt.multiply(1-(index+1)/(arr.length+1), true).add(segs[segs.length-1].end.pt.multiply((index+1)/(arr.length+1), true));
Expand Down
10 changes: 5 additions & 5 deletions src/common/Geom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,18 +464,18 @@ export class GraphSize extends ISize<GraphPoint> {
const maxY = Math.max(firstPt.y, secondPt.y);
return new GraphSize(minX, minY, maxX - minX, maxY - minY); }


public static closestIntersection(size: GraphSize, pt0: GraphPoint, targetPt: GraphPoint, gridAlign?: GraphPoint, m0?:number, q0?:number): GraphPoint | undefined {
let pt: GraphPoint = pt0.duplicate();
// both pt and targetPt are readonly-safe parameters
public static closestIntersection(size: GraphSize, pt: GraphPoint, targetPt: GraphPoint, gridAlign?: GraphPoint, m0?:number, q0?:number): GraphPoint | undefined {
// let pt: GraphPoint = pt0.duplicate();
const m = m0 || GraphPoint.getM(targetPt, pt);
const q = q0 || GraphPoint.getQ(targetPt, pt);
// console.log("closestIntersection()", {size, pt0, targetPt, m, q});
// if perfectly vertical line
if (m === Number.POSITIVE_INFINITY/* && q === Number.NEGATIVE_INFINITY*/) {
// top center
if (Math.abs(targetPt.y - size.y) <= Math.abs(targetPt.y - size.y - size.h)) return new GraphPoint(pt0.x, size.y);
if (Math.abs(targetPt.y - size.y) <= Math.abs(targetPt.y - size.y - size.h)) return pt;
// bottom center
else return new GraphPoint(pt0.x, size.y + size.h);
else return new GraphPoint(pt.x, size.y + size.h);
}
let tl = size.tl(), tr = size.tr(),
bl = size.bl(), br = size.br();
Expand Down
30 changes: 21 additions & 9 deletions src/model/dataStructure/GraphDataElements.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,10 @@ export class EdgeSegment{
let prev: EdgeSegment | undefined = this.prev;
if (!prev) return;
let prevedgemakerbezier: segmentmaker = (prev.bezier[prev.bezier.length-1] || prev.start);
let mirroredBezier: segmentmaker = {...prevedgemakerbezier, pt: EdgeSegment.invertLastBezierPt(prevedgemakerbezier.pt, prev.end.pt)};
let mirroredBezier: segmentmaker = {...prevedgemakerbezier,
pt: EdgeSegment.invertLastBezierPt(prevedgemakerbezier.pt, prev.end.pt),
uncutPt: EdgeSegment.invertLastBezierPt(prevedgemakerbezier.uncutPt, prev.end.uncutPt),
};
this.bezier = [mirroredBezier, ...this.bezier];
// always only 1 assumed pt both in cubic and quadratic.
// let next: this | undefined = this.segments[this.index+1];
Expand All @@ -1309,14 +1312,17 @@ export class EdgeSegment{
let bezierpts = [...this.bezier.map( b => b.pt), this.end.pt];
let finalpart = svgLetter + " " + bezierpts.map((p)=> p.x + " " + p.y).join(", ");
this.dpart = "M " + this.start.pt.x + " " + this.start.pt.y + ", " + finalpart;
let bezierptsUncut = [...this.bezier.map( b => b.uncutPt), this.end.pt]; // uncutPt exist for start and end too, but i want to use the cut one for those. or edgehead is off
let finalpartUncut = svgLetter + " " + bezierptsUncut.map((p)=> p.x + " " + p.y).join(", ");
this.d = (index === 0 ? "M" + this.start.pt.x + " " + this.start.pt.y + ", " : "") + finalpartUncut;

//midp = [this.startp, ...this.midp];
// d = M sp X mp2 ep // X = custom letter
// dpart = T sp X mp2 ep // S = S if X = C,
// sp is the startingpoint from the prev node, which might be != from endpoint of last node if last node have w>0 && h>0
// so i'm "filling" the gap with a T, or L arc wich can use only 1 parameter (they are the only 1-parameter arcs)
let startletter: string;
if (this.prev && this.prev.end.pt.equals(this.start.pt)) gapMode = EdgeGapMode.average; // if the 2 points coincide, i use any 1 of the gapmodes that are continuous
switch (gapMode){
/*switch (gapMode){
case EdgeGapMode.center:
case EdgeGapMode.average:
// continuous gap modes. they only differ in how the "joining" point is found, but not in how they behave after that.
Expand All @@ -1331,7 +1337,7 @@ export class EdgeSegment{
case SvgLetter.L: case SvgLetter.M:
startletter = SvgLetter.L + " "; break;
}
}*/
}* /
if (index) {
this.d = finalpart;
}
Expand All @@ -1346,7 +1352,7 @@ export class EdgeSegment{
break;
default:
Log.exDevv("unexpected EdgeGapMode:" + gapMode, {gapMode});
}
}*/
break;
default: return Log.exDevv("unexpected bending mode length:" + this.svgLetter + " or fillMode: " + gapMode, {bendingMode: this.svgLetter, index, gapMode});
}
Expand Down Expand Up @@ -1399,7 +1405,7 @@ export class EdgeFillSegment extends EdgeSegment{
}


type segmentmaker = {size: GraphSize, view: LViewElement, ge: LGraphElement, pt: GraphPoint};
type segmentmaker = {size: GraphSize, view: LViewElement, ge: LGraphElement, pt: GraphPoint, uncutPt: GraphPoint};
@RuntimeAccessible
export class LVoidEdge<Context extends LogicContext<DVoidEdge> = any, D extends DEdge = DEdge> extends LGraphElement {
public static cname: string = "LVoidEdge";
Expand Down Expand Up @@ -1657,18 +1663,20 @@ replaced by startPoint
return size.tl().add(offset, false);
}
const all: segmentmaker[] = allNodes.flatMap((ge, i) => {
let base: segmentmaker = {view: ge.view, size: outer ? ge.outerSize : ge.innerSize, ge, pt: null as any};
let base: segmentmaker = {view: ge.view, size: outer ? ge.outerSize : ge.innerSize, ge, pt: null as any, uncutPt: null as any};
let rets: segmentmaker | undefined;// = base as any;
let rete: segmentmaker | undefined;// = {...base} as any;
if (i !== 0){
rete = {...base};
rete.pt = (LEdgePoint.singleton as LEdgePoint).get_endPoint(undefined as any, rete.size, rete.view);
rete.pt = getAnchorOffset(rete.size, rete.view.edgeStartOffset, rete.view.edgeStartOffset_isPercentage);
rete.uncutPt = rete.pt;
}
if (i !== allNodes.length - 1){
rets = {...base};
rets.pt = (LEdgePoint.singleton as LEdgePoint).get_startPoint(undefined as any, rets.size, rets.view);
rets.pt = getAnchorOffset(rets.size, rets.view.edgeStartOffset, rets.view.edgeStartOffset_isPercentage);
rets.uncutPt = rets.pt;
}
// ret.pt = ge.startPoint
return rets && rete ? [rete, rets] : (rets ? [rets] : [rete as segmentmaker]); }
Expand Down Expand Up @@ -1764,7 +1772,7 @@ replaced by startPoint
// cut i === 0 is cut regardless of gapmode.
if (canCutStart) {
ci = GraphSize.closestIntersection(ret[0].start.size, ret[0].start.pt, (ret[0].bezier[0] || ret[0].end).pt, grid);
if (ci) ret[0].start.pt = ci;
if (ci) ret[0].start.pt = ci;
/*
ret[0].start.pt =
GraphSize.closestIntersection(ret[0].start.size, ret[0].start.pt, (ret[0].bezier[0] || ret[0].end).pt, grid) as any
Expand Down Expand Up @@ -1817,13 +1825,17 @@ replaced by startPoint
// they merge if just 1 of cutting sides are true. (and if they are both false we don't even enter the for loop)
curr.start.pt.add(prev.end.pt, false).divide(2, false);
prev.end.pt = curr.start.pt.duplicate() // intentionally not the same pt because during snap to edge they can temporarly diverge.again,
prev.start.uncutPt = prev.start.pt;
prev.end.uncutPt = prev.end.pt;
break;
// center: first move it to center of edgePoint/node, then snap to edge.
// this mode might be as well deleted, it can be specified with anchor points
case EdgeGapMode.center:
doEndCut = true; doStartCut = true;
doEndCut = false; doStartCut = false;
curr.start.pt = curr.start.size.tl().add(curr.start.size.br(), false).divide(2, false);
prev.end.pt = curr.start.pt.duplicate(); // intentionally not the same pt because during snap to edge they can diverge.again,
prev.start.uncutPt = prev.start.pt; // only update them when point moves without being cut (average and center)
prev.end.uncutPt = prev.end.pt;
break;
default:
return Log.exDevv("unexpected EdgeGapMode:" + gapMode);
Expand Down

0 comments on commit 043241d

Please sign in to comment.