Projekt

Obecné

Profil

« Předchozí | Další » 

Revize bda189f9

Přidáno uživatelem Pavel Fidranský před více než 6 roky(ů)

organized JS files into directories

Zobrazit rozdíly:

sources/src/main/webapp/js/coordinates.js
1
/**
2
 * Class representing a coordinates pair.
3
 * @constructor
4
 * @param {float} x X coordinate.
5
 * @param {float} y Y coordinate.
6
 */
7
function Coordinates(x, y) {
8
	/** @prop {float} x X coordinate. */
9
	this.x = x;
10
	/** @prop {float} y Y coordinate. */
11
	this.y = y;
12
}
sources/src/main/webapp/js/diagram.js
1
/**
2
 * Class representing a saved diagram.
3
 * @constructor
4
 * @param {object} props Properties of the diagram.
5
 */
6
function Diagram(props) {
7
	/** @prop {int} id Identifier of the diagram. */
8
	this.id = parseInt(props.id);
9
	/** @prop {string} name Name of the diagram. */
10
	this.name = props.name;
11
	/** @prop {bool} public True if the diagram is public, otherwise false. */
12
	this.public = props.public === '1';
13
}
sources/src/main/webapp/js/forceDirected.js
1
/**
2
 * @constructor
3
 */
4
function ForceDirected() {
5

  
6
	var forceField = {};
7
	var canvas = 0;
8

  
9
	// parametry layoutu
10
	var inumber = 30; // pocet iteraci; default 300
11
	var inumberClick = 20; // pocet iteraci u tlacitka
12
	var repulsiveStrength = 400; // odpudiva sila (prima umera); default 450
13
	var attractiveStrength = 510; // pritazliva sila (neprima umera, nesmi byt 0); default 110
14
	var dampeningEffect = 1000; // tlumeni sily (nesmi byt 0); default 200
15
	var borderRatio = 1; // hranice layoutu (cislo kterym se deli velikost canvasu)
16
	// tahle funkce se mi nelibi, je treba to vyresit jinak, nici to layout (nechat na 1)
17

  
18
	/**
19
	 * Force directed layout for visible components.
20
	 */
21
	this.run = function() {
22
		var border = canvas / borderRatio;
23

  
24
		var visibleNodes = app.viewportComponent.getNodeList(),
25
			otherVisibleNodes = [];
26

  
27
		var i = 0,
28
			j = 0;
29

  
30
		for (i = 0; i < visibleNodes.length; i++) {
31
			forceField[Utils.getUniqueId(visibleNodes[i])] = [0, 0];
32
		}
33

  
34
		// calculate repulsive force
35
		for (i = 0; i < visibleNodes.length; i++) {
36
			var currNode = visibleNodes[i];
37

  
38
			// other nodes
39
			for (var j = 0; j < visibleNodes.length; j++){
40
				otherVisibleNodes[j] = visibleNodes[j];
41
			}
42
			otherVisibleNodes.splice(i, 1);
43

  
44
			// iterate over other nodes
45
			for (j = 0; j < otherVisibleNodes.length; j++) {
46
				var otherNode = otherVisibleNodes[j];
47

  
48
				var currPosition = currNode.getPosition();
49
				var otherPosition = otherNode.getPosition();
50

  
51
				// calculate force
52
				var x = currPosition.x - otherPosition.x;
53
				var y = currPosition.y - otherPosition.y;
54
				
55
				var sum = Math.pow(x, 2) + Math.pow(y, 2);
56
				var distance = Math.sqrt(sum);
57

  
58
				if (distance !== 0) {
59
					forceField[Utils.getUniqueId(currNode)][0] += Math.floor(x * (repulsiveStrength / distance));
60
					forceField[Utils.getUniqueId(currNode)][1] += Math.floor(y * (repulsiveStrength / distance));
61
				}
62
			}
63
		}
64

  
65
		// calculate attractive forces
66
		for (i = 0; i < visibleNodes.length; i++){
67
			var currNode = visibleNodes[i];
68

  
69
			for (j = 0; j < currNode.getInEdgeList().length; j++) {
70
				var otherNode = currNode.getInEdgeList()[j].getFrom();
71

  
72
				var currPosition = currNode.getPosition();
73
				var otherPosition = otherNode.getPosition();
74

  
75
				// calculate force
76
				var x = currPosition.x - otherPosition.x;
77
				var y = currPosition.y - otherPosition.y;
78

  
79
				var sum = Math.pow(x, 2) + Math.pow(y, 2);
80
				var distance = Math.sqrt(sum);
81

  
82
				forceField[Utils.getUniqueId(currNode)][0] += Math.round(-1 * x * (distance / attractiveStrength));
83
				forceField[Utils.getUniqueId(currNode)][1] += Math.round(-1 * y * (distance / attractiveStrength));
84
			}
85

  
86
			for (j = 0; j < currNode.getOutEdgeList().length; j++) {
87
				var otherNode = currNode.getOutEdgeList()[j].getTo();
88

  
89
				var currPosition = currNode.getPosition();
90
				var otherPosition = otherNode.getPosition();
91

  
92
				// calculate force
93
				var x = currPosition.x - otherPosition.x;
94
				var y = currPosition.y - otherPosition.y;
95

  
96
				var sum = Math.pow(x, 2) + Math.pow(y, 2);
97
				var distance = Math.sqrt(sum);
98

  
99
				forceField[Utils.getUniqueId(currNode)][0] += Math.round(-1 * x * (distance / attractiveStrength));
100
				forceField[Utils.getUniqueId(currNode)][1] += Math.round(-1 * y * (distance / attractiveStrength));
101
			}
102
		}
103

  
104
		// applying the force
105
		for (i = 0; i < visibleNodes.length; i++){
106
			var currNode = visibleNodes[i],
107

  
108
				halfCan = canvas / 2,
109

  
110
				deltaX = currNode.getPosition().x - halfCan,
111
				deltaY = currNode.getPosition().y - halfCan;
112

  
113
			// tohle drzi layout uprostred, chtelo by to vymyslet nejak lip, docela ho to kurvi
114
			/*
115
			 if (deltaX > 0) {
116
			 currNode.x = Math.min(currNode.getPosition().x, (canvas/2)+border);
117
			 } else {
118
			 currNode.x = Math.max(currNode.getPosition().x, (canvas/2)-border);
119
			 }
120
			 if (deltaY > 0) {
121
			 currNode.y = Math.min(currNode.getPosition().y, (canvas/2)+border);
122
			 } else {
123
			 currNode.y = Math.max(currNode.getPosition().y, (canvas/2)-border);
124
			 }
125
			 */
126

  
127
			// kolecko
128
			var dist = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, +2)),
129
				maxDist = Math.sqrt(Math.pow(border, 2) + Math.pow(border, +2));
130

  
131
			if (dist > maxDist){
132
				var ratio = maxDist / dist,
133

  
134
					newX = deltaX * ratio,
135
					newY = deltaY * ratio;
136

  
137
				currNode.x += newX - deltaX;
138
				currNode.y += newY - deltaY;
139
			}
140

  
141
			// force dampening
142
			var forceX = Math.floor(forceField[Utils.getUniqueId(currNode)][0] / dampeningEffect),
143
				forceY = Math.floor(forceField[Utils.getUniqueId(currNode)][1] / dampeningEffect);
144

  
145
			// adding a random effect
146
			/*
147
			 forceX += -3+Math.floor((Math.random()*6)+1);
148
			 forceY += -3+Math.floor((Math.random()*6)+1);
149
			 */
150

  
151

  
152
			// moving a component
153
			if (Math.abs(forceX) > 1 || Math.abs(forceY) > 1) {
154
				var coords = new Coordinates(
155
					currNode.getPosition().x + forceX,
156
					currNode.getPosition().y + forceY,
157
				);
158

  
159
				currNode.setPosition(coords);
160
				currNode.move(coords);
161
			}
162
		}
163
	};
164
}
sources/src/main/webapp/js/graphExporter.js
1
/**
2
 * @constructor
3
 */
4
function GraphExporter() {
5

  
6
	/**
7
	 * Exports graph to JSON.
8
	 */
9
	this.run = function() {
10
		// vertices
11
		var vertices = app.vertexList.map(function(vertex) {
12
			return vertex.export();
13
		});
14

  
15
		// edges
16
		var edges = app.edgeList.map(function(edge) {
17
			return edge.export();
18
		});
19

  
20
		// groups
21
		var groups = app.groupList.map(function(group) {
22
			return group.export();
23
		});
24

  
25
		// nodes excluded to the sidebar
26
		var excludedNodeList = app.sidebarComponent.excludedNodeListComponent.getNodeList();
27
		var sideBar = excludedNodeList.map(function(node) {
28
			return {
29
				id: Utils.getUniqueId(node),
30
                isIconsDisplayed: node.isIconsDisplayed(),
31
			};
32
		});
33

  
34
        var highlightedEdge = app.edgeList.find(function (edge) {
35
            return edge.isHighlighted()
36
        });
37

  
38
        // when edge is highlighted another vertex can not be highlighted
39
        if (Utils.isUndefined(highlightedEdge)) {
40
            var highlightedVertex = app.nodeList.find(function (vertex) {
41
                return vertex.isHighlighted()
42
            });
43
        }
44

  
45
		return {
46
			attributeTypes: app.attributeTypeList,
47
			edgeArchetypes: app.archetype.edge,
48
			vertexArchetypes: app.archetype.vertex,
49
			vertices: vertices,
50
			edges: edges,
51
			possibleEnumValues: app.possibleEnumValues,
52
			groups: groups,
53
			sideBar: sideBar,
54
            highlightedVertex: Utils.getUniqueId(highlightedVertex),
55
			highlightedEdge: Utils.isUndefined(highlightedEdge) ? '' : highlightedEdge.id,
56
		};
57
	}
58

  
59
}
sources/src/main/webapp/js/graphLoader.js
1
/**
2
 * @constructor
3
 */
4
function GraphLoader() {
5

  
6
	/**
7
	 * Loads a new graph using graph data passed as parameters.
8
	 * @param {object} data Data of the graph.
9
	 * @throws {InvalidArgumentError} Thrown when either graph data are incomplete.
10
	 */
11
	this.run  = function(data) {
12
		if (Utils.isUndefined(data.vertices) || Utils.isUndefined(data.edges)) {
13
			throw new InvalidArgumentError('Invalid data.');
14
		}
15

  
16
		var canvasSize = ((data.vertices.length * 75) / Math.round(Math.sqrt(data.vertices.length))) + 1000;
17

  
18
		// store archetypes
19
		app.archetype.vertex = data.vertexArchetypes;
20
		app.archetype.edge = data.edgeArchetypes;
21

  
22
		app.attributeTypeList = data.attributeTypes;
23
		app.possibleEnumValues = data.possibleEnumValues;
24

  
25
		app.archetype.vertex.filter(function(vertexArchetype) {
26
			return Utils.isDefined(vertexArchetype.icon);
27
		}).forEach(function(vertexArchetype) {
28
			app.viewportComponent.addSvgDefinition('vertexArchetypeIcon-' + vertexArchetype.name, vertexArchetype.icon);
29
		});
30

  
31
        var highlightedNodeId;
32
        var highlightedNodeType;
33
        if (Utils.isDefined(data.highlightedVertex) && data.highlightedVertex.length > 0) {
34
            var highlightedNodeAttr = data.highlightedVertex.split("-");
35
            if (highlightedNodeAttr.length === 2) {
36
                highlightedNodeType = highlightedNodeAttr[0];
37
                highlightedNodeId = parseInt(highlightedNodeAttr[1], 10);
38
            }
39
        }
40
        if (Utils.isDefined(data.highlightedEdge) && data.highlightedEdge.length > 0) {
41
            var highlightedEdgeId = parseInt(data.highlightedEdge, 10);
42
        }
43

  
44
        var highlightedNode = undefined;
45
        var highlightedEdge = undefined;
46

  
47
        // construct vertices
48
		var vertexMap = {};
49
		data.vertices.forEach(function(component) {
50
			var vertex = new Vertex(component);
51

  
52
			if (highlightedNodeType === 'vertex' && highlightedNodeId === vertex.id ){
53
                highlightedNode = vertex;
54
			}
55

  
56
			var position = component.position;
57

  
58
			if (position === null || Utils.isUndefined(position)) {
59
                // set random
60
                vertex.setPosition(new Coordinates(
61
                    Math.floor(Math.random() * canvasSize),
62
                    Math.floor(Math.random() * canvasSize),
63
                ));
64

  
65
            } else {
66
                vertex.setPosition(new Coordinates(position.x, position.y));
67
			}
68

  
69
			app.nodeList.push(vertex);
70
			app.vertexList.push(vertex);
71

  
72
			vertexMap[component.id] = vertex;
73
		});
74

  
75
		// construct edges
76
		data.edges.forEach(function(component) {
77
			var edge = new Edge(component);
78

  
79
            if (highlightedEdgeId === edge.id ){
80
                highlightedEdge = edge;
81
            }
82

  
83
			var fromNode = vertexMap[component.from];
84
			if (fromNode) {
85
				fromNode.addOutEdge(edge);
86
			}
87

  
88
			var toNode = vertexMap[component.to];
89
			if (toNode) {
90
				toNode.addInEdge(edge);
91
			}
92

  
93
			if (fromNode && toNode) {
94
				fromNode.incrementRelatedArchetype(toNode.archetype);
95
				toNode.incrementRelatedArchetype(fromNode.archetype);
96
			}
97

  
98
			app.edgeList.push(edge);
99
		});
100

  
101
		delete vertexMap;
102

  
103
		// render components
104
		app.vertexList.forEach(function(vertex) {
105
			app.viewportComponent.addVertex(vertex);
106
		});
107

  
108
		app.edgeList.forEach(function(edge) {
109
			app.viewportComponent.addEdge(edge);
110
		});
111

  
112
		// find unconnected vertices
113
		app.vertexList.filter(function(vertex) {
114
			return vertex.isUnconnected();
115
		}).forEach(function(vertex) {
116
			vertex.exclude();
117
			app.sidebarComponent.unconnectedNodeListComponent.add(vertex);
118
		});
119

  
120
		// construct groups
121
		data.groups.forEach(function(component) {
122
			var group = new Group(component);
123

  
124
			if (highlightedNodeType === 'group' && highlightedNodeId === group.id ){
125
                highlightedNode = group;
126
            }
127

  
128
			// position
129
			var position = component.position;
130
			if (position === null || Utils.isUndefined(position)) {
131
                // set random
132
                group.setPosition(new Coordinates(
133
                    Math.floor(Math.random() * canvasSize),
134
                    Math.floor(Math.random() * canvasSize),
135
                ));
136

  
137
            } else {
138
                group.setPosition(new Coordinates(position.x, position.y));
139
            }
140

  
141
			// vertices
142
			app.vertexList.filter(function(vertex) {
143
				return component.verticesId.indexOf(vertex.id) > -1;
144
			}).forEach(function(vertex) {
145
				group.addVertex(vertex);
146
			});
147

  
148
			app.nodeList.push(group);
149
			app.groupList.push(group);
150

  
151
			app.viewportComponent.addGroup(group);
152
		});
153

  
154
		// exclude nodes
155
		data.sideBar.forEach(function(excludedNode) {
156
            if(typeof excludedNode.id !== 'string' && !(excludedNode.id instanceof String)) {
157
            	return;
158
            }
159
            var idArr = excludedNode.id.split("-");
160
            if(idArr.length !== 2){
161
				return;
162
            }
163
            idArr[1] = parseInt(idArr[1], 10);
164

  
165
			var node = app.nodeList.find(function(node) {
166
				var prefix = '';
167
				if (node instanceof Vertex) {
168
					prefix = 'vertex';
169
				} else if (node instanceof Group) {
170
					prefix = 'group';
171
				}
172
				return idArr[0] === prefix && node.id === idArr[1];
173
			});
174

  
175
			if (Utils.isDefined(node)) {
176
				node.exclude(excludedNode.isIconsDisplayed);
177

  
178
				app.sidebarComponent.excludedNodeListComponent.add(node);
179
			}
180
		});
181

  
182
		// center viewport
183
		app.viewportComponent.center();
184

  
185
		// update status bar
186
		app.sidebarComponent.statusBarComponent.setComponentCount(data.vertices.length);
187

  
188
		if (Utils.isDefined(highlightedEdge)) {
189
            highlightedEdge.setHighlighted(true);
190
            highlightedEdge.getFrom().setHighlighted(true);
191
            highlightedEdge.getTo().setHighlighted(true);
192
        }
193
		if (Utils.isDefined(highlightedNode)) highlightedNode.setHighlightedWithNeighbours(true);
194
	};
195

  
196
}
sources/src/main/webapp/js/loader.js
1
/**
2
 * Loader animation displayed when running some expensive operation.
3
 * 
4
 * @constructor
5
 * @param {object} options 
6
 */
7
function Loader(options) {
8
	var defaultOptions = {
9
		lines: 16, // The number of lines to draw
10
		length: 21, // The length of each line
11
		width: 8, // The line thickness
12
		radius: 40, // The radius of the inner circle
13
		rotate: 0, // The rotation offset
14
		color: '#000', // #rgb or #rrggbb
15
		speed: 1.2, // Rounds per second
16
		trail: 58, // Afterglow percentage
17
		shadow: true, // Whether to render a shadow
18
		hwaccel: true, // Whether to use hardware acceleration
19
		className: 'loader-spinner', // The CSS class to assign to the spinner
20
		zIndex: 2, // The z-index (defaults to 2000000000)
21
	};
22

  
23
	var opts = $.extend(defaultOptions, options);
24

  
25
	/**
26
	 * Spin jQuery plugin.
27
	 */
28
	$.fn.spin = function(opts) {
29
		this.each(function() {
30
			var $this = $(this),
31
			data = $this.data();
32
			
33
			if (data.spinner) {
34
				data.spinner.stop();
35
				delete data.spinner;
36
			}
37

  
38
			if (opts !== false) {
39
				data.spinner = new Spinner($.extend({
40
					color: $this.css('color')
41
				}, opts)).spin(this);
42
			}
43
		});
44
		return this;
45
	};
46

  
47
	/**
48
	* Enables loader.
49
	*/
50
	this.enable = function() {
51
		$('#loader').show();
52
		$('#spinLoader').spin(opts);
53
	};
54

  
55
	/**
56
	* Disables loader.
57
	*/
58
	this.disable = function() {
59
		$('#loader').hide();
60
		$('#spinLoader').spin(false);
61
	};
62
}
sources/src/main/webapp/js/services/forceDirected.js
1
/**
2
 * @constructor
3
 */
4
function ForceDirected() {
5

  
6
	var forceField = {};
7
	var canvas = 0;
8

  
9
	// parametry layoutu
10
	var inumber = 30; // pocet iteraci; default 300
11
	var inumberClick = 20; // pocet iteraci u tlacitka
12
	var repulsiveStrength = 400; // odpudiva sila (prima umera); default 450
13
	var attractiveStrength = 510; // pritazliva sila (neprima umera, nesmi byt 0); default 110
14
	var dampeningEffect = 1000; // tlumeni sily (nesmi byt 0); default 200
15
	var borderRatio = 1; // hranice layoutu (cislo kterym se deli velikost canvasu)
16
	// tahle funkce se mi nelibi, je treba to vyresit jinak, nici to layout (nechat na 1)
17

  
18
	/**
19
	 * Force directed layout for visible components.
20
	 */
21
	this.run = function() {
22
		var border = canvas / borderRatio;
23

  
24
		var visibleNodes = app.viewportComponent.getNodeList(),
25
			otherVisibleNodes = [];
26

  
27
		var i = 0,
28
			j = 0;
29

  
30
		for (i = 0; i < visibleNodes.length; i++) {
31
			forceField[Utils.getUniqueId(visibleNodes[i])] = [0, 0];
32
		}
33

  
34
		// calculate repulsive force
35
		for (i = 0; i < visibleNodes.length; i++) {
36
			var currNode = visibleNodes[i];
37

  
38
			// other nodes
39
			for (var j = 0; j < visibleNodes.length; j++){
40
				otherVisibleNodes[j] = visibleNodes[j];
41
			}
42
			otherVisibleNodes.splice(i, 1);
43

  
44
			// iterate over other nodes
45
			for (j = 0; j < otherVisibleNodes.length; j++) {
46
				var otherNode = otherVisibleNodes[j];
47

  
48
				var currPosition = currNode.getPosition();
49
				var otherPosition = otherNode.getPosition();
50

  
51
				// calculate force
52
				var x = currPosition.x - otherPosition.x;
53
				var y = currPosition.y - otherPosition.y;
54
				
55
				var sum = Math.pow(x, 2) + Math.pow(y, 2);
56
				var distance = Math.sqrt(sum);
57

  
58
				if (distance !== 0) {
59
					forceField[Utils.getUniqueId(currNode)][0] += Math.floor(x * (repulsiveStrength / distance));
60
					forceField[Utils.getUniqueId(currNode)][1] += Math.floor(y * (repulsiveStrength / distance));
61
				}
62
			}
63
		}
64

  
65
		// calculate attractive forces
66
		for (i = 0; i < visibleNodes.length; i++){
67
			var currNode = visibleNodes[i];
68

  
69
			for (j = 0; j < currNode.getInEdgeList().length; j++) {
70
				var otherNode = currNode.getInEdgeList()[j].getFrom();
71

  
72
				var currPosition = currNode.getPosition();
73
				var otherPosition = otherNode.getPosition();
74

  
75
				// calculate force
76
				var x = currPosition.x - otherPosition.x;
77
				var y = currPosition.y - otherPosition.y;
78

  
79
				var sum = Math.pow(x, 2) + Math.pow(y, 2);
80
				var distance = Math.sqrt(sum);
81

  
82
				forceField[Utils.getUniqueId(currNode)][0] += Math.round(-1 * x * (distance / attractiveStrength));
83
				forceField[Utils.getUniqueId(currNode)][1] += Math.round(-1 * y * (distance / attractiveStrength));
84
			}
85

  
86
			for (j = 0; j < currNode.getOutEdgeList().length; j++) {
87
				var otherNode = currNode.getOutEdgeList()[j].getTo();
88

  
89
				var currPosition = currNode.getPosition();
90
				var otherPosition = otherNode.getPosition();
91

  
92
				// calculate force
93
				var x = currPosition.x - otherPosition.x;
94
				var y = currPosition.y - otherPosition.y;
95

  
96
				var sum = Math.pow(x, 2) + Math.pow(y, 2);
97
				var distance = Math.sqrt(sum);
98

  
99
				forceField[Utils.getUniqueId(currNode)][0] += Math.round(-1 * x * (distance / attractiveStrength));
100
				forceField[Utils.getUniqueId(currNode)][1] += Math.round(-1 * y * (distance / attractiveStrength));
101
			}
102
		}
103

  
104
		// applying the force
105
		for (i = 0; i < visibleNodes.length; i++){
106
			var currNode = visibleNodes[i],
107

  
108
				halfCan = canvas / 2,
109

  
110
				deltaX = currNode.getPosition().x - halfCan,
111
				deltaY = currNode.getPosition().y - halfCan;
112

  
113
			// tohle drzi layout uprostred, chtelo by to vymyslet nejak lip, docela ho to kurvi
114
			/*
115
			 if (deltaX > 0) {
116
			 currNode.x = Math.min(currNode.getPosition().x, (canvas/2)+border);
117
			 } else {
118
			 currNode.x = Math.max(currNode.getPosition().x, (canvas/2)-border);
119
			 }
120
			 if (deltaY > 0) {
121
			 currNode.y = Math.min(currNode.getPosition().y, (canvas/2)+border);
122
			 } else {
123
			 currNode.y = Math.max(currNode.getPosition().y, (canvas/2)-border);
124
			 }
125
			 */
126

  
127
			// kolecko
128
			var dist = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, +2)),
129
				maxDist = Math.sqrt(Math.pow(border, 2) + Math.pow(border, +2));
130

  
131
			if (dist > maxDist){
132
				var ratio = maxDist / dist,
133

  
134
					newX = deltaX * ratio,
135
					newY = deltaY * ratio;
136

  
137
				currNode.x += newX - deltaX;
138
				currNode.y += newY - deltaY;
139
			}
140

  
141
			// force dampening
142
			var forceX = Math.floor(forceField[Utils.getUniqueId(currNode)][0] / dampeningEffect),
143
				forceY = Math.floor(forceField[Utils.getUniqueId(currNode)][1] / dampeningEffect);
144

  
145
			// adding a random effect
146
			/*
147
			 forceX += -3+Math.floor((Math.random()*6)+1);
148
			 forceY += -3+Math.floor((Math.random()*6)+1);
149
			 */
150

  
151

  
152
			// moving a component
153
			if (Math.abs(forceX) > 1 || Math.abs(forceY) > 1) {
154
				var coords = new Coordinates(
155
					currNode.getPosition().x + forceX,
156
					currNode.getPosition().y + forceY,
157
				);
158

  
159
				currNode.setPosition(coords);
160
				currNode.move(coords);
161
			}
162
		}
163
	};
164
}
sources/src/main/webapp/js/services/graphExporter.js
1
/**
2
 * @constructor
3
 */
4
function GraphExporter() {
5

  
6
	/**
7
	 * Exports graph to JSON.
8
	 */
9
	this.run = function() {
10
		// vertices
11
		var vertices = app.vertexList.map(function(vertex) {
12
			return vertex.export();
13
		});
14

  
15
		// edges
16
		var edges = app.edgeList.map(function(edge) {
17
			return edge.export();
18
		});
19

  
20
		// groups
21
		var groups = app.groupList.map(function(group) {
22
			return group.export();
23
		});
24

  
25
		// nodes excluded to the sidebar
26
		var excludedNodeList = app.sidebarComponent.excludedNodeListComponent.getNodeList();
27
		var sideBar = excludedNodeList.map(function(node) {
28
			return {
29
				id: Utils.getUniqueId(node),
30
                isIconsDisplayed: node.isIconsDisplayed(),
31
			};
32
		});
33

  
34
        var highlightedEdge = app.edgeList.find(function (edge) {
35
            return edge.isHighlighted()
36
        });
37

  
38
        // when edge is highlighted another vertex can not be highlighted
39
        if (Utils.isUndefined(highlightedEdge)) {
40
            var highlightedVertex = app.nodeList.find(function (vertex) {
41
                return vertex.isHighlighted()
42
            });
43
        }
44

  
45
		return {
46
			attributeTypes: app.attributeTypeList,
47
			edgeArchetypes: app.archetype.edge,
48
			vertexArchetypes: app.archetype.vertex,
49
			vertices: vertices,
50
			edges: edges,
51
			possibleEnumValues: app.possibleEnumValues,
52
			groups: groups,
53
			sideBar: sideBar,
54
            highlightedVertex: Utils.getUniqueId(highlightedVertex),
55
			highlightedEdge: Utils.isUndefined(highlightedEdge) ? '' : highlightedEdge.id,
56
		};
57
	}
58

  
59
}
sources/src/main/webapp/js/services/graphLoader.js
1
/**
2
 * @constructor
3
 */
4
function GraphLoader() {
5

  
6
	/**
7
	 * Loads a new graph using graph data passed as parameters.
8
	 * @param {object} data Data of the graph.
9
	 * @throws {InvalidArgumentError} Thrown when either graph data are incomplete.
10
	 */
11
	this.run  = function(data) {
12
		if (Utils.isUndefined(data.vertices) || Utils.isUndefined(data.edges)) {
13
			throw new InvalidArgumentError('Invalid data.');
14
		}
15

  
16
		var canvasSize = ((data.vertices.length * 75) / Math.round(Math.sqrt(data.vertices.length))) + 1000;
17

  
18
		// store archetypes
19
		app.archetype.vertex = data.vertexArchetypes;
20
		app.archetype.edge = data.edgeArchetypes;
21

  
22
		app.attributeTypeList = data.attributeTypes;
23
		app.possibleEnumValues = data.possibleEnumValues;
24

  
25
		app.archetype.vertex.filter(function(vertexArchetype) {
26
			return Utils.isDefined(vertexArchetype.icon);
27
		}).forEach(function(vertexArchetype) {
28
			app.viewportComponent.addSvgDefinition('vertexArchetypeIcon-' + vertexArchetype.name, vertexArchetype.icon);
29
		});
30

  
31
        var highlightedNodeId;
32
        var highlightedNodeType;
33
        if (Utils.isDefined(data.highlightedVertex) && data.highlightedVertex.length > 0) {
34
            var highlightedNodeAttr = data.highlightedVertex.split("-");
35
            if (highlightedNodeAttr.length === 2) {
36
                highlightedNodeType = highlightedNodeAttr[0];
37
                highlightedNodeId = parseInt(highlightedNodeAttr[1], 10);
38
            }
39
        }
40
        if (Utils.isDefined(data.highlightedEdge) && data.highlightedEdge.length > 0) {
41
            var highlightedEdgeId = parseInt(data.highlightedEdge, 10);
42
        }
43

  
44
        var highlightedNode = undefined;
45
        var highlightedEdge = undefined;
46

  
47
        // construct vertices
48
		var vertexMap = {};
49
		data.vertices.forEach(function(component) {
50
			var vertex = new Vertex(component);
51

  
52
			if (highlightedNodeType === 'vertex' && highlightedNodeId === vertex.id ){
53
                highlightedNode = vertex;
54
			}
55

  
56
			var position = component.position;
57

  
58
			if (position === null || Utils.isUndefined(position)) {
59
                // set random
60
                vertex.setPosition(new Coordinates(
61
                    Math.floor(Math.random() * canvasSize),
62
                    Math.floor(Math.random() * canvasSize),
63
                ));
64

  
65
            } else {
66
                vertex.setPosition(new Coordinates(position.x, position.y));
67
			}
68

  
69
			app.nodeList.push(vertex);
70
			app.vertexList.push(vertex);
71

  
72
			vertexMap[component.id] = vertex;
73
		});
74

  
75
		// construct edges
76
		data.edges.forEach(function(component) {
77
			var edge = new Edge(component);
78

  
79
            if (highlightedEdgeId === edge.id ){
80
                highlightedEdge = edge;
81
            }
82

  
83
			var fromNode = vertexMap[component.from];
84
			if (fromNode) {
85
				fromNode.addOutEdge(edge);
86
			}
87

  
88
			var toNode = vertexMap[component.to];
89
			if (toNode) {
90
				toNode.addInEdge(edge);
91
			}
92

  
93
			if (fromNode && toNode) {
94
				fromNode.incrementRelatedArchetype(toNode.archetype);
95
				toNode.incrementRelatedArchetype(fromNode.archetype);
96
			}
97

  
98
			app.edgeList.push(edge);
99
		});
100

  
101
		delete vertexMap;
102

  
103
		// render components
104
		app.vertexList.forEach(function(vertex) {
105
			app.viewportComponent.addVertex(vertex);
106
		});
107

  
108
		app.edgeList.forEach(function(edge) {
109
			app.viewportComponent.addEdge(edge);
110
		});
111

  
112
		// find unconnected vertices
113
		app.vertexList.filter(function(vertex) {
114
			return vertex.isUnconnected();
115
		}).forEach(function(vertex) {
116
			vertex.exclude();
117
			app.sidebarComponent.unconnectedNodeListComponent.add(vertex);
118
		});
119

  
120
		// construct groups
121
		data.groups.forEach(function(component) {
122
			var group = new Group(component);
123

  
124
			if (highlightedNodeType === 'group' && highlightedNodeId === group.id ){
125
                highlightedNode = group;
126
            }
127

  
128
			// position
129
			var position = component.position;
130
			if (position === null || Utils.isUndefined(position)) {
131
                // set random
132
                group.setPosition(new Coordinates(
133
                    Math.floor(Math.random() * canvasSize),
134
                    Math.floor(Math.random() * canvasSize),
135
                ));
136

  
137
            } else {
138
                group.setPosition(new Coordinates(position.x, position.y));
139
            }
140

  
141
			// vertices
142
			app.vertexList.filter(function(vertex) {
143
				return component.verticesId.indexOf(vertex.id) > -1;
144
			}).forEach(function(vertex) {
145
				group.addVertex(vertex);
146
			});
147

  
148
			app.nodeList.push(group);
149
			app.groupList.push(group);
150

  
151
			app.viewportComponent.addGroup(group);
152
		});
153

  
154
		// exclude nodes
155
		data.sideBar.forEach(function(excludedNode) {
156
            if(typeof excludedNode.id !== 'string' && !(excludedNode.id instanceof String)) {
157
            	return;
158
            }
159
            var idArr = excludedNode.id.split("-");
160
            if(idArr.length !== 2){
161
				return;
162
            }
163
            idArr[1] = parseInt(idArr[1], 10);
164

  
165
			var node = app.nodeList.find(function(node) {
166
				var prefix = '';
167
				if (node instanceof Vertex) {
168
					prefix = 'vertex';
169
				} else if (node instanceof Group) {
170
					prefix = 'group';
171
				}
172
				return idArr[0] === prefix && node.id === idArr[1];
173
			});
174

  
175
			if (Utils.isDefined(node)) {
176
				node.exclude(excludedNode.isIconsDisplayed);
177

  
178
				app.sidebarComponent.excludedNodeListComponent.add(node);
179
			}
180
		});
181

  
182
		// center viewport
183
		app.viewportComponent.center();
184

  
185
		// update status bar
186
		app.sidebarComponent.statusBarComponent.setComponentCount(data.vertices.length);
187

  
188
		if (Utils.isDefined(highlightedEdge)) {
189
            highlightedEdge.setHighlighted(true);
190
            highlightedEdge.getFrom().setHighlighted(true);
191
            highlightedEdge.getTo().setHighlighted(true);
192
        }
193
		if (Utils.isDefined(highlightedNode)) highlightedNode.setHighlightedWithNeighbours(true);
194
	};
195

  
196
}
sources/src/main/webapp/js/services/loader.js
1
/**
2
 * Loader animation displayed when running some expensive operation.
3
 * 
4
 * @constructor
5
 * @param {object} options 
6
 */
7
function Loader(options) {
8
	var defaultOptions = {
9
		lines: 16, // The number of lines to draw
10
		length: 21, // The length of each line
11
		width: 8, // The line thickness
12
		radius: 40, // The radius of the inner circle
13
		rotate: 0, // The rotation offset
14
		color: '#000', // #rgb or #rrggbb
15
		speed: 1.2, // Rounds per second
16
		trail: 58, // Afterglow percentage
17
		shadow: true, // Whether to render a shadow
18
		hwaccel: true, // Whether to use hardware acceleration
19
		className: 'loader-spinner', // The CSS class to assign to the spinner
20
		zIndex: 2, // The z-index (defaults to 2000000000)
21
	};
22

  
23
	var opts = $.extend(defaultOptions, options);
24

  
25
	/**
26
	 * Spin jQuery plugin.
27
	 */
28
	$.fn.spin = function(opts) {
29
		this.each(function() {
30
			var $this = $(this),
31
			data = $this.data();
32
			
33
			if (data.spinner) {
34
				data.spinner.stop();
35
				delete data.spinner;
36
			}
37

  
38
			if (opts !== false) {
39
				data.spinner = new Spinner($.extend({
40
					color: $this.css('color')
41
				}, opts)).spin(this);
42
			}
43
		});
44
		return this;
45
	};
46

  
47
	/**
48
	* Enables loader.
49
	*/
50
	this.enable = function() {
51
		$('#loader').show();
52
		$('#spinLoader').spin(opts);
53
	};
54

  
55
	/**
56
	* Disables loader.
57
	*/
58
	this.disable = function() {
59
		$('#loader').hide();
60
		$('#spinLoader').spin(false);
61
	};
62
}
sources/src/main/webapp/js/services/zoom.js
1
/**
2
 * @constructor
3
 * @param {float} defaultScale Default zoom scale.
4
 */
5
function Zoom(defaultScale) {
6
	/** @prop {float} scale Current zoom scale. */
7
	this.scale = defaultScale || 1;
8
	
9
	var steps = [ 0.1, 0.25, 0.4, 0.55, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.45, 1.6, 1.75, 1.9, 2.5, 3.5, 5 ];
10
	var step = steps.indexOf(this.scale);
11
	
12
	/**
13
	 * Zoom in. If the current scale is maximal, it does nothing.
14
	 */
15
	this.zoomIn = function() {
16
		if (step === steps.length - 1) return;
17

  
18
		if (step === 0) {
19
			document.querySelector('#zoomOut').classList.remove('disabled');
20
			document.querySelector('#zoomOut img').src = 'images/zoom_out.png';
21
		}
22

  
23
		step++;
24
		zoomChanged.call(this);
25

  
26
		if (step === steps.length - 1) {
27
			document.querySelector('#zoomIn').classList.add('disabled');
28
			document.querySelector('#zoomIn img').src = 'images/zoom_in_disabled.png';
29
		}
30
	};
31
	
32
	/**
33
	 * Zoom out. If the current scale is minimal, it does nothing.
34
	 */
35
	this.zoomOut = function() {
36
		if (step === 0) return;
37

  
38
		if (step === steps.length - 1) {
39
			document.querySelector('#zoomIn').classList.remove('disabled');
40
			document.querySelector('#zoomIn img').src = 'images/zoom_in.png';
41
		}
42

  
43
		step--;
44
		zoomChanged.call(this);
45

  
46
		if (step === 0) {
47
			document.querySelector('#zoomOut').classList.add('disabled');
48
			document.querySelector('#zoomOut img').src = 'images/zoom_out_disabled.png';
49
		}
50
	};
51
	
52
	/**
53
	 * Change current zoom scale according to currently selected step.
54
	 */
55
	function zoomChanged() {
56
		this.scale = steps[step];
57
		
58
		document.getElementById('zoomValue').innerText = Math.round(this.scale * 100) + '%';
59
		document.getElementById('graph').setAttribute('transform', 'scale(' + this.scale + ')');
60

  
61
		// TODO: zoom to mouse position / center
62
		
63
		app.redrawEdges();
64
	}
65
}
sources/src/main/webapp/js/valueObjects/coordinates.js
1
/**
2
 * Class representing a coordinates pair.
3
 * @constructor
4
 * @param {float} x X coordinate.
5
 * @param {float} y Y coordinate.
6
 */
7
function Coordinates(x, y) {
8
	/** @prop {float} x X coordinate. */
9
	this.x = x;
10
	/** @prop {float} y Y coordinate. */
11
	this.y = y;
12
}
sources/src/main/webapp/js/valueObjects/diagram.js
1
/**
2
 * Class representing a saved diagram.
3
 * @constructor
4
 * @param {object} props Properties of the diagram.
5
 */
6
function Diagram(props) {
7
	/** @prop {int} id Identifier of the diagram. */
8
	this.id = parseInt(props.id);
9
	/** @prop {string} name Name of the diagram. */
10
	this.name = props.name;
11
	/** @prop {bool} public True if the diagram is public, otherwise false. */
12
	this.public = props.public === '1';
13
}
sources/src/main/webapp/js/zoom.js
1
/**
2
 * @constructor
3
 * @param {float} defaultScale Default zoom scale.
4
 */
5
function Zoom(defaultScale) {
6
	/** @prop {float} scale Current zoom scale. */
7
	this.scale = defaultScale || 1;
8
	
9
	var steps = [ 0.1, 0.25, 0.4, 0.55, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.45, 1.6, 1.75, 1.9, 2.5, 3.5, 5 ];
10
	var step = steps.indexOf(this.scale);
11
	
12
	/**
13
	 * Zoom in. If the current scale is maximal, it does nothing.
14
	 */
15
	this.zoomIn = function() {
16
		if (step === steps.length - 1) return;
17

  
18
		if (step === 0) {
19
			document.querySelector('#zoomOut').classList.remove('disabled');
20
			document.querySelector('#zoomOut img').src = 'images/zoom_out.png';
21
		}
22

  
23
		step++;
24
		zoomChanged.call(this);
25

  
26
		if (step === steps.length - 1) {
27
			document.querySelector('#zoomIn').classList.add('disabled');
28
			document.querySelector('#zoomIn img').src = 'images/zoom_in_disabled.png';
29
		}
30
	};
31
	
32
	/**
33
	 * Zoom out. If the current scale is minimal, it does nothing.
34
	 */
35
	this.zoomOut = function() {
36
		if (step === 0) return;
37

  
38
		if (step === steps.length - 1) {
39
			document.querySelector('#zoomIn').classList.remove('disabled');
40
			document.querySelector('#zoomIn img').src = 'images/zoom_in.png';
41
		}
42

  
43
		step--;
44
		zoomChanged.call(this);
45

  
46
		if (step === 0) {
47
			document.querySelector('#zoomOut').classList.add('disabled');
48
			document.querySelector('#zoomOut img').src = 'images/zoom_out_disabled.png';
49
		}
50
	};
51
	
52
	/**
53
	 * Change current zoom scale according to currently selected step.
54
	 */
55
	function zoomChanged() {
56
		this.scale = steps[step];
57
		
58
		document.getElementById('zoomValue').innerText = Math.round(this.scale * 100) + '%';
59
		document.getElementById('graph').setAttribute('transform', 'scale(' + this.scale + ')');
60

  
61
		// TODO: zoom to mouse position / center
62
		
63
		app.redrawEdges();
64
	}
65
}
sources/src/main/webapp/showGraph.jsp
41 41

  
42 42
		<script src="js/errors/invalidArgumentError.js"></script>
43 43

  
44
		<script src="js/constants.js"></script>
45
		<script src="js/coordinates.js"></script>
46
		<script src="js/diagram.js"></script>
47
		<script src="js/forceDirected.js"></script>
48
		<script src="js/graphLoader.js"></script>
49
		<script src="js/graphExporter.js"></script>
50
		<script src="js/loader.js"></script>
51
		<script src="js/markSymbol.js"></script>
44
		<script src="js/services/forceDirected.js"></script>
45
		<script src="js/services/graphLoader.js"></script>
46
		<script src="js/services/graphExporter.js"></script>
47
		<script src="js/services/loader.js"></script>
48
		<script src="js/services/zoom.js"></script>
49

  
52 50
		<script src="js/utils/cookies.js"></script>
53 51
		<script src="js/utils/dom.js"></script>
54 52
		<script src="js/utils/utils.js"></script>
55
		<script src="js/zoom.js"></script>
56
		<script src="js/app.js"></script>
53

  
54
		<script src="js/valueObjects/coordinates.js"></script>
55
		<script src="js/valueObjects/diagram.js"></script>
56

  
57 57
		<script src="js/userMenu.js"></script>
58
		<script src="js/markSymbol.js"></script>
59
		<script src="js/constants.js"></script>
60
		<script src="js/app.js"></script>
58 61

  
59 62
		<title>IMiGEr</title>
60 63
	</head>

Také k dispozici: Unified diff