Revize ed458068
Přidáno uživatelem Pavel Fidranský před téměř 6 roky(ů)
sources/src/main/webapp/js/components/floatingPoint.js | ||
---|---|---|
1 |
/** |
|
2 |
* Class representing a floating point connecting a node present in the viewport with a node excluded to the sidebar. Position |
|
3 |
* of a floating point is changed every time when graph is moved or zoomed, node is moved in viewport or sidebar is scrolled. |
|
4 |
* @constructor |
|
5 |
*/ |
|
6 |
function FloatingPoint() { |
|
7 |
var rootElement; |
|
8 |
|
|
9 |
var node; |
|
10 |
var position = new Coordinates(0, 0); |
|
11 |
|
|
12 |
var inEdgeList = []; |
|
13 |
var outEdgeList = []; |
|
14 |
|
|
15 |
/** |
|
16 |
* Sets a DOM element in sidebar that this floating point is bound to. It is used to calculate floating point position |
|
17 |
* when sidebar is scrolled. |
|
18 |
* @param {Element} newValue DOM element in sidebar the floating point is bound to. |
|
19 |
*/ |
|
20 |
this.setElement = function(newValue) { |
|
21 |
rootElement = newValue; |
|
22 |
}; |
|
23 |
|
|
24 |
/** |
|
25 |
* Sets a graph node (vertex or group) that this floating point is bound to. This node is then highlighted when the other |
|
26 |
* node of the edge is clicked. |
|
27 |
* @param {(Vertex|Group)} newValue Graph node the floating point is bound to. |
|
28 |
*/ |
|
29 |
this.setNode = function(newValue) { |
|
30 |
node = newValue; |
|
31 |
}; |
|
32 |
|
|
33 |
/** |
|
34 |
* Adds a new edge ending in this floating point. Its ending point is moved to the current position of the floating point. |
|
35 |
* @param {Edge} edge Edge going to the floating point. |
|
36 |
*/ |
|
37 |
this.addInEdge = function(edge) { |
|
38 |
if (!(edge instanceof Edge)) { |
|
39 |
throw new TypeError(edge.toString() + 'is not instance of Edge'); |
|
40 |
} |
|
41 |
|
|
42 |
edge.end = this.getPosition(); |
|
43 |
|
|
44 |
inEdgeList.push(edge); |
|
45 |
}; |
|
46 |
|
|
47 |
/** |
|
48 |
* Adds a new edge starting in this floating point. Its starting point is moved to the current position of the floating point. |
|
49 |
* @param {Edge} edge Edge going from the floating point. |
|
50 |
*/ |
|
51 |
this.addOutEdge = function(edge) { |
|
52 |
if (!(edge instanceof Edge)) { |
|
53 |
throw new TypeError(edge.toString() + 'is not instance of Edge'); |
|
54 |
} |
|
55 |
|
|
56 |
edge.start = this.getPosition(); |
|
57 |
|
|
58 |
outEdgeList.push(edge); |
|
59 |
}; |
|
60 |
|
|
61 |
/** |
|
62 |
* @returns {array<Edge>} Array of edges going to the floating point. |
|
63 |
*/ |
|
64 |
this.getInEdgeList = function() { |
|
65 |
return inEdgeList; |
|
66 |
}; |
|
67 |
|
|
68 |
/** |
|
69 |
* @returns {array<Edge>} Array of edges going from the floating point. |
|
70 |
*/ |
|
71 |
this.getOutEdgeList = function() { |
|
72 |
return outEdgeList; |
|
73 |
}; |
|
74 |
|
|
75 |
/** |
|
76 |
* @returns {Coordinates} Current position of the floating point. |
|
77 |
*/ |
|
78 |
this.getPosition = function() { |
|
79 |
return position; |
|
80 |
}; |
|
81 |
|
|
82 |
/** |
|
83 |
* Updates the current position of vertices related to the floating point. |
|
84 |
*/ |
|
85 |
this.setPosition = function() { |
|
86 |
var bbox = rootElement.getBoundingClientRect(); |
|
87 |
var viewportPosition = app.viewportComponent.getPosition(); |
|
88 |
|
|
89 |
position.x = (bbox.left - viewportPosition.x); |
|
90 |
position.y = (bbox.top - viewportPosition.y - app.headerComponent.height - app.navbarComponent.height); |
|
91 |
|
|
92 |
if (node instanceof Vertex) { |
|
93 |
var edgeOffsetY = 10; |
|
94 |
} else if (node instanceof Group) { |
|
95 |
var edgeOffsetY = 35; |
|
96 |
} else { |
|
97 |
var edgeOffsetY = 0; |
|
98 |
} |
|
99 |
|
|
100 |
var archetypeList = Object.keys(node.relatedArchetypeMap).map(function(archetypeIndex) { |
|
101 |
return parseInt(archetypeIndex); |
|
102 |
}); |
|
103 |
var archetypeIconOrder; |
|
104 |
|
|
105 |
// redraw dependent edges |
|
106 |
inEdgeList.forEach(function(edge) { |
|
107 |
archetypeIconOrder = archetypeList.indexOf(edge.from.archetype); |
|
108 |
|
|
109 |
edge.end = new Coordinates( |
|
110 |
position.x / app.zoom.scale, |
|
111 |
(position.y + edgeOffsetY + archetypeIconOrder * 20) / app.zoom.scale, |
|
112 |
}, this); |
|
113 |
); |
|
114 |
|
|
115 |
outEdgeList.forEach(function(edge) { |
|
116 |
archetypeIconOrder = archetypeList.indexOf(edge.to.archetype); |
|
117 |
|
|
118 |
edge.start = new Coordinates( |
|
119 |
position.x / app.zoom.scale, |
|
120 |
(position.y + edgeOffsetY + archetypeIconOrder * 20) / app.zoom.scale, |
|
121 |
}, this); |
|
122 |
); |
|
123 |
}; |
|
124 |
|
|
125 |
/** |
|
126 |
* @returns {Coordinates} Centre of this floating point. |
|
127 |
*/ |
|
128 |
this.getCenter = function() { |
|
129 |
return position; |
|
130 |
}; |
|
131 |
|
|
132 |
/** |
|
133 |
* Always returns false as floating points may never be excluded. It is here for FloatingPoint to be compatible with API of Vertex. |
|
134 |
* @see Vertex |
|
135 |
* @returns {boolean} Always false. |
|
136 |
*/ |
|
137 |
this.isExcluded = function() { |
|
138 |
return false; |
|
139 |
}; |
|
140 |
|
|
141 |
/** |
|
142 |
* Does nothing as floating points may never be dimmed. It is here for FloatingPoint to be compatible with API of Vertex. |
|
143 |
* @see Vertex |
|
144 |
* @param {boolean} newValue Anything. |
|
145 |
*/ |
|
146 |
this.setDimmed = function(newValue) { |
|
147 |
// do nothing |
|
148 |
}; |
|
149 |
|
|
150 |
/** |
|
151 |
* Toggles highlighting of the depedent node. |
|
152 |
* @param {boolean} newValue True to highlight the node as required, otherwise false. |
|
153 |
*/ |
|
154 |
this.setHighlightedRequired = function(newValue) { |
|
155 |
node.isHighlightedAsRequired = newValue; |
|
156 |
}; |
|
157 |
|
|
158 |
/** |
|
159 |
* Toggles highlighting of the depedent node. |
|
160 |
* @param {boolean} newValue True to highlight the node as provided, otherwise false. |
|
161 |
*/ |
|
162 |
this.setHighlightedProvided = function(newValue) { |
|
163 |
node.isHighlightedAsProvided = newValue; |
|
164 |
}; |
|
165 |
} |
sources/src/main/webapp/js/components/group.js | ||
---|---|---|
396 | 396 |
]); |
397 | 397 |
|
398 | 398 |
// set floater |
399 |
this._proxy.setElement(this._rootElement);
|
|
399 |
this._proxy.element = this._rootElement;
|
|
400 | 400 |
|
401 | 401 |
// set edges' ends |
402 | 402 |
let inEdgeList = this.inEdgeList; |
sources/src/main/webapp/js/components/node.js | ||
---|---|---|
279 | 279 |
|
280 | 280 |
if (newValue) { |
281 | 281 |
// set floater |
282 |
this._proxy = new FloatingPoint; |
|
283 |
this._proxy.setNode(this); |
|
282 |
this._proxy = new NodeProxy(this); |
|
284 | 283 |
app.sidebarComponent.addFloater(this._proxy); |
285 | 284 |
|
286 | 285 |
} else { |
sources/src/main/webapp/js/components/nodeProxy.js | ||
---|---|---|
1 |
/** |
|
2 |
* Class representing a proxy node connecting a node present in the viewport with a node excluded to the sidebar. Position |
|
3 |
* of a proxy is changed every time when graph is moved or zoomed, the node is moved in viewport or sidebar is scrolled. |
|
4 |
*/ |
|
5 |
class NodeProxy { |
|
6 |
/** |
|
7 |
* @constructor |
|
8 |
* @param {Node} node Node that this proxy is bound to. |
|
9 |
*/ |
|
10 |
constructor(node) { |
|
11 |
if (!(node instanceof Node)) { |
|
12 |
throw new TypeError(node.toString() + ' is not an instance of Node'); |
|
13 |
} |
|
14 |
|
|
15 |
this._node = node; |
|
16 |
|
|
17 |
this._position = new Coordinates(0, 0); |
|
18 |
|
|
19 |
this._inEdgeList = []; |
|
20 |
this._outEdgeList = []; |
|
21 |
} |
|
22 |
|
|
23 |
/** |
|
24 |
* Sets a DOM element in sidebar that this proxy is bound to. It is used to calculate proxy position when sidebar is scrolled. |
|
25 |
* @param {Element} newValue DOM element in sidebar the proxy is bound to. |
|
26 |
*/ |
|
27 |
set element(newValue) { |
|
28 |
if (!(newValue instanceof Element)) { |
|
29 |
throw new TypeError(newValue.toString() + ' is not an instance of Element'); |
|
30 |
} |
|
31 |
|
|
32 |
this._rootElement = newValue; |
|
33 |
} |
|
34 |
|
|
35 |
/** |
|
36 |
* Adds a new edge ending in this proxy. Its ending point is moved to the current position of the proxy. |
|
37 |
* @param {Edge} edge Edge going to this proxy. |
|
38 |
*/ |
|
39 |
addInEdge(edge) { |
|
40 |
if (!(edge instanceof Edge)) { |
|
41 |
throw new TypeError(edge.toString() + ' is not an instance of Edge'); |
|
42 |
} |
|
43 |
|
|
44 |
edge.end = this.position; |
|
45 |
|
|
46 |
this._inEdgeList.push(edge); |
|
47 |
} |
|
48 |
|
|
49 |
/** |
|
50 |
* Adds a new edge starting in this proxy. Its starting point is moved to the current position of the proxy. |
|
51 |
* @param {Edge} edge Edge going from this proxy. |
|
52 |
*/ |
|
53 |
addOutEdge(edge) { |
|
54 |
if (!(edge instanceof Edge)) { |
|
55 |
throw new TypeError(edge.toString() + ' is not an instance of Edge'); |
|
56 |
} |
|
57 |
|
|
58 |
edge.start = this.position; |
|
59 |
|
|
60 |
this._outEdgeList.push(edge); |
|
61 |
} |
|
62 |
|
|
63 |
/** |
|
64 |
* @returns {array<Edge>} Array of edges going to the proxy. |
|
65 |
*/ |
|
66 |
get inEdgeList() { |
|
67 |
return this._inEdgeList; |
|
68 |
} |
|
69 |
|
|
70 |
/** |
|
71 |
* @returns {array<Edge>} Array of edges going from this proxy. |
|
72 |
*/ |
|
73 |
get outEdgeList() { |
|
74 |
return this._outEdgeList; |
|
75 |
} |
|
76 |
|
|
77 |
/** |
|
78 |
* @returns {Coordinates} Current position of this proxy. |
|
79 |
*/ |
|
80 |
get position() { |
|
81 |
return this._position; |
|
82 |
} |
|
83 |
|
|
84 |
/** |
|
85 |
* Updates the current position of vertices related to this proxy. |
|
86 |
*/ |
|
87 |
updatePosition() { |
|
88 |
let bbox = this._rootElement.getBoundingClientRect(); |
|
89 |
let viewportPosition = app.viewportComponent.getPosition(); |
|
90 |
|
|
91 |
this._position.x = (bbox.left - viewportPosition.x); |
|
92 |
this._position.y = (bbox.top - viewportPosition.y - app.headerComponent.height - app.navbarComponent.height); |
|
93 |
|
|
94 |
let edgeOffsetY; |
|
95 |
if (this._node instanceof Vertex) { |
|
96 |
edgeOffsetY = 10; |
|
97 |
} else if (this._node instanceof Group) { |
|
98 |
edgeOffsetY = 35; |
|
99 |
} else { |
|
100 |
edgeOffsetY = 0; |
|
101 |
} |
|
102 |
|
|
103 |
let archetypeList = Object.keys(this._node.relatedArchetypeMap).map(archetypeIndex => parseInt(archetypeIndex)); |
|
104 |
let archetypeIconOrder; |
|
105 |
|
|
106 |
// redraw dependent edges |
|
107 |
let inEdgeList = this.inEdgeList; |
|
108 |
inEdgeList.forEach(edge => { |
|
109 |
archetypeIconOrder = archetypeList.indexOf(edge.from.archetype); |
|
110 |
|
|
111 |
edge.end = new Coordinates( |
|
112 |
this._position.x / app.zoom.scale, |
|
113 |
(this._position.y + edgeOffsetY + archetypeIconOrder * 20) / app.zoom.scale, |
|
114 |
); |
|
115 |
}); |
|
116 |
|
|
117 |
let outEdgeList = this.outEdgeList; |
|
118 |
outEdgeList.forEach(edge => { |
|
119 |
archetypeIconOrder = archetypeList.indexOf(edge.to.archetype); |
|
120 |
|
|
121 |
edge.start = new Coordinates( |
|
122 |
this._position.x / app.zoom.scale, |
|
123 |
(this._position.y + edgeOffsetY + archetypeIconOrder * 20) / app.zoom.scale, |
|
124 |
); |
|
125 |
}); |
|
126 |
} |
|
127 |
|
|
128 |
/** |
|
129 |
* @returns {Coordinates} Centre of this proxy. |
|
130 |
*/ |
|
131 |
get center() { |
|
132 |
return this._position; |
|
133 |
} |
|
134 |
|
|
135 |
/** |
|
136 |
* Always returns false as proxies may never be excluded. It is here for NodeProxy to be compatible with API of Node. |
|
137 |
* @see Node |
|
138 |
* @returns {boolean} Always false. |
|
139 |
*/ |
|
140 |
get isExcluded() { |
|
141 |
return false; |
|
142 |
} |
|
143 |
|
|
144 |
/** |
|
145 |
* Does nothing as proxies may never be dimmed. It is here for NodeProxy to be compatible with API of Node. |
|
146 |
* @see Node |
|
147 |
* @param {boolean} newValue Anything. |
|
148 |
*/ |
|
149 |
set isDimmed(newValue) { |
|
150 |
// do nothing |
|
151 |
} |
|
152 |
|
|
153 |
/** |
|
154 |
* Toggles highlighting of the depedent node. |
|
155 |
* @param {boolean} newValue True to highlight the node as required, otherwise false. |
|
156 |
*/ |
|
157 |
set isHighlightedAsRequired(newValue) { |
|
158 |
this._node.isHighlightedAsRequired = newValue; |
|
159 |
} |
|
160 |
|
|
161 |
/** |
|
162 |
* Toggles highlighting of the depedent node. |
|
163 |
* @param {boolean} newValue True to highlight the node as provided, otherwise false. |
|
164 |
*/ |
|
165 |
set isHighlightedAsProvided(newValue) { |
|
166 |
this._node.isHighlightedAsProvided = newValue; |
|
167 |
} |
|
168 |
} |
sources/src/main/webapp/js/components/sidebar.js | ||
---|---|---|
21 | 21 |
|
22 | 22 |
this.refreshFloaters = function() { |
23 | 23 |
floaterList.forEach(floater => { |
24 |
floater.setPosition();
|
|
24 |
floater.updatePosition();
|
|
25 | 25 |
}); |
26 | 26 |
}; |
27 | 27 |
|
sources/src/main/webapp/js/components/vertex.js | ||
---|---|---|
364 | 364 |
]); |
365 | 365 |
|
366 | 366 |
// set floater element |
367 |
this._proxy.setElement(this._rootElement);
|
|
367 |
this._proxy.element = this._rootElement;
|
|
368 | 368 |
|
369 | 369 |
// set edges' ends |
370 | 370 |
let inEdgeList = this.inEdgeList; |
sources/src/main/webapp/showGraph.jsp | ||
---|---|---|
38 | 38 |
<script src="js/components/generic/popover.js"></script> |
39 | 39 |
<script src="js/components/generic/popup.js"></script> |
40 | 40 |
<script src="js/components/node.js"></script> |
41 |
<script src="js/components/nodeProxy.js"></script> |
|
41 | 42 |
<script src="js/components/attribute.js"></script> |
42 | 43 |
<script src="js/components/edge.js"></script> |
43 | 44 |
<script src="js/components/edgePopover.js"></script> |
44 |
<script src="js/components/floatingPoint.js"></script> |
|
45 | 45 |
<script src="js/components/group.js"></script> |
46 | 46 |
<script src="js/components/groupVertexList.js"></script> |
47 | 47 |
<script src="js/components/header.js"></script> |
Také k dispozici: Unified diff
reworked FloatingPoint to ES6 class NodeProxy