1
|
/**
|
2
|
* Object responsible for handling SeCo panel.
|
3
|
*/
|
4
|
var OffScreenKiv = {
|
5
|
markSymbol: new MarkSymbol(),
|
6
|
vertexSearchHighlighting: {},
|
7
|
groupManager: new GroupManager(),
|
8
|
|
9
|
init: function(){
|
10
|
this.showVertexInRightPanel = this.showVertexInRightPanel.bind(this);
|
11
|
this.showVertexInGraph = this.showVertexInGraph.bind(this);
|
12
|
this.notHighlightNeighbour = this.notHighlightNeighbour.bind(this);
|
13
|
this.highlightAllNeighbour = this.highlightAllNeighbour.bind(this);
|
14
|
this.highlightProvidedEvent = this.highlightProvidedEvent.bind(this);
|
15
|
this.highlightRequiredEvent = this.highlightRequiredEvent.bind(this);
|
16
|
this.showVertexIcons = this.showVertexIcons.bind(this);
|
17
|
this.hideVertexIcons = this.hideVertexIcons.bind(this);
|
18
|
this.showGroupIcons = this.showGroupIcons.bind(this);
|
19
|
this.hideGroupIcons = this.hideGroupIcons.bind(this);
|
20
|
|
21
|
this.deleteItemFromGroupEvent = this.deleteItemFromGroupEvent.bind(this);
|
22
|
this.groupHighlightProvided = this.groupHighlightProvided.bind(this);
|
23
|
this.groupDisHighlightProvided = this.groupDisHighlightProvided.bind(this);
|
24
|
this.groupHighlightRequired = this.groupHighlightRequired.bind(this);
|
25
|
this.groupDisHighlightRequired = this.groupDisHighlightRequired.bind(this);
|
26
|
this.groupHighlightRequiredAndProvided = this.groupHighlightRequiredAndProvided.bind(this);
|
27
|
this.groupDisHighlightRequiredAndProvided = this.groupDisHighlightRequiredAndProvided.bind(this);
|
28
|
this.search = this.search.bind(this);
|
29
|
this.deselectHighlightSearchedVertices = this.deselectHighlightSearchedVertices.bind(this);
|
30
|
|
31
|
this.excludeVerticesWithMostEdges = this.excludeVerticesWithMostEdges.bind(this);
|
32
|
this.excludeVerticesWithMostEdgesToGroup = this.excludeVerticesWithMostEdgesToGroup.bind(this);
|
33
|
|
34
|
this.includeUnconItem = this.includeUnconItem.bind(this);
|
35
|
this.includeUncon = this.includeUncon.bind(this);
|
36
|
this.deleteUncon = this.deleteUncon.bind(this);
|
37
|
|
38
|
this.parseTransform = this.parseTransform.bind(this);
|
39
|
|
40
|
this.proposeChanges = this.proposeChanges.bind(this);
|
41
|
},
|
42
|
|
43
|
/**
|
44
|
* Includes the component with passed ID to the diagram area.
|
45
|
*
|
46
|
* @param id the component identifier
|
47
|
*/
|
48
|
includeUnconnectedComponent: function(id) {
|
49
|
var list = GraphManager.unconList;
|
50
|
var i = list.indexOf(id);
|
51
|
|
52
|
list.splice(i, 1);
|
53
|
|
54
|
$('#vertex'+ id)[0].classList.add('vertex--unconnected');
|
55
|
$('#vertex'+ id).show();
|
56
|
|
57
|
$('#liuc'+ id).hide();
|
58
|
},
|
59
|
|
60
|
/**
|
61
|
* Includes all unconnected components in the diagram area.
|
62
|
*/
|
63
|
includeUncon: function() {
|
64
|
var list = GraphManager.unconList;
|
65
|
|
66
|
// cancel highlight
|
67
|
ViewportManager.highlightVertex = null;
|
68
|
|
69
|
//ukaze v grafu a odstrani ze seznamu
|
70
|
for (var i = list.length-1; i >= 0; i--) {
|
71
|
this.includeUnconnectedComponent(list[i]);
|
72
|
}
|
73
|
},
|
74
|
|
75
|
/**
|
76
|
* Includes a single unconnected component in the diagram area.
|
77
|
*/
|
78
|
includeUnconItem: function(e) {
|
79
|
var vertexId = $(e.target.parentElement).data('id');
|
80
|
|
81
|
this.includeUnconnectedComponent(vertexId);
|
82
|
},
|
83
|
|
84
|
/**
|
85
|
* Removes unconnected components from the diagram area.
|
86
|
*/
|
87
|
deleteUncon: function() {
|
88
|
var list = GraphManager.unconList;
|
89
|
var vertices = GraphManager.graph.vertices;
|
90
|
|
91
|
// pridani nepropojenych do seznamu
|
92
|
for (var i = 0; i < vertices.length; i++) {
|
93
|
var vertex = vertices[i];
|
94
|
|
95
|
// test existence sousedu a viditelnosti
|
96
|
if (vertex.edges.length === 0 && $('#vertex'+ vertex.id)[0].isVisible()) {
|
97
|
var j = list.length;
|
98
|
list[j] = vertex.id;
|
99
|
}
|
100
|
}
|
101
|
|
102
|
// schova v grafu
|
103
|
for (var i = 0; i < list.length; i++){
|
104
|
$('#vertex'+ list[i]).hide();
|
105
|
$('#liuc'+ list[i]).show();
|
106
|
}
|
107
|
},
|
108
|
|
109
|
/**
|
110
|
* Sorts components excluded to SeCo.
|
111
|
*/
|
112
|
sortComponents: function(e) {
|
113
|
e.preventDefault();
|
114
|
|
115
|
var components;
|
116
|
switch ($(this).attr('id')) {
|
117
|
case 'sortComponents_name_asc':
|
118
|
components = $('#excludedComponents .component').sort(OffScreenKiv.sortByComponentName);
|
119
|
break;
|
120
|
case 'sortComponents_name_desc':
|
121
|
components = $('#excludedComponents .component').sort(OffScreenKiv.sortByComponentName).get().reverse();
|
122
|
break;
|
123
|
case 'sortComponents_count_asc':
|
124
|
components = $('#excludedComponents .component').sort(OffScreenKiv.sortByComponentCount);
|
125
|
break;
|
126
|
case 'sortComponents_count_desc':
|
127
|
components = $('#excludedComponents .component').sort(OffScreenKiv.sortByComponentCount).get().reverse();
|
128
|
break;
|
129
|
}
|
130
|
|
131
|
$('#excludedComponents').append(components);
|
132
|
|
133
|
$('.sort-button').removeClass('active');
|
134
|
$(this).addClass('active');
|
135
|
},
|
136
|
|
137
|
/**
|
138
|
* Perfoms the actual sorting by component name in ascending order.
|
139
|
*/
|
140
|
sortByComponentName: function(a, b) {
|
141
|
var $_a_item = $(a).find('g[id^="detailVertex"] text');
|
142
|
var $_b_item = $(b).find('g[id^="detailVertex"] text');
|
143
|
|
144
|
var a_item_text = '';
|
145
|
var b_item_text = '';
|
146
|
|
147
|
if ($_a_item.length > 0) {
|
148
|
a_item_text = $_a_item.text().toLowerCase();
|
149
|
} else {
|
150
|
a_item_text = $(a).find('ul li:first p').text().toLowerCase();
|
151
|
}
|
152
|
|
153
|
if ($_b_item.length > 0) {
|
154
|
b_item_text = $_b_item.text().toLowerCase();
|
155
|
} else {
|
156
|
b_item_text = $(b).find('ul li:first p').text().toLowerCase();
|
157
|
}
|
158
|
|
159
|
return a_item_text > b_item_text ? 1 : -1;
|
160
|
},
|
161
|
|
162
|
/**
|
163
|
* Perfoms the actual sorting by count of components in ascending order.
|
164
|
*/
|
165
|
sortByComponentCount: function(a, b) {
|
166
|
var $_a_item = $(a).find('g[id^="detailVertex"] text');
|
167
|
var $_b_item = $(b).find('g[id^="detailVertex"] text');
|
168
|
|
169
|
var a_count_comp = 1;
|
170
|
var b_count_comp = 1;
|
171
|
|
172
|
if ($_a_item.length > 0) {
|
173
|
a_count_comp = 1;
|
174
|
} else {
|
175
|
a_count_comp = $(a).find('ul li').length;
|
176
|
}
|
177
|
|
178
|
if ($_b_item.length > 0) {
|
179
|
b_count_comp = 1;
|
180
|
} else {
|
181
|
b_count_comp = $(b).find('ul li').length;
|
182
|
}
|
183
|
|
184
|
return a_count_comp > b_count_comp ? 1 : -1;
|
185
|
},
|
186
|
|
187
|
/**
|
188
|
* Includes all components in the graph.
|
189
|
*/
|
190
|
includeAllComponents: function(e){
|
191
|
e.preventDefault();
|
192
|
|
193
|
//show component in graph
|
194
|
$('#excludedComponents .component').each(function() {
|
195
|
if (this.classList.contains('vertex')) {
|
196
|
OffScreenKiv.showVertexInGraph(findId(this));
|
197
|
} else if (this.classList.contains('group_vertices')) {
|
198
|
OffScreenKiv.showGroupInGraph(findId(this));
|
199
|
}
|
200
|
});
|
201
|
|
202
|
$('#includeAllComponents').hide();
|
203
|
},
|
204
|
|
205
|
/**
|
206
|
* Hides include all components button if there are no components or groups displayed in SeCo.
|
207
|
*/
|
208
|
hideIncludeAllComponentsButton: function(){
|
209
|
if ($('#excludedComponents .component').length === 0) {
|
210
|
$('#includeAllComponents').hide();
|
211
|
}
|
212
|
},
|
213
|
|
214
|
/**
|
215
|
* This method ensures display icon at the vertex neighbors
|
216
|
*/
|
217
|
showIcons: function(vertex) {
|
218
|
for (var i = 0; i < vertex.edges.length; i++) {
|
219
|
var targetVertex = this.getEdgeOtherSide(vertex.edges[i], vertex);
|
220
|
// var markId = vertex.id + 'mark' + targetVertex.id;
|
221
|
var markId = 'mark' + vertex.symbol[0]+ vertex.symbol[1];
|
222
|
if (!targetVertex.gridMark.existMark(markId)) {
|
223
|
var mark = new Mark(vertex.symbol, markId, targetVertex.$selector);
|
224
|
targetVertex.gridMark.addMark(markId, mark);
|
225
|
}
|
226
|
}
|
227
|
},
|
228
|
|
229
|
/**
|
230
|
* This method ensures disappearance of icon at the vertex neighbors
|
231
|
*/
|
232
|
hideIcons: function(vertex){
|
233
|
for (var i = 0; i < vertex.edges.length; i++) {
|
234
|
var targetVertex = this.getEdgeOtherSide(vertex.edges[i], vertex);
|
235
|
var markId = 'mark' + vertex.symbol[0]+ vertex.symbol[1];
|
236
|
|
237
|
if (targetVertex.gridMark.existMark(markId)) {
|
238
|
targetVertex.gridMark.removeMark(markId);
|
239
|
}
|
240
|
}
|
241
|
},
|
242
|
|
243
|
/**
|
244
|
* Event calls action showIcons after click to given element.
|
245
|
* Parameters: e - event
|
246
|
*/
|
247
|
showVertexIcons: function(e) {
|
248
|
var id = findId(e.target);
|
249
|
var vertex = GraphManager.graph.vertices[id - 1];
|
250
|
var color = vertex.symbol[1];
|
251
|
var buttonElement = $(e.target);
|
252
|
|
253
|
this.showIcons(vertex);
|
254
|
|
255
|
buttonElement.attr('class', 'button c' + color.substring(1, color.length));
|
256
|
buttonElement.unbind('click');
|
257
|
buttonElement.click(this.hideVertexIcons);
|
258
|
},
|
259
|
|
260
|
/**
|
261
|
* Event calls action hideIcons after click to given element.
|
262
|
* Parameters: e - event
|
263
|
*/
|
264
|
hideVertexIcons: function(e) {
|
265
|
var id = findId(e.target);
|
266
|
var vertex = GraphManager.graph.vertices[id - 1];
|
267
|
var buttonElement = $(e.target);
|
268
|
|
269
|
this.hideIcons(vertex);
|
270
|
|
271
|
buttonElement.attr('class', 'button buttonClassic');
|
272
|
buttonElement.unbind('click');
|
273
|
buttonElement.click(this.showVertexIcons);
|
274
|
},
|
275
|
|
276
|
/**
|
277
|
* Event calls action showIcons after click to given element.
|
278
|
* It ensures to display icon at all vertex neighbors in group.
|
279
|
* Parameters: e - event
|
280
|
*/
|
281
|
showGroupIcons: function(e){
|
282
|
var idGroup = findId(e.target);
|
283
|
var group = this.groupManager.getGroup(idGroup);
|
284
|
var firstRun = true;
|
285
|
var symbol;
|
286
|
var buttonElement = $(e.target);
|
287
|
|
288
|
for (var key in group.items.getAll()) {
|
289
|
if (firstRun) {
|
290
|
symbol = group.items.get(key).symbol;
|
291
|
firstRun = false;
|
292
|
buttonElement.attr('class', "button c" + symbol[1].substring(1, symbol[1].length));
|
293
|
}
|
294
|
this.showIcons(group.items.get(key));
|
295
|
}
|
296
|
|
297
|
buttonElement.unbind('click', this.showGroupIcons);
|
298
|
buttonElement.click(this.hideGroupIcons);
|
299
|
},
|
300
|
|
301
|
/**
|
302
|
* Event calls action hideIcons after click to given element.
|
303
|
* It ensures to disappearance icon at all vertex neighbors in group.
|
304
|
* Parameters: e - event
|
305
|
*/
|
306
|
hideGroupIcons: function(e) {
|
307
|
var idGroup = findId(e.target);
|
308
|
var group = this.groupManager.getGroup(idGroup);
|
309
|
var buttonElement = $(e.target);
|
310
|
|
311
|
for (var key in group.items.getAll()) {
|
312
|
this.hideIcons(group.items.get(key));
|
313
|
}
|
314
|
|
315
|
buttonElement.attr('class', 'button buttonClassic');
|
316
|
buttonElement.unbind('click', this.hideGroupIcons);
|
317
|
buttonElement.click(this.showGroupIcons);
|
318
|
},
|
319
|
|
320
|
/**
|
321
|
*
|
322
|
* Detect and make opaque the unconnected vertices according to #1751. Detect while removing a vertex from diagram.
|
323
|
*
|
324
|
* @param vertex
|
325
|
*/
|
326
|
detectAndSetUnconnectedInGraph : function(vertex) {
|
327
|
for (var i = 0; i < vertex.edges.length; i++) {
|
328
|
var neighbour = null;
|
329
|
var adjacent = null;
|
330
|
|
331
|
var visibleAdjacentsCount = 0;
|
332
|
|
333
|
if (vertex.edges[i].from == vertex) {
|
334
|
neighbour = vertex.edges[i].to;
|
335
|
} else {
|
336
|
neighbour = vertex.edges[i].from;
|
337
|
}
|
338
|
|
339
|
var styleNeighbour = neighbour.$selector.attr('style');
|
340
|
|
341
|
if (!/display: none/.test(styleNeighbour)) {
|
342
|
for (var j = 0; j < neighbour.edges.length; j++) {
|
343
|
if (neighbour.edges[j].from == neighbour) {
|
344
|
adjacent = neighbour.edges[j].to;
|
345
|
} else {
|
346
|
adjacent = neighbour.edges[j].from;
|
347
|
}
|
348
|
|
349
|
// not count the edge to the vertex being removed
|
350
|
if (adjacent == vertex || adjacent == neighbour) {
|
351
|
continue;
|
352
|
}
|
353
|
|
354
|
var styleAdj = adjacent.$selector.attr('style');
|
355
|
|
356
|
if (/display: none/.test(styleAdj)) {
|
357
|
continue;
|
358
|
}
|
359
|
|
360
|
visibleAdjacentsCount++;
|
361
|
}
|
362
|
|
363
|
if (visibleAdjacentsCount === 0) {
|
364
|
neighbour.$selector[0].classList.add('vertex--unconnected');
|
365
|
neighbour.leftAlone = true;
|
366
|
}
|
367
|
}
|
368
|
}
|
369
|
},
|
370
|
|
371
|
/**
|
372
|
*
|
373
|
* Detect and make reset the opacity the previously unconnected vertices according to #1751. Detect while adding a vertex back to diagram.
|
374
|
*
|
375
|
* @param vertex
|
376
|
*/
|
377
|
detectAndResetReconnectedInGraph : function(vertex) {
|
378
|
var visibleAdjacentsCount = 0;
|
379
|
|
380
|
for (var i = 0; i < vertex.edges.length; i++) {
|
381
|
var neighbour = null;
|
382
|
|
383
|
if (vertex.edges[i].from == vertex) {
|
384
|
neighbour = vertex.edges[i].to;
|
385
|
} else {
|
386
|
neighbour = vertex.edges[i].from;
|
387
|
}
|
388
|
|
389
|
// set proper opacity
|
390
|
if (neighbour.leftAlone && !neighbour.excluded) {
|
391
|
// not greyed-out by highlighing
|
392
|
if (!neighbour.dimmed) {
|
393
|
neighbour.$selector[0].classList.remove('vertex--unconnected');
|
394
|
} else { // greyed-out by highlighting
|
395
|
neighbour.$selector[0].classList.add('vertex--dimmed');
|
396
|
}
|
397
|
|
398
|
neighbour.leftAlone = false;
|
399
|
}
|
400
|
|
401
|
// got a neighbour in graph
|
402
|
if (!neighbour.excluded) {
|
403
|
visibleAdjacentsCount++;
|
404
|
}
|
405
|
}
|
406
|
|
407
|
// make visible if got a neighbour
|
408
|
if (visibleAdjacentsCount > 0) {
|
409
|
if (!vertex.dimmed) {
|
410
|
vertex.$selector[0].classList.remove('vertex--unconnected');
|
411
|
} else {
|
412
|
vertex.$selector[0].classList.add('vertex--dimmed');
|
413
|
}
|
414
|
} else { // is alone after returning to graph
|
415
|
vertex.$selector[0].classList.add('vertex--unconnected');
|
416
|
vertex.leftAlone = true;
|
417
|
}
|
418
|
},
|
419
|
|
420
|
/**
|
421
|
* Counts dependencies of vertex with other vertices.
|
422
|
* Parameters: vertex - vertex
|
423
|
*/
|
424
|
countDependence: function(vertex){
|
425
|
var countFrom = 0;
|
426
|
var countTo = 0;
|
427
|
|
428
|
if(!GraphManager.isEfpGraph) {
|
429
|
countFrom = vertex.exportedPackages.length;
|
430
|
countTo = vertex.importedPackages.length;
|
431
|
} else { // legacy method - for efp graphs
|
432
|
for (var i = 0; i < vertex.edges.length;i++) {
|
433
|
if (vertex.id == vertex.edges[i].from.id) {
|
434
|
countFrom++;
|
435
|
}
|
436
|
}
|
437
|
|
438
|
countTo = vertex.edges.length - countFrom;
|
439
|
}
|
440
|
|
441
|
return {
|
442
|
countFrom: countFrom,
|
443
|
countTo: countTo
|
444
|
};
|
445
|
},
|
446
|
|
447
|
/**
|
448
|
* Counts dependencies of grouped vertices with other vertices outside the group.
|
449
|
*
|
450
|
* @param idGroup
|
451
|
*/
|
452
|
countDependenceGroup: function(idGroup){
|
453
|
var countFrom = 0;
|
454
|
var countTo = 0;
|
455
|
|
456
|
var group = this.groupManager.getGroup(idGroup);
|
457
|
var vertexList = group.items.getAll();
|
458
|
|
459
|
// iterate over vertices
|
460
|
$.each(vertexList, function(key, vertex){
|
461
|
for (var j = 0; j < vertex.edges.length; j++){
|
462
|
var toEndOk = true, fromEndOk = true;
|
463
|
|
464
|
if (vertex.id == vertex.edges[j].from.id) {
|
465
|
//check if the TO end of the found edge is NOT in this group too
|
466
|
$.each(vertexList, function(key, otherEndVertex) {
|
467
|
if (otherEndVertex.id == vertex.edges[j].to.id) {
|
468
|
toEndOk = false;
|
469
|
|
470
|
return false;
|
471
|
}
|
472
|
});
|
473
|
|
474
|
// increase if OK
|
475
|
if (toEndOk) {
|
476
|
countFrom++;
|
477
|
}
|
478
|
}
|
479
|
|
480
|
if (vertex.id == vertex.edges[j].to.id) {
|
481
|
//check if the FROM end of the found edge is NOT in this group too
|
482
|
$.each(vertexList, function(key, otherEndVertex) {
|
483
|
if (otherEndVertex.id == vertex.edges[j].from.id) {
|
484
|
fromEndOk = false;
|
485
|
|
486
|
return false;
|
487
|
}
|
488
|
});
|
489
|
|
490
|
// increase if OK
|
491
|
if (fromEndOk) {
|
492
|
countTo++;
|
493
|
}
|
494
|
}
|
495
|
}
|
496
|
});
|
497
|
|
498
|
return {
|
499
|
countFrom: countFrom,
|
500
|
countTo: countTo
|
501
|
};
|
502
|
},
|
503
|
|
504
|
isOnOneSideOfEdge: function(vertex, edge) {
|
505
|
return (edge.to.id == vertex.id) || (edge.from.id != vertex.id);
|
506
|
},
|
507
|
|
508
|
getEdgeOtherSide: function(edge, vertex) {
|
509
|
return (edge.to.id != vertex.id) ? edge.to : edge.from;
|
510
|
},
|
511
|
|
512
|
/**
|
513
|
* Creates all elements representing the vertex in SeCo and binds click callbacks.
|
514
|
*
|
515
|
* @param vertex the vertex
|
516
|
*/
|
517
|
createVertexDetail: function(vertex) {
|
518
|
$('#excludedComponents').append('<div class="component vertex" id="component' + vertex.id + '" data-id="' + vertex.id + '"></div>');
|
519
|
|
520
|
var componentElement = $('#component' + vertex.id);
|
521
|
componentElement.append(SvgFactory.createVertexDetail(vertex));
|
522
|
componentElement.append('<div class="control-buttons"></div>');
|
523
|
|
524
|
var buttonsElement = componentElement.children('.control-buttons');
|
525
|
buttonsElement.append('<div class="button buttonClassic" id="showIcons' + vertex.id +'">' + vertex.symbol[0] + '</div>');
|
526
|
if (vertex.name !== 'NOT_FOUND') {
|
527
|
buttonsElement.append('<div class="button buttonClassic" id="change' + vertex.id +'">'+
|
528
|
'<img class="buttonImage" src="images/tochange/tochange-trans.gif" alt="change" title="Send component to change">'+
|
529
|
'</div>');
|
530
|
}
|
531
|
buttonsElement.append('<div class="button buttonClassic" id="remove' + vertex.id +'"><img src="images/button_cancel.png" alt="remove" title="remove"/></div>');
|
532
|
|
533
|
// registration of event
|
534
|
$('#showIcons' + vertex.id).click(this.showVertexIcons);
|
535
|
$('#change' + vertex.id).click(OffScreenKiv.changeComponent);
|
536
|
$('#postpone' + vertex.id).click(OffScreenKiv.postponeComponent);
|
537
|
$('#remove' + vertex.id).click(function(e) {
|
538
|
OffScreenKiv.showVertexInGraph(vertex.id);
|
539
|
});
|
540
|
|
541
|
configurationVertexDetailTooltip('#detailVertex' + vertex.id);
|
542
|
|
543
|
// assigning actions to parts of detail
|
544
|
$('#detailVertex' + vertex.id).click(ViewportManager.highlightClckdVertexSeCo);
|
545
|
$('#provided' + vertex.id).click(ViewportManager.highlightProvGraphSeCo);
|
546
|
$('#required' + vertex.id).click(ViewportManager.highlightReqGraphSeCo);
|
547
|
},
|
548
|
|
549
|
/**
|
550
|
* Create detail of removed vertex from graph and registers all events.
|
551
|
* Parameters: e - event
|
552
|
*/
|
553
|
showVertexInRightPanel: function(e) {
|
554
|
if (e.which != 1) return;
|
555
|
|
556
|
var id = findId(e.target);
|
557
|
var vertex = GraphManager.graph.vertices[id - 1];
|
558
|
vertex.symbol = OffScreenKiv.markSymbol.getMarkSymbol();
|
559
|
|
560
|
// according to #1751
|
561
|
this.detectAndSetUnconnectedInGraph(vertex);
|
562
|
|
563
|
vertex.excluded = true;
|
564
|
|
565
|
this.hideEdges(vertex);
|
566
|
vertex.$selector.hide();
|
567
|
|
568
|
this.addItemToContextMenu(vertex.symbol, vertex.id, vertex.name);
|
569
|
|
570
|
this.createVertexDetail(vertex);
|
571
|
|
572
|
$('#includeAllComponents').show();
|
573
|
|
574
|
// Excludes from graph with the correct highlight color
|
575
|
$('#detailVertex' + vertex.id).attr('class', vertex.$selector.attr('class'));
|
576
|
|
577
|
// handle search highlight vertieces
|
578
|
if (this.vertexSearchHighlighting[vertex.symbolicName] !== undefined) {
|
579
|
var secoVertex = $('#detailVertex' + (vertex.id));
|
580
|
secoVertex[0].classList.add('vertex--searched');
|
581
|
|
582
|
this.vertexSearchHighlighting['detailVertex' + (vertex.id)] = secoVertex;
|
583
|
}
|
584
|
},
|
585
|
|
586
|
/**
|
587
|
* Display vertex and its edges in graph.
|
588
|
*/
|
589
|
showVertexInGraph: function(id) {
|
590
|
var vertex = GraphManager.graph.vertices[id - 1];
|
591
|
|
592
|
vertex.$selector.show();
|
593
|
|
594
|
for (var i = 0; i < vertex.edges.length; i++){
|
595
|
if (vertex.edges[i].to.id != vertex.id &&
|
596
|
(vertex.edges[i].to.$selector[0].isVisible() ||
|
597
|
($('#rightPanel #li'+vertex.edges[i].to.id).length == 1 && $('#rightPanel #li'+ vertex.edges[i].to.id).is(':visible') === false)
|
598
|
)
|
599
|
) {
|
600
|
vertex.edges[i].$selector.show();
|
601
|
}
|
602
|
|
603
|
if (vertex.edges[i].from.id != vertex.id &&
|
604
|
(vertex.edges[i].from.$selector[0].isVisible() ||
|
605
|
($('#rightPanel #li'+vertex.edges[i].to.id).length == 1 && $('#rightPanel #li'+ vertex.edges[i].from.id).is(':visible') === false)
|
606
|
)
|
607
|
) {
|
608
|
vertex.edges[i].$selector.show();
|
609
|
}
|
610
|
}
|
611
|
|
612
|
$("#detailVertex" + vertex.id).qtip('destroy');
|
613
|
for (var j = 0; j < vertex.edges.length; j++) {
|
614
|
var targetVertex = this.getEdgeOtherSide(vertex.edges[j], vertex);
|
615
|
var markId = 'mark' + vertex.symbol[0]+ vertex.symbol[1];
|
616
|
|
617
|
if (targetVertex.gridMark.existMark(markId)) {
|
618
|
targetVertex.gridMark.removeMark(markId);
|
619
|
}
|
620
|
}
|
621
|
|
622
|
$('#component' + vertex.id).remove();
|
623
|
$('#proposed' + vertex.id).remove();
|
624
|
|
625
|
vertex.excluded = false;
|
626
|
this.markSymbol.removeSymbol(vertex.symbol);
|
627
|
var itemId = vertex.symbol[1].substring(1) + vertex.symbol[0];
|
628
|
this.deleteItemFromContextMenu(itemId);
|
629
|
|
630
|
this.hideIncludeAllComponentsButton();
|
631
|
|
632
|
// check if opacity needs to be reset
|
633
|
this.detectAndResetReconnectedInGraph(vertex);
|
634
|
},
|
635
|
|
636
|
/**
|
637
|
* Shows component and in the propose-change list in SeCo.
|
638
|
*/
|
639
|
changeComponent: function(e){
|
640
|
if (e.which != 1) return;
|
641
|
|
642
|
var id = findId(e.target);
|
643
|
var vertex = GraphManager.graph.vertices[id - 1];
|
644
|
vertex.symbol = OffScreenKiv.markSymbol.getMarkSymbol();
|
645
|
|
646
|
$('#component' + vertex.id).remove();
|
647
|
$('#rightPanel .to-change-components').append('<div class="component vertex" id="component' + vertex.id + '" data-id="' + vertex.id + '"></div>');
|
648
|
|
649
|
var componentElement = $('#component' + vertex.id);
|
650
|
componentElement.append(SvgFactory.createVertexDetail(vertex));
|
651
|
componentElement.append('<div class="control-buttons"></div>');
|
652
|
componentElement.append('<div class="compatibility-list">' + getTooltipEdge(vertex.id) + '</div>');
|
653
|
|
654
|
var buttonsElement = componentElement.children('.control-buttons');
|
655
|
if (vertex.name !== 'NOT_FOUND') {
|
656
|
buttonsElement.append('<div class="button buttonClassic" id="postpone' + vertex.id +'">'+
|
657
|
'<img class="buttonImage" src="images/tochange/postpone-trans.gif" alt="Postpone" title="Postpone component change">'+
|
658
|
'</div>');
|
659
|
}
|
660
|
buttonsElement.append('<div class="button buttonClassic" id="remove' + vertex.id +'"><img src="images/button_cancel.png" alt="remove" title="remove"/></div>');
|
661
|
|
662
|
// registration of event
|
663
|
$('#postpone' + vertex.id).click(function(e) {
|
664
|
OffScreenKiv.postponeComponent(e);
|
665
|
});
|
666
|
$('#remove' + vertex.id).click(function(e) {
|
667
|
OffScreenKiv.showVertexInGraph(vertex.id);
|
668
|
});
|
669
|
|
670
|
/*
|
671
|
$('#rightPanel').append('<div class="component" id="proposed' + vertex.id + '">');
|
672
|
|
673
|
$('#proposed' + vertex.id).append('<hr class="verticalSeparator clean"/>');
|
674
|
$('#proposed' + vertex.id).append('<h5 class="text">Proposed</h5>');
|
675
|
$('#proposed' + vertex.id).append(SvgFactory.createVertexDetail(vertex));
|
676
|
|
677
|
$('#proposed' + vertex.id).append('<div id ="proposedCb' + vertex.id + '" class="controlButton">');
|
678
|
//todo change to IMG
|
679
|
$('#proposedCb' + vertex.id).append('<div class="button buttonClassic" id="ok' + vertex.id +'" disabled>\n\
|
680
|
<img src="images/efp_qtip/OK.png" alt="confirm" title="confirm"/></div>');
|
681
|
$('#proposedCb' + vertex.id).append('<div class="button buttonClassic" id="db' + vertex.id +'" disabled>\n\
|
682
|
<img src="images/button_cancel.png" alt="remove" title="remove"/></div>');
|
683
|
$('#proposed' + vertex.id).append('</div><br class="clean"/>');
|
684
|
$('#proposed' + vertex.id).append('<hr class="verticalSeparator clean"/>');
|
685
|
$('#rightPanel').append('</div>');
|
686
|
*/
|
687
|
|
688
|
setUpTooltipList(componentElement.find('#edgeTooltipListDiv' + (id - 1)));
|
689
|
},
|
690
|
|
691
|
/**
|
692
|
* Shows component and in the postponed list in SeCo.
|
693
|
*/
|
694
|
postponeComponent: function(e) {
|
695
|
if (e.which != 1) return;
|
696
|
|
697
|
var id = findId(e.target);
|
698
|
var vertex = GraphManager.graph.vertices[id - 1];
|
699
|
vertex.symbol = OffScreenKiv.markSymbol.getMarkSymbol();
|
700
|
|
701
|
$('#component' + vertex.id).remove();
|
702
|
$('#rightPanel .postponed-components').append('<div class="component vertex" id="component' + vertex.id + '" data-id="' + vertex.id + '"></div>');
|
703
|
|
704
|
var componentElement = $('#component' + vertex.id);
|
705
|
componentElement.append(SvgFactory.createVertexDetail(vertex));
|
706
|
componentElement.append('<div class="control-buttons"></div>');
|
707
|
|
708
|
var buttonsElement = componentElement.children('.control-buttons');
|
709
|
if (vertex.name !== 'NOT_FOUND') {
|
710
|
buttonsElement.append('<div class="button buttonClassic" id="change' + vertex.id +'">'+
|
711
|
'<img class="buttonImage" src="images/tochange/tochange-trans.gif" alt="ToChange" title="Send component to change">'+
|
712
|
'</div>');
|
713
|
}
|
714
|
buttonsElement.append('<div class="button buttonClassic" id="remove' + vertex.id +'"><img src="images/button_cancel.png" alt="remove" title="remove"/></div>');
|
715
|
|
716
|
// registration of event
|
717
|
$('#change' + vertex.id).click(function(e) {
|
718
|
OffScreenKiv.changeComponent(e);
|
719
|
});
|
720
|
$('#remove' + vertex.id).click(function(e) {
|
721
|
OffScreenKiv.showVertexInGraph(vertex.id);
|
722
|
});
|
723
|
},
|
724
|
|
725
|
/**
|
726
|
* Send changes to crce
|
727
|
*/
|
728
|
proposeChanges: function(e) {
|
729
|
var javaClasses = {
|
730
|
boolean: 'java.lang.Boolean',
|
731
|
string: 'java.lang.String',
|
732
|
list: 'java.util.List',
|
733
|
set: 'java.util.Set',
|
734
|
};
|
735
|
|
736
|
var crceClasses = {
|
737
|
package: 'crce.api.java.package',
|
738
|
class: 'crce.api.java.class',
|
739
|
method: 'crce.api.java.method',
|
740
|
property: 'crce.api.java.property',
|
741
|
};
|
742
|
|
743
|
var ns = ''; // http://relisa.kiv.zcu.cz
|
744
|
var xsi = 'http://www.w3.org/2001/XMLSchema-instance';
|
745
|
var xsd = 'crce.xsd';
|
746
|
|
747
|
var xmlDocument;
|
748
|
var xmlSerializer = new XMLSerializer();
|
749
|
var requirementsCounter;
|
750
|
|
751
|
var toChangeComponents = $('#toChangeComps > .vertex');
|
752
|
var changedComponentsCounter = 0;
|
753
|
|
754
|
if (toChangeComponents.length > 0) {
|
755
|
changeComponent(toChangeComponents[changedComponentsCounter]);
|
756
|
}
|
757
|
|
758
|
function appendRequirementsTree(element, node) {
|
759
|
var type = node.desc.type;
|
760
|
|
761
|
if (typeof type === 'undefined') {
|
762
|
node.subtree.forEach(function(node) {
|
763
|
appendRequirementsTree(element, node);
|
764
|
});
|
765
|
|
766
|
} else {
|
767
|
// add package for classes
|
768
|
if (type === 'class') {
|
769
|
var packageRequirementEl = xmlDocument.createElementNS(ns, 'requirement');
|
770
|
packageRequirementEl.setAttribute('uuid', requirementsCounter++);
|
771
|
packageRequirementEl.setAttribute('namespace', crceClasses['package']);
|
772
|
|
773
|
var packageAttributeEl = xmlDocument.createElementNS(ns, 'attribute');
|
774
|
packageAttributeEl.setAttribute('name', 'name');
|
775
|
packageAttributeEl.setAttribute('type', javaClasses.string);
|
776
|
packageAttributeEl.setAttribute('value', node.desc.details.package);
|
777
|
|
778
|
packageRequirementEl.appendChild(packageAttributeEl);
|
779
|
|
780
|
delete node.desc.details.package;
|
781
|
}
|
782
|
|
783
|
var requirementEl = xmlDocument.createElementNS(ns, 'requirement');
|
784
|
requirementEl.setAttribute('uuid', requirementsCounter++);
|
785
|
requirementEl.setAttribute('namespace', crceClasses[type]);
|
786
|
|
787
|
// attributes
|
788
|
var details = node.desc.details;
|
789
|
for (var key in details) {
|
790
|
if (!details.hasOwnProperty(key)) continue;
|
791
|
|
792
|
var value = details[key];
|
793
|
|
794
|
var attributeType;
|
795
|
switch (typeof value) {
|
796
|
case 'boolean':
|
797
|
attributeType = javaClasses.boolean;
|
798
|
break;
|
799
|
case 'object':
|
800
|
if (value.constructor.name === 'Array') {
|
801
|
attributeType = javaClasses.list;
|
802
|
break;
|
803
|
}
|
804
|
default:
|
805
|
attributeType = javaClasses.string;
|
806
|
}
|
807
|
|
808
|
var attributeEl = xmlDocument.createElementNS(ns, 'attribute');
|
809
|
attributeEl.setAttribute('name', key);
|
810
|
attributeEl.setAttribute('type', attributeType);
|
811
|
attributeEl.setAttribute('value', value);
|
812
|
|
813
|
requirementEl.appendChild(attributeEl);
|
814
|
}
|
815
|
|
816
|
// children
|
817
|
node.subtree.forEach(function(node) {
|
818
|
appendRequirementsTree(requirementEl, node);
|
819
|
});
|
820
|
|
821
|
// add package for classes
|
822
|
if (type === 'class') {
|
823
|
packageRequirementEl.appendChild(requirementEl);
|
824
|
element.appendChild(packageRequirementEl);
|
825
|
} else {
|
826
|
element.appendChild(requirementEl);
|
827
|
}
|
828
|
}
|
829
|
}
|
830
|
|
831
|
function changeComponent(component) {
|
832
|
app.loader.enable();
|
833
|
|
834
|
var id = findId(component);
|
835
|
var vertex = GraphManager.graph.vertices[id - 1];
|
836
|
|
837
|
// initialize requirements XML to be send to CRCE
|
838
|
xmlDocument = document.implementation.createDocument(ns, 'requirements', null);
|
839
|
//xmlDocument.documentElement.setAttributeNS(xsi, 'xsi:schemaLocation', ns + ' ' + xsd);
|
840
|
|
841
|
requirementsCounter = 0;
|
842
|
|
843
|
// construct functionality requirements tree
|
844
|
vertex.edges.forEach(function(edge) {
|
845
|
//var compatibilityInfo = JSON.parse(edge.compInfoJSON);
|
846
|
|
847
|
// TODO: mocked compatibility info
|
848
|
var compatibilityInfo = [
|
849
|
{
|
850
|
"details": {
|
851
|
"abstract": false,
|
852
|
"annotation": false,
|
853
|
"final": false,
|
854
|
"static": false,
|
855
|
"name": "Dashboard",
|
856
|
"package": "cz.zcu.kiv.osgi.demo.parking.dashboard",
|
857
|
"enum": false,
|
858
|
"interface": false
|
859
|
},
|
860
|
"causedBy": "cz.zcu.kiv.osgi.demo.parking.dashboard.DashboardActivator",
|
861
|
"type": "class",
|
862
|
"incomps": [
|
863
|
{
|
864
|
"subtree": [
|
865
|
{
|
866
|
"subtree": [],
|
867
|
"desc": {
|
868
|
"isIncompCause": false,
|
869
|
"propertyName": "Fields",
|
870
|
"contentCode": "cmp.child.fields",
|
871
|
"level": 1,
|
872
|
"name": "Fields"
|
873
|
}
|
874
|
}, {
|
875
|
"subtree": [{
|
876
|
"subtree": [],
|
877
|
"desc": {
|
878
|
"difference": "DEL",
|
879
|
"isIncompCause": true,
|
880
|
"propertyName": "Method",
|
881
|
"contentCode": "cmp.child.method",
|
882
|
"level": 2,
|
883
|
"details": {
|
884
|
"abstract": false,
|
885
|
"final": false,
|
886
|
"exceptions": [],
|
887
|
"static": false,
|
888
|
"synchronized": false,
|
889
|
"name": "clear",
|
890
|
"paramTypes": [],
|
891
|
"returnType": "void",
|
892
|
"constructor": false
|
893
|
},
|
894
|
"incompName": "<span class='entity'>M<\/span> void clear() is missing -> REFACTOR",
|
895
|
"name": "M void clear()",
|
896
|
"strategy": "REFACTOR",
|
897
|
"type": "method"
|
898
|
}
|
899
|
}],
|
900
|
"desc": {
|
901
|
"isIncompCause": false,
|
902
|
"propertyName": "Methods",
|
903
|
"contentCode": "cmp.child.methods",
|
904
|
"level": 1,
|
905
|
"name": "Methods"
|
906
|
}
|
907
|
}, {
|
908
|
"subtree": [],
|
909
|
"desc": {
|
910
|
"isIncompCause": false,
|
911
|
"propertyName": "Constructors",
|
912
|
"contentCode": "cmp.child.constructors",
|
913
|
"level": 1,
|
914
|
"name": "Constructors"
|
915
|
}
|
916
|
}
|
917
|
],
|
918
|
"desc": {
|
919
|
"isIncompCause": false,
|
920
|
"propertyName": "Class",
|
921
|
"contentCode": "cmp.child.class",
|
922
|
"level": 0,
|
923
|
"details": {
|
924
|
"name": "LaneStatistics",
|
925
|
"abstract": false,
|
926
|
"annotation": false,
|
927
|
"final": false,
|
928
|
"static": false,
|
929
|
"package": "cz.zcu.kiv.osgi.demo.parking.lane.statistics",
|
930
|
"enum": false,
|
931
|
"interface": false
|
932
|
},
|
933
|
"name": "Class: cz.zcu.kiv.osgi.demo.parking.lane.statistics.ILaneStatistics",
|
934
|
"type": "class"
|
935
|
}
|
936
|
}
|
937
|
]
|
938
|
}
|
939
|
];
|
940
|
|
941
|
compatibilityInfo.forEach(function(component) {
|
942
|
component.incomps.forEach(function(node) {
|
943
|
appendRequirementsTree(xmlDocument.documentElement, node);
|
944
|
});
|
945
|
});
|
946
|
});
|
947
|
|
948
|
// get components related to the one being changed
|
949
|
var relatedJars = [];
|
950
|
|
951
|
vertex.edges.forEach(function(edge) {
|
952
|
// store related jars
|
953
|
relatedJars.push(edge.from.name);
|
954
|
relatedJars.push(edge.to.name);
|
955
|
});
|
956
|
|
957
|
relatedJars = relatedJars.filter(function(jarName) {
|
958
|
return jarName !== 'NOT_FOUND' && jarName !== vertex.name;
|
959
|
});
|
960
|
|
961
|
// trigger change
|
962
|
$.ajax({
|
963
|
type: 'POST', // jQuery docs tells to use "method" but it doesn't work and always sends GET -> use "type" instead
|
964
|
url: 'http://localhost:8081/rest/v2/metadata/catalogue/',
|
965
|
data: xmlSerializer.serializeToString(xmlDocument),
|
966
|
contentType: 'application/xml',
|
967
|
timeout: 180 * 1000, // in milliseconds
|
968
|
}).then(function(data, textStatus, jqXHR) {
|
969
|
app.loader.disable();
|
970
|
|
971
|
var proposals = [];
|
972
|
|
973
|
var resources = data.childNodes[0];
|
974
|
resources.childNodes.forEach(function(resource) {
|
975
|
var proposal = {
|
976
|
crceUuid: resource.getAttribute('uuid'),
|
977
|
};
|
978
|
|
979
|
var capability = resource.childNodes[0];
|
980
|
capability.childNodes.forEach(function(attribute) {
|
981
|
if (['name', 'version'].includes(attribute.getAttribute('name'))) {
|
982
|
proposal[attribute.getAttribute('name')] = attribute.getAttribute('value');
|
983
|
}
|
984
|
});
|
985
|
|
986
|
proposals.push(proposal);
|
987
|
});
|
988
|
|
989
|
$(component).prepend('<h5>Current change</h5>');
|
990
|
$(component).addClass('active');
|
991
|
|
992
|
var proposedList = $('<ul id="proposed"></ul>');
|
993
|
$(component).append(proposedList);
|
994
|
|
995
|
for (var i = 0; i < proposals.length; i++) {
|
996
|
proposal = proposals[i];
|
997
|
|
998
|
var maven = proposal.name.split('.');
|
999
|
proposedList.append('<li><span class="download-component-link" data-uuid="' + proposal.crceUuid + '">' + proposal.name + ' ' + proposal.version + '</span><a href="https://mvnrepository.com/artifact/' + maven[0] + '/' + maven[1] + '/' + proposal.version + '" target="_blank">Maven</a></li>');
|
1000
|
}
|
1001
|
|
1002
|
$('.download-component-link').click(function(e) {
|
1003
|
app.loader.enable();
|
1004
|
|
1005
|
var uuid = $(this).data('uuid');
|
1006
|
|
1007
|
return $.ajax({
|
1008
|
type: 'POST',
|
1009
|
url: 'api/download-component?uuid=' + encodeURIComponent(uuid),
|
1010
|
timeout: 180 * 1000, // in milliseconds
|
1011
|
}).done(function(data, textStatus, jqXHR) {
|
1012
|
relatedJars.push(data.jarName);
|
1013
|
|
1014
|
return $.ajax({
|
1015
|
type: 'GET',
|
1016
|
url: 'graph-data?jarNames=' + encodeURIComponent(relatedJars.join(',')),
|
1017
|
timeout: 180 * 1000, // in milliseconds
|
1018
|
}).done(function(data, textStatus, jqXHR) {
|
1019
|
GraphManager.graph = data;
|
1020
|
|
1021
|
GraphManager.buildGraph();
|
1022
|
ViewportManager.revive();
|
1023
|
});
|
1024
|
});
|
1025
|
});
|
1026
|
|
1027
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
1028
|
console.info('Server failed:');
|
1029
|
console.log(errorThrown);
|
1030
|
});
|
1031
|
}
|
1032
|
},
|
1033
|
|
1034
|
/**
|
1035
|
* Hides vertex edges
|
1036
|
* @param vertex vertex whose edges will be hidden
|
1037
|
*/
|
1038
|
hideEdges: function(vertex){
|
1039
|
for (var i = 0; i < vertex.edges.length; i++) {
|
1040
|
vertex.edges[i].$selector.hide();
|
1041
|
}
|
1042
|
|
1043
|
$('[data-from-id='+ vertex.id +']').each(function(){
|
1044
|
$(this).hide();
|
1045
|
});
|
1046
|
},
|
1047
|
|
1048
|
/**
|
1049
|
* Adds item to context menu.
|
1050
|
* Parameters: symbol - symbol which will be in context menu.
|
1051
|
* vertexId - id of vertex which is linked with item of context menu.
|
1052
|
*/
|
1053
|
addItemToContextMenu: function(symbol, vertexId, vertexName){
|
1054
|
var color = symbol[1].substring(1);
|
1055
|
var itemId = color + symbol[0];
|
1056
|
$('#myMenu').append('<li id="' + itemId + '" data-vertexId="' + vertexId + '"><a href="#' + itemId +
|
1057
|
'" class="component_color"><img class="imgContextMenu" src="images/'+color +'.png" alt="'+color+'"/>' + symbol[0] +
|
1058
|
'</a><a class="cont_menu_group" href="#" onclick="OffScreenKiv.showDescription(\''+itemId+'\'); return false;">[+]</a><span class="contextMenuDescription" id="contMenu_'+vertexId+'" style="display:none">' + vertexName + '</span>'+
|
1059
|
'<span class="cleaner"></span></li>');
|
1060
|
|
1061
|
// $('#myMenu li#'+itemId+' .cont_menu_group').unbind('mousedown').unbind('mouseup');
|
1062
|
|
1063
|
},
|
1064
|
|
1065
|
showDescription: function (itemId) {
|
1066
|
if ($('#myMenu li#'+itemId+' .contextMenuDescription:hidden').length) {
|
1067
|
$('#myMenu li#'+itemId+' .contextMenuDescription').show();
|
1068
|
$('#myMenu li#'+itemId+' a.cont_menu_group').text('[-]');
|
1069
|
} else {
|
1070
|
$('#myMenu li#'+itemId+' .contextMenuDescription').hide();
|
1071
|
$('#myMenu li#'+itemId+' a.cont_menu_group').text('[+]');
|
1072
|
}
|
1073
|
|
1074
|
// set css height of li#idGroup by count li elements
|
1075
|
/*
|
1076
|
var count_in_li = $('#myMenu li#' + itemId + ' .contextMenuDescription').length;
|
1077
|
$('#myMenu li#' + itemId).css('height', (22 + (count_in_li * 16)) + 'px'); */
|
1078
|
|
1079
|
var count_in_li = $('#myMenu li#' + itemId + ' .contextMenuDescription:not(:hidden)').length;
|
1080
|
$('#myMenu li#' + itemId).css('height', (22 + (count_in_li * 16)) + 'px');
|
1081
|
$('#myMenu li#' + itemId).show();
|
1082
|
},
|
1083
|
|
1084
|
/**
|
1085
|
* Delete item from context menu.
|
1086
|
* Parameters: groupID - id item from context menu which will be deleted.
|
1087
|
*/
|
1088
|
deleteItemFromContextMenu: function(groupID){
|
1089
|
$('#' + groupID).remove();
|
1090
|
},
|
1091
|
|
1092
|
/**
|
1093
|
* Check and set highlighting when grouping vertices.
|
1094
|
* @param vertex
|
1095
|
*/
|
1096
|
checkHighlightingAtGrouping: function(vertex){
|
1097
|
var $groupedVertex = $('#li' + (vertex.id));
|
1098
|
if ($("#vertex" + (vertex.id) + "[class~='colorHighProvB']").length) {
|
1099
|
$groupedVertex.attr('style', 'background-color: #5896FF');
|
1100
|
}
|
1101
|
|
1102
|
if ($("#vertex" + (vertex.id) + "[class~='colorHighReqR']").length) {
|
1103
|
$groupedVertex.attr('style', 'background-color: red');
|
1104
|
}
|
1105
|
},
|
1106
|
|
1107
|
/**
|
1108
|
* Adds vertex to group.
|
1109
|
* Parameters: action - id of element from context menu
|
1110
|
* element - id vertex element
|
1111
|
*/
|
1112
|
addVertexToGroup: function(action, element) {
|
1113
|
var id = element.data('id');
|
1114
|
var idGroup = action;
|
1115
|
|
1116
|
var vertex = GraphManager.graph.vertices[id - 1];
|
1117
|
vertex.$selector.hide();
|
1118
|
|
1119
|
this.hideEdges(vertex);
|
1120
|
|
1121
|
// detect if removing the vertex causes some unconnection(s)
|
1122
|
this.detectAndSetUnconnectedInGraph(vertex);
|
1123
|
|
1124
|
var group = null;
|
1125
|
var defaultVertex = GraphManager.graph.vertices[$("#" + idGroup).attr('data-vertexId')-1];
|
1126
|
defaultVertex.excluded = true;
|
1127
|
vertex.symbol = defaultVertex.symbol;
|
1128
|
var color = defaultVertex.symbol[1];
|
1129
|
var isSetClassOnButton = $('#b' + defaultVertex.id).hasClass('c' + color.substring(1, color.length));
|
1130
|
|
1131
|
if (!this.groupManager.existGroup(idGroup)) {
|
1132
|
$('#component' + defaultVertex.id).remove();
|
1133
|
group = new Group(defaultVertex.symbol, idGroup);
|
1134
|
group.addToGroup(defaultVertex.id, defaultVertex);
|
1135
|
group.addProvidedPackage(defaultVertex.exportedPackages);
|
1136
|
group.addRequiredPackage(defaultVertex.importedPackages);
|
1137
|
group.addProvidedPackage(vertex.exportedPackages);
|
1138
|
group.addRequiredPackage(vertex.importedPackages);
|
1139
|
this.createGroup(group, defaultVertex, vertex);
|
1140
|
this.groupManager.addGroupToList(idGroup, group);
|
1141
|
|
1142
|
} else {
|
1143
|
group = this.groupManager.getGroup(idGroup);
|
1144
|
group.addProvidedPackage(vertex.exportedPackages);
|
1145
|
group.addRequiredPackage(vertex.importedPackages);
|
1146
|
$('#ul' + idGroup).append('<li id="li' + vertex.id + '"><p data-vertexId="' + vertex.id + '" data-title="' + vertex.name + '">' + vertex.name + '</p><img class="deleteItemGroup" id="li_del_' + vertex.id + '" alt="delete" src="images/button_cancel.png"/></li>');
|
1147
|
configurationVertexDetailTooltip('#li' + vertex.id + " p");
|
1148
|
|
1149
|
// add highlighting possiblity
|
1150
|
$('#li' + vertex.id + ' p').click(ViewportManager.highlightClckdVertexGroupSeCo);
|
1151
|
|
1152
|
// highlight the newly added vertex if already highlight in move area
|
1153
|
this.checkHighlightingAtGrouping(vertex);
|
1154
|
|
1155
|
// highlight the newly added vertex if searched
|
1156
|
if (this.vertexSearchHighlighting[vertex.symbolicName] !== undefined) {
|
1157
|
this.highlightSearchedVertexInGroup(vertex);
|
1158
|
}
|
1159
|
}
|
1160
|
|
1161
|
var is_in_group = false;
|
1162
|
$.each(group.items.getAll(), function(index, value) {
|
1163
|
if ( value.id == vertex.id) {
|
1164
|
is_in_group = true;
|
1165
|
}
|
1166
|
});
|
1167
|
|
1168
|
|
1169
|
if (is_in_group === false) {
|
1170
|
var style_display = ' style="display:none" ';
|
1171
|
if ( $('#myMenu li#' + idGroup + ' .contextMenuDescription:not(:hidden)').length ) {
|
1172
|
$('#myMenu li#' + idGroup + ' .contextMenuDescription:last').after('<span class="contextMenuDescription b" id="contMenu_'+vertex.id+'" >'+vertex.name+'</span>');
|
1173
|
}else{
|
1174
|
$('#myMenu li#' + idGroup + ' .contextMenuDescription:last').after('<span class="contextMenuDescription b" id="contMenu_'+vertex.id+'" '+style_display+'>'+vertex.name+'</span>');
|
1175
|
}
|
1176
|
|
1177
|
}
|
1178
|
|
1179
|
//set css height of li#idGroup by count li elements
|
1180
|
var count_in_li = $('#myMenu li#' + idGroup + ' .contextMenuDescription:not(:hidden)').length;
|
1181
|
$('#myMenu li#' + idGroup).css('height', (22 + (count_in_li * 16)) + 'px');
|
1182
|
|
1183
|
vertex.excluded = true;
|
1184
|
group.addToGroup(vertex.id, vertex);
|
1185
|
|
1186
|
|
1187
|
|
1188
|
$('.deleteItemGroup').unbind('click',this.deleteItemFromGroupEvent);
|
1189
|
$('.deleteItemGroup').click(this.deleteItemFromGroupEvent);
|
1190
|
|
1191
|
if (group.getGroupItemsLength() > 2) {
|
1192
|
this.editHeightOfGroup(group);
|
1193
|
}
|
1194
|
this.updateCountOfProvidedAndRequired(group);
|
1195
|
var buttonGroupId = $("#b" + idGroup);
|
1196
|
|
1197
|
if (isSetClassOnButton) {
|
1198
|
this.showIcons(vertex);
|
1199
|
buttonGroupId.attr('class', 'button c'+idGroup.substring(0,idGroup.length-1));
|
1200
|
buttonGroupId.unbind('click');
|
1201
|
buttonGroupId.click(this.hideIconsAllItemGroup);
|
1202
|
}
|
1203
|
|
1204
|
if ($("#b" + idGroup).hasClass("c"+idGroup.substring(0,idGroup.length-1))) {
|
1205
|
this.showIcons(vertex);
|
1206
|
}
|
1207
|
|
1208
|
$('#gr' + group.idGroup).click(this.groupHighlightRequiredAndProvided);
|
1209
|
$('#provided' + group.idGroup).click(this.groupHighlightProvided);
|
1210
|
$('#required' + group.idGroup).click(this.groupHighlightRequired);
|
1211
|
|
1212
|
$(".contextMenu").hide();
|
1213
|
// $(".contextMenuDescription").hide();
|
1214
|
|
1215
|
// kontrola, zda je skupina komponent zobrazena v grafu
|
1216
|
// -> pokud ano zobrazit hrany vedouci z komponenty, ktera byla pridana do grafu
|
1217
|
|
1218
|
if ($('g#gv_'+group.idGroup).length > 0) {
|
1219
|
//show all edges removed vertex from group.
|
1220
|
//TODO: nastavit správnou pozici komponenty
|
1221
|
|
1222
|
for (var i = 0; i < vertex.edges.length; i++) {
|
1223
|
if (vertex.edges[i].to.id != vertex.id && (
|
1224
|
vertex.edges[i].to.$selector[0].isVisible() ||
|
1225
|
($('#rightPanel #li'+vertex.edges[i].to.id).length == 1 && $('#rightPanel #li'+vertex.edges[i].to.id).is(':visible') === false)
|
1226
|
)
|
1227
|
){
|
1228
|
vertex.edges[i].$selector.show();
|
1229
|
}
|
1230
|
|
1231
|
if (vertex.edges[i].from.id != vertex.id && (
|
1232
|
vertex.edges[i].from.$selector[0].isVisible() ||
|
1233
|
($('#rightPanel #li'+vertex.edges[i].to.id).length == 1 && $('#rightPanel #li'+vertex.edges[i].from.id).is(':visible') === false)
|
1234
|
)
|
1235
|
) {
|
1236
|
vertex.edges[i].$selector.show();
|
1237
|
}
|
1238
|
|
1239
|
vertex.edges[i].to.$selector.attr('class','node vertex colorNormal');
|
1240
|
vertex.edges[i].from.$selector.attr('class','node vertex colorNormal');
|
1241
|
}
|
1242
|
|
1243
|
var coords = getCoordinates($('#gv_'+ idGroup )[0].getAttribute('transform'));
|
1244
|
posX = coords.x;
|
1245
|
posY = coords.y;
|
1246
|
|
1247
|
posX_reset = posX;
|
1248
|
|
1249
|
//nastavení pozice prvků
|
1250
|
id_vert =vertex.id;
|
1251
|
|
1252
|
|
1253
|
var newX;
|
1254
|
var newY;
|
1255
|
|
1256
|
var lollipop;
|
1257
|
posX = posX_reset;
|
1258
|
posX = parseFloat(posX);
|
1259
|
|
1260
|
//posun pozice, aby byla komponenta vycentrovana
|
1261
|
hidden_component_width = $('g#vertex' + id_vert + ' rect').attr('width');
|
1262
|
|
1263
|
if (group.decompose) {
|
1264
|
$('#gv_'+ idGroup).children(' rect').attr('height',group.items.size() * 34 + 55);
|
1265
|
posY = parseFloat(posY) + group.items.size() * 26 +34;
|
1266
|
|
1267
|
$item = $('g#vertex' + id_vert);
|
1268
|
|
1269
|
moveElementTopSVG("graph", 'vertex' + id_vert);
|
1270
|
$item.show();
|
1271
|
} else {
|
1272
|
posY = parseFloat(posY);
|
1273
|
}
|
1274
|
|
1275
|
//vystredeni na stred
|
1276
|
posX = posX - (hidden_component_width/2) + 40;
|
1277
|
|
1278
|
group.items.get(id_vert).x = posX;
|
1279
|
group.items.get(id_vert).y = posY ;
|
1280
|
|
1281
|
|
1282
|
$item.attr('transform', 'translate('+ posX +', '+ posY +')');
|
1283
|
$item.trigger('click', {
|
1284
|
move_edges: true,
|
1285
|
});
|
1286
|
|
1287
|
for (var i = 0; i< group.items.get(id_vert).edges.length; i++) {
|
1288
|
var edge = group.items.get(id_vert).edges[i];
|
1289
|
var sizeOfRectFrom = getSizeOfRectangle(edge.from.name);
|
1290
|
var sizeOfRectTo = getSizeOfRectangle(edge.to.name);
|
1291
|
|
1292
|
if (edge.from.id == id_vert) {
|
1293
|
newX = group.items.get(id_vert).edges[i].to.x + sizeOfRectTo/2;
|
1294
|
newY = group.items.get(id_vert).edges[i].to.y + 13;
|
1295
|
lollipop = getLollipopPosition(posX + sizeOfRectFrom/2, posY +13 , newX, newY);
|
1296
|
|
1297
|
edge.$selector.children("line").attr('x1', posX + sizeOfRectFrom/2);
|
1298
|
edge.$selector.children("line").attr('y1', posY + 13);
|
1299
|
edge.$selector.children("g").attr('transform', 'rotate(' + lollipop.angle + ',' + lollipop.x + ',' + lollipop.y + ') translate('+ lollipop.x + ',' + lollipop.y + ')');
|
1300
|
|
1301
|
ViewportManager.preventTickRotation(edge, lollipop);
|
1302
|
ViewportManager.preventCrossRotation(edge, lollipop);
|
1303
|
|
1304
|
//hrana k vrcholu se zobrazi pouze pokud je vrchol zobrazen
|
1305
|
if ($('#vertex'+ edge.to.id )[0].isVisible() ||
|
1306
|
($('#rightPanel li#li'+edge.to.id).is(':visible') === false && $('#rightPanel li#li'+edge.to.id).length > 0)
|
1307
|
) {
|
1308
|
edge.$selector.show();
|
1309
|
}
|
1310
|
|
1311
|
} else {
|
1312
|
newX = group.items.get(id_vert).edges[i].from.x + sizeOfRectFrom/2;
|
1313
|
newY = group.items.get(id_vert).edges[i].from.y + 13;
|
1314
|
lollipop = getLollipopPosition(newX, newY, posX + sizeOfRectTo/2, posY + 13);
|
1315
|
|
1316
|
edge.$selector.children("line").attr('x2', posX + sizeOfRectTo/2);
|
1317
|
edge.$selector.children("line").attr('y2', posY + 13);
|
1318
|
edge.$selector.children("g").attr('transform', 'rotate(' + lollipop.angle + ',' + lollipop.x + ',' + lollipop.y + ') translate('+ lollipop.x + ',' + lollipop.y + ')');
|
1319
|
|
1320
|
ViewportManager.preventTickRotation(edge, lollipop);
|
1321
|
ViewportManager.preventCrossRotation(edge, lollipop);
|
1322
|
|
1323
|
//hrana k vrcholu se zobrazi pouze pokud je vrchol zobrazen
|
1324
|
if ($('#vertex'+ edge.from.id )[0].isVisible() ||
|
1325
|
($('#rightPanel #li'+edge.from.id).is(':visible') === false && $('#rightPanel li#li'+edge.from.id).length > 0)
|
1326
|
) {
|
1327
|
edge.$selector.show();
|
1328
|
}
|
1329
|
}
|
1330
|
}
|
1331
|
}
|
1332
|
},
|
1333
|
|
1334
|
/**
|
1335
|
* Event, which ensures deleting of vertex from group and modified all highlighting.
|
1336
|
*/
|
1337
|
deleteItemFromGroupEvent: function(e){
|
1338
|
var liItem = e.target.parentElement;
|
1339
|
var groupIdUl = liItem.parentElement.id;
|
1340
|
var itemId = liItem.id;
|
1341
|
$("#" + itemId + " p").qtip('destroy');
|
1342
|
$('#' + itemId).remove();
|
1343
|
var vertex = GraphManager.graph.vertices[(getIndexFromId(itemId, 2)-1)];
|
1344
|
|
1345
|
var groupId = $('#' + groupIdUl).attr('data-groupId');
|
1346
|
var group = this.groupManager.getGroup(groupId);
|
1347
|
|
1348
|
if ($("#b" + groupId).hasClass("c"+groupId.substring(0,groupId.length-1))) {
|
1349
|
for (var key in group.items.getAll()) {
|
1350
|
this.hideIconEvent(group.items.get(key));
|
1351
|
}
|
1352
|
}
|
1353
|
|
1354
|
|
1355
|
$('#myMenu li#' + groupId + ' #contMenu_'+vertex.id).remove();
|
1356
|
//set css height of li#idGroup by count li elements
|
1357
|
var count_in_li = $('#myMenu li#' + groupId + ' .contextMenuDescription:not(:hidden)').length;
|
1358
|
$('#myMenu li#' + groupId).css('height', (22 + (count_in_li * 16)) + 'px');
|
1359
|
|
1360
|
vertex.excluded = false;
|
1361
|
var lengthGroup = group.items.size();
|
1362
|
group.removeFromGroup(vertex.id);
|
1363
|
if ($("#b" + groupId).hasClass("c"+groupId.substring(0,groupId.length-1))) {
|
1364
|
for (var key1 in group.items.getAll()) {
|
1365
|
this.showIcons(group.items.get(key1));
|
1366
|
|
1367
|
}
|
1368
|
}
|
1369
|
lengthGroup = group.items.size();
|
1370
|
group.deleteProvidedPackage(vertex.exportedPackages);
|
1371
|
group.deleteRequiredPackage(vertex.importedPackages);
|
1372
|
this.updateCountOfProvidedAndRequired(group);
|
1373
|
|
1374
|
if (lengthGroup >= 2) {
|
1375
|
this.editHeightOfGroup(group);
|
1376
|
}
|
1377
|
|
1378
|
//if length of group is 0, removed all html and svg elements linked with given group.
|
1379
|
if (lengthGroup <= 0) {
|
1380
|
$('#group' + groupId).remove();
|
1381
|
this.groupManager.removeGroupFromList(groupId);
|
1382
|
this.deleteItemFromContextMenu(groupId);
|
1383
|
this.markSymbol.removeSymbol([groupId.substring(groupId.length-1),("#"+groupId.substring(0, groupId.length-1))]);
|
1384
|
}
|
1385
|
|
1386
|
vertex.$selector.show();
|
1387
|
|
1388
|
//show all edges removed vertex from group.
|
1389
|
for (var i = 0; i < vertex.edges.length; i++) {
|
1390
|
if (vertex.edges[i].to.id != vertex.id && vertex.edges[i].to.$selector[0].isVisible()) {
|
1391
|
vertex.edges[i].$selector.show();
|
1392
|
}
|
1393
|
if (vertex.edges[i].from.id != vertex.id && vertex.edges[i].from.$selector[0].isVisible()) {
|
1394
|
vertex.edges[i].$selector.show();
|
1395
|
}
|
1396
|
/*
|
1397
|
vertex.edges[i].to.$selector.attr('class','node vertex colorNormal');
|
1398
|
vertex.edges[i].from.$selector.attr('class','node vertex colorNormal');
|
1399
|
*/
|
1400
|
}
|
1401
|
|
1402
|
this.hideIncludeAllComponentsButton();
|
1403
|
|
1404
|
// check if opacity needs to be reset
|
1405
|
this.detectAndResetReconnectedInGraph(vertex);
|
1406
|
},
|
1407
|
|
1408
|
/**
|
1409
|
* Creates all elements representing the group in SeCo and binds click callbacks.
|
1410
|
*
|
1411
|
* @param group the group
|
1412
|
* @param symbol the symbol of the group
|
1413
|
*/
|
1414
|
createGroupDetail: function(group, symbol) {
|
1415
|
$('#rightPanel').append('<div class="component group_vertices" id="group' + group.idGroup + '" data-id="' + group.idGroup + '"></div>');
|
1416
|
|
1417
|
var componentElement = $('#group' + group.idGroup);
|
1418
|
componentElement.append('<div class="group-label"><strong>G: </strong><span id="label' + group.idGroup + '">Group</span></div>');
|
1419
|
componentElement.append(SvgFactory.createGroupDetail(group));
|
1420
|
componentElement.append('<ul data-groupID="' + group.idGroup + '" id="ul' + group.idGroup + '"></ul>');
|
1421
|
componentElement.append('<div class="control-buttons"></div>');
|
1422
|
|
1423
|
var buttonsElement = componentElement.children('.control-buttons');
|
1424
|
buttonsElement.append('<div class="button buttonClassic" id="showIcons' + group.idGroup +'">' + symbol[0] + '</div>');
|
1425
|
|
1426
|
// set click handler for group renaming
|
1427
|
$('#label' + group.idGroup).click(function() {
|
1428
|
$('#dialog').data('group', group)
|
1429
|
.data('groupLabel', $('#label' + group.idGroup))
|
1430
|
.data('isSvgElement', false)
|
1431
|
.dialog('open');
|
1432
|
});
|
1433
|
|
1434
|
// set click handler for showing group items
|
1435
|
$('#showIcons' + group.idGroup).click(this.showGroupIcons);
|
1436
|
},
|
1437
|
|
1438
|
/**
|
1439
|
* Creates all elements which represent given group and adds passed vertices to the group.
|
1440
|
* Parameters: group - group
|
1441
|
* defaultVertex - first vertex which will be added to the group
|
1442
|
* vertex - second vertex
|
1443
|
*/
|
1444
|
createGroup: function(group, defaultVertex, vertex) {
|
1445
|
this.createGroupDetail(group, defaultVertex.symbol);
|
1446
|
|
1447
|
$('#ul' + group.idGroup).append('<li id="li' + defaultVertex.id + '"><p data-vertexId="' + defaultVertex.id + '" data-title="' + defaultVertex.name + '">' + defaultVertex.name + '</p><img class="deleteItemGroup" id="li_del_' + defaultVertex.id + '" alt="delete" src="images/button_cancel.png"/></li>');
|
1448
|
$('#ul' + group.idGroup).append('<li id="li' + vertex.id + '"><p data-vertexId="' + vertex.id + '" data-title="' + vertex.name + '">' + vertex.name + '</p><img class="deleteItemGroup" id="li_del_' + vertex.id + '" alt="delete" src="images/button_cancel.png"/></li>');
|
1449
|
|
1450
|
configurationVertexDetailTooltip('#li' + defaultVertex.id + " p");
|
1451
|
configurationVertexDetailTooltip('#li' + vertex.id + " p");
|
1452
|
|
1453
|
// add highlight
|
1454
|
$('#li' + defaultVertex.id + ' p').click(ViewportManager.highlightClckdVertexGroupSeCo);
|
1455
|
$('#li' + vertex.id + ' p').click(ViewportManager.highlightClckdVertexGroupSeCo);
|
1456
|
|
1457
|
// highlight the newly added vertices if already highlight in the move area
|
1458
|
this.checkHighlightingAtGrouping(vertex);
|
1459
|
this.checkHighlightingAtGrouping(defaultVertex);
|
1460
|
|
1461
|
// highlight the default vertex if searched
|
1462
|
if (this.vertexSearchHighlighting[defaultVertex.symbolicName] !== undefined) {
|
1463
|
this.highlightSearchedVertexInGroup(defaultVertex);
|
1464
|
}
|
1465
|
|
1466
|
// highlight the newly added vertex if searched
|
1467
|
if (this.vertexSearchHighlighting[vertex.symbolicName] !== undefined) {
|
1468
|
this.highlightSearchedVertexInGroup(vertex);
|
1469
|
}
|
1470
|
},
|
1471
|
|
1472
|
/**
|
1473
|
* Zobrazeni skupiny komponent v pravem sloupci.
|
1474
|
*/
|
1475
|
showGroupInRightPanel: function(group_name){
|
1476
|
// remove possible transformations
|
1477
|
$('#required' + group_name).removeAttr('transform');
|
1478
|
$('#provided' + group_name).removeAttr('transform');
|
1479
|
|
1480
|
// hide decomposed-spreat vertices
|
1481
|
$('ul[data-groupid=' + group_name + '] li').each(function() {
|
1482
|
id_vert = $(this).find('p').attr('data-vertexid');
|
1483
|
|
1484
|
$('g#vertex' + id_vert).hide();
|
1485
|
});
|
1486
|
|
1487
|
// set proper label
|
1488
|
var selected_group = this.groupManager.getGroup(group_name);
|
1489
|
$('#rightPanel #group' + group_name + ' #label' + group_name).html(selected_group.label);
|
1490
|
|
1491
|
$('#rightPanel #group'+group_name).show();
|
1492
|
|
1493
|
//odstraneni skupiny komponent
|
1494
|
$('#graph #gv_'+group_name).remove();
|
1495
|
|
1496
|
//skryti
|
1497
|
group2 = this.groupManager.getGroup(group_name);
|
1498
|
|
1499
|
$('ul[data-groupid=' + group_name + '] li').each(function() {
|
1500
|
id_vert = $(this).find('p').attr('data-vertexid');
|
1501
|
|
1502
|
for(var i = 0; i< group2.items.get(id_vert).edges.length; i++){
|
1503
|
var edge = group2.items.get(id_vert).edges[i];
|
1504
|
|
1505
|
if(edge.from.id == id_vert){
|
1506
|
edge.$selector.hide();
|
1507
|
} else {
|
1508
|
edge.$selector.hide();
|
1509
|
}
|
1510
|
}
|
1511
|
});
|
1512
|
|
1513
|
// check if opacity needs to be set to unconnected - for vertices grouped in the group
|
1514
|
var vertexList = selected_group.items.getAll();
|
1515
|
|
1516
|
// iterate through the object filled with vertices
|
1517
|
$.each(vertexList, function(key, value){
|
1518
|
// vertex is not excluded anymore
|
1519
|
value.excluded = true;
|
1520
|
|
1521
|
OffScreenKiv.detectAndSetUnconnectedInGraph(value);
|
1522
|
});
|
1523
|
|
1524
|
$('#includeAllComponents').show();
|
1525
|
},
|
1526
|
|
1527
|
/**
|
1528
|
* Called when group's left arrow icon is clicked in SeCo to display the group in the diagram area.
|
1529
|
*
|
1530
|
* @param idGroup identifier of a group
|
1531
|
*/
|
1532
|
showGroupInGraph: function(idGroup){
|
1533
|
var graph = $('#graph')[0];
|
1534
|
|
1535
|
var group = this.groupManager.getGroup(idGroup);
|
1536
|
var svg = SvgFactory.createGroup(group);
|
1537
|
|
1538
|
// add to the main graph svg
|
1539
|
graph.appendChild(svg);
|
1540
|
|
1541
|
// drag only by rectangle or the symbol
|
1542
|
var groupElement = $('#gv_' + idGroup + ' > rect, #symbol' + idGroup + ', #labelTextElement' + idGroup);
|
1543
|
groupElement.mousedown(group.idGroup, ViewportManager.groupVertexMousedownHandler);
|
1544
|
groupElement.mouseup(ViewportManager.viewportEndDraggingHandler);
|
1545
|
|
1546
|
// bind lollipop highlighting
|
1547
|
$('#provided' + idGroup).click(OffScreenKiv.groupHighlightProvided);
|
1548
|
$('#required' + idGroup).click(OffScreenKiv.groupHighlightRequired);
|
1549
|
|
1550
|
// bind label change that doesn't click if dragged
|
1551
|
var flag;
|
1552
|
$('#labelTextElement' + idGroup + ', #symbol' + idGroup).mousedown(function(){
|
1553
|
flag = 0;
|
1554
|
});
|
1555
|
$('#labelTextElement' + idGroup + ', #symbol' + idGroup).mousemove(function(){
|
1556
|
flag = 1;
|
1557
|
});
|
1558
|
$('#labelTextElement' + idGroup + ', #symbol' + idGroup).mouseup(function(){
|
1559
|
if (flag == 0) {
|
1560
|
$('#dialog').data('group', group)
|
1561
|
.data('groupLabel', $('#label' + group.idGroup))
|
1562
|
.data('isSvgElement', true)
|
1563
|
.dialog('open');
|
1564
|
}
|
1565
|
});
|
1566
|
|
1567
|
this.moveElementAfter(svg, group.idGroup);
|
1568
|
|
1569
|
// update the numbers in lollis
|
1570
|
this.updateCountOfProvidedAndRequired(group);
|
1571
|
|
1572
|
// check if opacity needs to be reset - for vertices grouped in the group
|
1573
|
var vertexList = group.items.getAll();
|
1574
|
|
1575
|
// iterate through the object filled with vertices
|
1576
|
$.each(vertexList, function(key, value){
|
1577
|
// vertex has became excluded from the diagram area
|
1578
|
value.excluded = false;
|
1579
|
|
1580
|
OffScreenKiv.detectAndResetReconnectedInGraph(value);
|
1581
|
});
|
1582
|
},
|
1583
|
|
1584
|
/**
|
1585
|
* Moves group element in DOM after it is created to have right z-index.
|
1586
|
*/
|
1587
|
moveElementAfter: function(group_elm, group_name){
|
1588
|
var coords = getCoordinates(group_elm.getAttribute('transform'));
|
1589
|
posX = coords.x;
|
1590
|
posY = coords.y;
|
1591
|
|
1592
|
posX_reset = posX;
|
1593
|
|
1594
|
group2 = this.groupManager.getGroup(group_name);
|
1595
|
group2.x = posX;
|
1596
|
group2.y = posY;
|
1597
|
|
1598
|
id_vert = 0;
|
1599
|
|
1600
|
$('ul[data-groupid=' + group_name + '] li').each(function() {
|
1601
|
id_vert = $(this).find('p').attr('data-vertexid');
|
1602
|
|
1603
|
var newX;
|
1604
|
var newY;
|
1605
|
|
1606
|
var lollipop;
|
1607
|
posX = posX_reset;
|
1608
|
posX = parseFloat(posX);
|
1609
|
posY = parseFloat(posY);
|
1610
|
|
1611
|
//posun pozice, aby byla komponenta vycentrovana
|
1612
|
hidden_component_width = $('g#vertex' + id_vert + ' rect').attr('width');
|
1613
|
|
1614
|
//vystredeni na stred
|
1615
|
posX = posX - (hidden_component_width/2) + 40;
|
1616
|
|
1617
|
group2.items.get(id_vert).x = posX;
|
1618
|
group2.items.get(id_vert).y = posY;
|
1619
|
|
1620
|
$vertexentTarget = $('g#vertex' + id_vert);
|
1621
|
$vertexentTarget.attr('transform', 'translate('+posX+','+posY+')');
|
1622
|
$vertexentTarget.trigger('click',{move_edges:true});
|
1623
|
|
1624
|
for(var i = 0; i< group2.items.get(id_vert).edges.length; i++){
|
1625
|
var edge = group2.items.get(id_vert).edges[i];
|
1626
|
var sizeOfRectFrom = getSizeOfRectangle(edge.from.name);
|
1627
|
var sizeOfRectTo = getSizeOfRectangle(edge.to.name);
|
1628
|
|
1629
|
if (edge.from.id == id_vert) {
|
1630
|
newX = group2.items.get(id_vert).edges[i].to.x + sizeOfRectTo/2;
|
1631
|
newY = group2.items.get(id_vert).edges[i].to.y + 13;
|
1632
|
lollipop = getLollipopPosition(posX + sizeOfRectFrom/2, posY +13 , newX, newY);
|
1633
|
|
1634
|
edge.$selector.children("line").attr('x1', posX + sizeOfRectFrom/2);
|
1635
|
edge.$selector.children("line").attr('y1', posY + 13);
|
1636
|
edge.$selector.children("g").attr('transform', 'rotate(' + lollipop.angle + ',' + lollipop.x + ',' + lollipop.y + ') translate('+ lollipop.x + ',' + lollipop.y + ')');
|
1637
|
|
1638
|
ViewportManager.preventTickRotation(edge, lollipop);
|
1639
|
ViewportManager.preventCrossRotation(edge, lollipop);
|
1640
|
|
1641
|
//hrana k vrcholu se zobrazi pouze pokud je vrchol zobrazen
|
1642
|
if ($('#vertex'+ edge.to.id)[0].isVisible() ||
|
1643
|
($('#rightPanel li#li'+edge.to.id).is(':visible') === false && $('#rightPanel li#li'+edge.to.id).length > 0)
|
1644
|
) {
|
1645
|
edge.$selector.show();
|
1646
|
}
|
1647
|
|
1648
|
} else {
|
1649
|
newX = group2.items.get(id_vert).edges[i].from.x + sizeOfRectFrom/2;
|
1650
|
newY = group2.items.get(id_vert).edges[i].from.y + 13;
|
1651
|
lollipop = getLollipopPosition(newX, newY, posX + sizeOfRectTo/2, posY + 13);
|
1652
|
|
1653
|
edge.$selector.children("line").attr('x2', posX + sizeOfRectTo/2);
|
1654
|
edge.$selector.children("line").attr('y2', posY + 13);
|
1655
|
edge.$selector.children("g").attr('transform', 'rotate(' + lollipop.angle + ',' + lollipop.x + ',' + lollipop.y + ') translate('+ lollipop.x + ',' + lollipop.y + ')');
|
1656
|
|
1657
|
ViewportManager.preventTickRotation(edge, lollipop);
|
1658
|
ViewportManager.preventCrossRotation(edge, lollipop);
|
1659
|
|
1660
|
//hrana k vrcholu se zobrazi pouze pokud je vrchol zobrazen
|
1661
|
if ($('g#vertex'+ edge.from.id)[0].isVisible() ||
|
1662
|
($('#rightPanel #li'+edge.from.id).is(':visible') === false && $('#rightPanel li#li'+edge.from.id).length > 0)
|
1663
|
) {
|
1664
|
edge.$selector.show();
|
1665
|
}
|
1666
|
}
|
1667
|
}
|
1668
|
|
1669
|
|
1670
|
//skryti komponenty
|
1671
|
$vertexentTarget.hide();
|
1672
|
});
|
1673
|
|
1674
|
$('#rightPanel div#group' + group_name).hide();
|
1675
|
|
1676
|
// set it as decomposed initially
|
1677
|
group2.decompose = false;
|
1678
|
},
|
1679
|
|
1680
|
/**
|
1681
|
* Displays a group of components as a detached viewport in the diagram area.
|
1682
|
*
|
1683
|
* @param idGroup ID of the group
|
1684
|
*/
|
1685
|
showGroupInViewport: function(idGroup) {
|
1686
|
$('#gv_'+ idGroup).remove();
|
1687
|
|
1688
|
var groupViewport = $('#groupViewport_'+ idGroup);
|
1689
|
|
1690
|
if (groupViewport.length !== 0) {
|
1691
|
groupViewport.show();
|
1692
|
return;
|
1693
|
}
|
1694
|
|
1695
|
var group = this.groupManager.getGroup(idGroup);
|
1696
|
group.decompose = true;
|
1697
|
|
1698
|
// positions
|
1699
|
var coords = {
|
1700
|
x: stringToFloat(group.x),
|
1701
|
y: stringToFloat(group.y) + 5,
|
1702
|
};
|
1703
|
|
1704
|
var width = 600;
|
1705
|
var height = 300;
|
1706
|
|
1707
|
// move other nodes to make space for viewport
|
1708
|
var boundaries = {
|
1709
|
top: coords.y,
|
1710
|
bottom: coords.y + height,
|
1711
|
left: coords.x,
|
1712
|
right: coords.x + width,
|
1713
|
};
|
1714
|
|
1715
|
ViewportManager.moveNodes(boundaries);
|
1716
|
|
1717
|
// add to the main graph svg
|
1718
|
$('#graph .edges').after(SvgFactory.createGroupViewport(group, coords));
|
1719
|
|
1720
|
|
1721
|
// bind drag
|
1722
|
var viewportElement = $('#graph #groupViewport_' + idGroup + ' .handle');
|
1723
|
viewportElement.mousedown(idGroup, ViewportManager.viewportMousedownHandler);
|
1724
|
viewportElement.mouseup(ViewportManager.viewportEndDraggingHandler);
|
1725
|
|
1726
|
|
1727
|
// bind label change
|
1728
|
$('#labelTextElement' + idGroup).click(function(){
|
1729
|
$('#dialog').data('group', group)
|
1730
|
.data('groupLabel', $('#label' + group.idGroup))
|
1731
|
.data('isSvgElement', true)
|
1732
|
.dialog('open');
|
1733
|
});
|
1734
|
|
1735
|
|
1736
|
// remove edges
|
1737
|
$('ul[data-groupid=' + idGroup + '] li').each(function() {
|
1738
|
vertexId = $(this).find('p').attr('data-vertexid');
|
1739
|
for (var i = 0; i < group.items.get(vertexId).edges.length; i++) {
|
1740
|
var edge = group.items.get(vertexId).edges[i];
|
1741
|
|
1742
|
if (edge.from.id == vertexId) {
|
1743
|
edge.$selector.hide();
|
1744
|
} else {
|
1745
|
edge.$selector.hide();
|
1746
|
}
|
1747
|
}
|
1748
|
});
|
1749
|
|
1750
|
// iterate through the object filled with vertices
|
1751
|
$.each(group.items.getAll(), function(key, value){
|
1752
|
// vertex is not excluded anymore
|
1753
|
value.excluded = true;
|
1754
|
|
1755
|
OffScreenKiv.detectAndSetUnconnectedInGraph(value);
|
1756
|
});
|
1757
|
},
|
1758
|
|
1759
|
/**
|
1760
|
* Nifty little snippet to parse the transform attribute into usable a format
|
1761
|
* @param transformString Value of the transform attribute
|
1762
|
*/
|
1763
|
|
1764
|
parseTransform: function(transformString)
|
1765
|
{
|
1766
|
|
1767
|
var b={};
|
1768
|
for (var i in transformString = String(transformString).match(/(\w+\((\-?\d+\.?\d*e?\-?\d*,?)+\))+/g))
|
1769
|
{
|
1770
|
var c = String(transformString[i]).match(/[\w\.\-]+/g);
|
1771
|
b[c.shift()] = c;
|
1772
|
}
|
1773
|
return b;
|
1774
|
|
1775
|
},
|
1776
|
|
1777
|
/**
|
1778
|
* Hides the detached viewport of a group displayed in graph and displays it as a simple group node instead.
|
1779
|
* @param idGroup ID of the group
|
1780
|
*/
|
1781
|
hideGroupViewport: function(idGroup) {
|
1782
|
//$('#gv_'+ idGroup).show();
|
1783
|
|
1784
|
var group = this.groupManager.getGroup(idGroup);
|
1785
|
|
1786
|
var viewportTransform = $('#groupViewport_' + idGroup + ' > .viewportTransform');
|
1787
|
var coords = getCoordinates(viewportTransform[0].getAttribute('transform'));
|
1788
|
|
1789
|
group.x = coords.x;
|
1790
|
group.y = coords.y - 5;
|
1791
|
|
1792
|
this.showGroupInGraph(idGroup);
|
1793
|
|
1794
|
var groupViewport = $('#groupViewport_'+ idGroup);
|
1795
|
if (groupViewport.length) {
|
1796
|
groupViewport.remove();
|
1797
|
$('.edge-viewport-out').remove();
|
1798
|
return;
|
1799
|
}
|
1800
|
},
|
1801
|
|
1802
|
/**
|
1803
|
* Odstraneni vsech komponent ze skupiny
|
1804
|
* @param idGroup ID of the group
|
1805
|
*/
|
1806
|
removeAllComponentFromGroup: function(idGroup){
|
1807
|
//show group of components in graph
|
1808
|
$('#rightPanel #group'+ idGroup +' .deleteItemGroup').each(function() {
|
1809
|
$(this).trigger('click');
|
1810
|
});
|
1811
|
|
1812
|
var group = $('#gv_'+ idGroup);
|
1813
|
if (group.length) {
|
1814
|
group.remove();
|
1815
|
}
|
1816
|
|
1817
|
var viewport = $('#groupViewport_'+ idGroup);
|
1818
|
if (viewport.length) {
|
1819
|
viewport.remove();
|
1820
|
$('.edge-viewport-out').remove();
|
1821
|
return;
|
1822
|
}
|
1823
|
},
|
1824
|
|
1825
|
/**
|
1826
|
* Count height of group in dependency of count of item in group.
|
1827
|
* Parameters: group - group
|
1828
|
*/
|
1829
|
countHeightOfGroup: function(group){
|
1830
|
var heightOneItem = 17;
|
1831
|
var height = heightOneItem*group.getGroupItemsLength();
|
1832
|
return height;
|
1833
|
},
|
1834
|
|
1835
|
/**
|
1836
|
* Edit height of group in dependency of count of item in group.
|
1837
|
* Parameters: group - group
|
1838
|
*/
|
1839
|
editHeightOfGroup: function(group){
|
1840
|
var height = this.countHeightOfGroup(group);
|
1841
|
var svg_new_height = height;
|
1842
|
var new_height = height;
|
1843
|
if ( svg_new_height < 60 ) {
|
1844
|
svg_new_height = 70;
|
1845
|
new_height = 56;
|
1846
|
} else {
|
1847
|
svg_new_height += 18;
|
1848
|
}
|
1849
|
$("#svgGroup" + group.idGroup).attr('height', svg_new_height);
|
1850
|
$("#gr" + group.idGroup).children('rect').attr('height', new_height);
|
1851
|
},
|
1852
|
|
1853
|
/**
|
1854
|
* Update count of provided end required packages.
|
1855
|
*/
|
1856
|
updateCountOfProvidedAndRequired: function(group){
|
1857
|
var dependence = null;
|
1858
|
var provided = 0, required = 0;
|
1859
|
|
1860
|
if(!GraphManager.isEfpGraph){ // legacy method
|
1861
|
provided = group.providedPackage.size();
|
1862
|
required = group.requiredPackage.size();
|
1863
|
} else { // count real dependancies for EFP graphs
|
1864
|
dependence = this.countDependenceGroup(group.idGroup);
|
1865
|
|
1866
|
provided = dependence.countFrom;
|
1867
|
required = dependence.countTo;
|
1868
|
}
|
1869
|
|
1870
|
$("#provided" + group.idGroup).children('text').text(provided);
|
1871
|
$("#required" + group.idGroup).children('text').text(required);
|
1872
|
},
|
1873
|
|
1874
|
/*
|
1875
|
* Cancels highlighting of provided neighbours of given vertex.
|
1876
|
* Parameters: vertex - vertex
|
1877
|
* id - id of element on which was be clicked
|
1878
|
*/
|
1879
|
disHighlightProvided: function(parentId, vertex){
|
1880
|
for (var i = 0; i < vertex.edges.length; i++) {
|
1881
|
var edgeId = vertex.edges[i].to.id;
|
1882
|
|
1883
|
$('#detailVertex' + (edgeId)).attr('class', 'detail colorNormal');
|
1884
|
}
|
1885
|
|
1886
|
$('#' + parentId).attr('class', 'whiteColor');
|
1887
|
for (var k = 0; k < vertex.edges.length; k++) {
|
1888
|
vertex.edges[k].to.$selector.attr('class', 'node vertex colorNormal');
|
1889
|
}
|
1890
|
},
|
1891
|
|
1892
|
|
1893
|
/**
|
1894
|
* Highlights of provided neighbour of given vertex.
|
1895
|
* Parameters: vertex - vertex
|
1896
|
* id - id of element on which was be clicked
|
1897
|
*/
|
1898
|
highlightProvided:function(parentId, vertex){
|
1899
|
var idd = getIndexFromId(parentId, 8) - 1;
|
1900
|
|
1901
|
for (var i = 0; i < vertex.edges.length; i++) {
|
1902
|
var edgeId = vertex.edges[i].to.id;
|
1903
|
|
1904
|
$('#detailVertex' + (edgeId)).attr('class', 'detail colorHighlightProvided');
|
1905
|
$('#detailVertex' + (idd+1)).attr('class', 'detail colorNormal');
|
1906
|
}
|
1907
|
|
1908
|
$('#' + parentId).attr('class', 'colorHighlightProvided');
|
1909
|
this.deselectHighlightSearchedVertices();
|
1910
|
for (var i = 0; i < vertex.edges.length; i++) {
|
1911
|
vertex.edges[i].to.$selector.attr('class', 'node vertex colorHighlightProvided');
|
1912
|
}
|
1913
|
},
|
1914
|
|
1915
|
/**
|
1916
|
* Cancels highlighting of required neighbour of given vertex.
|
1917
|
* Parameters: vertex - vertex
|
1918
|
* id - id of element on which was be clicked
|
1919
|
*/
|
1920
|
disHighlightRequired: function(id, vertex){
|
1921
|
for (var i = 0; i < vertex.edges.length; i++) {
|
1922
|
var edgeId = vertex.edges[i].from.id;
|
1923
|
|
1924
|
$('#detailVertex' + (edgeId)).attr('class', 'detail colorNormal');
|
1925
|
}
|
1926
|
|
1927
|
$('#' + id).attr('class', 'whiteColor');
|
1928
|
for (var l = 0; l < vertex.edges.length; l++) {
|
1929
|
vertex.edges[l].from.$selector.attr('class', 'node vertex colorNormal');
|
1930
|
}
|
1931
|
},
|
1932
|
|
1933
|
/**
|
1934
|
* Highlights of required neighbour of given vertex.
|
1935
|
* Parameters: vertex - vertex
|
1936
|
* id - id of element on which was be clicked
|
1937
|
*/
|
1938
|
highlightRequired:function(parentId, vertex){
|
1939
|
var idd = getIndexFromId(parentId, 8) - 1;
|
1940
|
|
1941
|
for (var i = 0; i < vertex.edges.length; i++) {
|
1942
|
var edgeId = vertex.edges[i].from.id;
|
1943
|
|
1944
|
$('#detailVertex' + (edgeId)).attr('class', 'detail colorHighlightRequired');
|
1945
|
$('#detailVertex' + (idd+1)).attr('class', 'detail colorNormal');
|
1946
|
}
|
1947
|
|
1948
|
|
1949
|
$('#' + parentId).attr('class', 'colorHighlightRequired'); // tohle je zvyrazneni lizatka
|
1950
|
this.deselectHighlightSearchedVertices();
|
1951
|
for (var j = 0; j < vertex.edges.length; j++) {
|
1952
|
vertex.edges[j].from.$selector.attr('class', 'node vertex colorHighlightRequired');
|
1953
|
}
|
1954
|
},
|
1955
|
|
1956
|
/**
|
1957
|
* Event calls action disHighlightProvided or highlightProvided depending on what element was clicked.
|
1958
|
* Parameters: e - event
|
1959
|
*/
|
1960
|
highlightProvidedEvent: function(e){
|
1961
|
var parentId = e.target.parentElement.id;
|
1962
|
var id = getIndexFromId(parentId, 8) - 1;
|
1963
|
var vertex = GraphManager.graph.vertices[id];
|
1964
|
this.deselectHighlightSearchedVertices();
|
1965
|
|
1966
|
if ($('#' + parentId).attr('class') != 'whiteColor') {
|
1967
|
this.disHighlightProvided(parentId, vertex);
|
1968
|
} else {
|
1969
|
this.highlightProvided(parentId, vertex);
|
1970
|
}
|
1971
|
|
1972
|
if (($('#provided' + (id+1)).attr('class') != 'whiteColor') && ($('#required' + (id+1)).attr('class') != 'whiteColor')) {
|
1973
|
$('#detailVertex' + (id+1)).unbind('click');
|
1974
|
$('#detailVertex' + (id+1)).click(this.notHighlightNeighbour);
|
1975
|
} else {
|
1976
|
$('#detailVertex' + (id+1)).unbind('click');
|
1977
|
$('#detailVertex' + (id+1)).click(this.highlightAllNeighbour);
|
1978
|
}
|
1979
|
},
|
1980
|
|
1981
|
/**
|
1982
|
* Event calls action disHighlightRequired or highlightRequired depending on what element was clicked.
|
1983
|
* Parameters: e - event
|
1984
|
*/
|
1985
|
highlightRequiredEvent: function(e){
|
1986
|
var parentId = e.target.parentElement.id;
|
1987
|
var id = getIndexFromId(parentId, 8) - 1;
|
1988
|
var vertex = GraphManager.graph.vertices[id];
|
1989
|
|
1990
|
if ($('#' + parentId).attr('class') != 'whiteColor') {
|
1991
|
this.disHighlightRequired(parentId, vertex);
|
1992
|
}else {
|
1993
|
this.highlightRequired(parentId, vertex);
|
1994
|
}
|
1995
|
|
1996
|
if (($('#provided' + (id+1)).attr('class') != 'whiteColor') && ($('#required' + (id+1)).attr('class') != 'whiteColor')) {
|
1997
|
$('#detailVertex' + (id+1)).unbind('click');
|
1998
|
$('#detailVertex' + (id+1)).click(this.notHighlightNeighbour);
|
1999
|
} else {
|
2000
|
$('#detailVertex' + (id+1)).unbind('click');
|
2001
|
$('#detailVertex' + (id+1)).click(this.highlightAllNeighbour);
|
2002
|
}
|
2003
|
},
|
2004
|
|
2005
|
/**
|
2006
|
* Cancels all highlighting of neigbour given vertex.
|
2007
|
* Parameters: vertex - vertex
|
2008
|
* id - id of element on which was be clicked
|
2009
|
*/
|
2010
|
disHighlihgtAll: function(id, vertex){
|
2011
|
for(var i = 0; i < vertex.edges.length; i++){
|
2012
|
var edgeFrom = vertex.edges[i].from;
|
2013
|
var edgeTo = vertex.edges[i].to;
|
2014
|
|
2015
|
$('#detailVertex' + (edgeFrom.id)).attr('class', 'detail colorNormal');
|
2016
|
$('#detailVertex' + (edgeTo.id)).attr('class', 'detail colorNormal');
|
2017
|
|
2018
|
edgeFrom.$selector.attr('class', 'node vertex colorNormal');
|
2019
|
edgeTo.$selector.attr('class', 'node vertex colorNormal');
|
2020
|
|
2021
|
if (vertex.id === edgeFrom.id) {
|
2022
|
vertex.edges[i].$selector.css('stroke', '');
|
2023
|
} else if (vertex.id === edgeTo.id) {
|
2024
|
vertex.edges[i].$selector.css('stroke', '');
|
2025
|
}
|
2026
|
}
|
2027
|
|
2028
|
$('#provided'+ id).attr('class', 'whiteColor');
|
2029
|
$('#required'+ id).attr('class', 'whiteColor');
|
2030
|
},
|
2031
|
|
2032
|
/**
|
2033
|
* Event calls action disHighlihgtAll after click to given element.
|
2034
|
* Parameters: e - event
|
2035
|
*/
|
2036
|
notHighlightNeighbour: function(e){
|
2037
|
var id = getIndexFromId(e.target.parentElement.id, 12) - 1;
|
2038
|
var vertex = GraphManager.graph.vertices[id];
|
2039
|
|
2040
|
this.disHighlihgtAll((id+1), vertex);
|
2041
|
$('#' + e.target.parentElement.id).unbind('click', this.notHighlightNeighbour);
|
2042
|
$('#' + e.target.parentElement.id).click(this.highlightAllNeighbour);
|
2043
|
},
|
2044
|
|
2045
|
/**
|
2046
|
* Highlights all neigbours given vertex.
|
2047
|
* Parameters: vertex - vertex
|
2048
|
* id - id of element on which was be clicked
|
2049
|
*/
|
2050
|
highlihgtAll: function(id, vertex) {
|
2051
|
this.deselectHighlightSearchedVertices();
|
2052
|
|
2053
|
for (var i = 0; i < vertex.edges.length; i++){
|
2054
|
var edgeFrom = vertex.edges[i].from;
|
2055
|
var edgeTo = vertex.edges[i].to;
|
2056
|
|
2057
|
$('#detailVertex' + (edgeFrom.id)).attr('class', 'detail colorHighlightRequired');
|
2058
|
$('#detailVertex' + (edgeTo.id)).attr('class', 'detail colorHighlightProvided');
|
2059
|
$('#detailVertex' + (id)).attr('class', 'detail colorNormal');
|
2060
|
|
2061
|
edgeFrom.$selector.attr('class', 'node vertex colorHighlightRequired');
|
2062
|
edgeTo.$selector.attr('class', 'node vertex colorHighlightProvided');
|
2063
|
|
2064
|
if (vertex.id === edgeFrom.id) {
|
2065
|
vertex.edges[i].$selector[0].classList.remove('edge--dimmed');
|
2066
|
} else if (vertex.id === edgeTo.id) {
|
2067
|
vertex.edges[i].$selector[0].classList.remove('edge--dimmed');
|
2068
|
}
|
2069
|
}
|
2070
|
|
2071
|
$('#provided'+ id).attr('class', 'colorHighlightProvided');
|
2072
|
$('#required'+ id).attr('class', 'colorHighlightRequired');
|
2073
|
},
|
2074
|
|
2075
|
/**
|
2076
|
* Event calls action highlihgtAll after click to given element.
|
2077
|
* Parameters: e - event
|
2078
|
*/
|
2079
|
highlightAllNeighbour: function(e){
|
2080
|
var id = getIndexFromId(e.target.parentElement.id, 12) - 1;
|
2081
|
var vertex = GraphManager.graph.vertices[id];
|
2082
|
this.highlihgtAll((id+1), vertex);
|
2083
|
|
2084
|
$('#' + e.target.parentElement.id).unbind('click', this.highlightAllNeighbour);
|
2085
|
$('#' + e.target.parentElement.id).click(this.notHighlightNeighbour);
|
2086
|
},
|
2087
|
|
2088
|
/**
|
2089
|
* Cancels highlighting of all neighbors (provided) of vertex in group.
|
2090
|
* Parameters: e - event
|
2091
|
*/
|
2092
|
groupDisHighlightProvided: function(e){
|
2093
|
var providedElement = e.target.parentElement.id;
|
2094
|
|
2095
|
var id = findId(e.target);
|
2096
|
var group = this.groupManager.getGroup(id);
|
2097
|
|
2098
|
for (var key in group.items) {
|
2099
|
if (group.items.contains(key)) {
|
2100
|
this.disHighlightProvided(providedElement, group.items.get(key));
|
2101
|
}
|
2102
|
}
|
2103
|
|
2104
|
$('#' + providedElement).unbind('click', this.groupDisHightlightProvided);
|
2105
|
$('#' + providedElement).click(this.groupHighlightProvided);
|
2106
|
|
2107
|
if (($('#provided' + id).attr('class') != 'whiteColor') && ($('#required' + id).attr('class') != 'whiteColor')) {
|
2108
|
$('#gr' + id).unbind('click',this.groupHighlightRequiredAndProvided);
|
2109
|
$('#gr' + id).click(this.groupDisHighlightRequiredAndProvided);
|
2110
|
} else {
|
2111
|
$('#gr' + id).unbind('click', this.groupDisHighlightRequiredAndProvided);
|
2112
|
$('#gr' + id).click(this.groupHighlightRequiredAndProvided);
|
2113
|
}
|
2114
|
},
|
2115
|
|
2116
|
/**
|
2117
|
* Highlights all neighbors (provided) of vertex in group.
|
2118
|
* Parameters: e - event
|
2119
|
*/
|
2120
|
groupHighlightProvided: function(e){
|
2121
|
var providedElement = e.target.parentElement.id;
|
2122
|
|
2123
|
var id = findId(e.target);
|
2124
|
var group = this.groupManager.getGroup(id);
|
2125
|
|
2126
|
for (var key in group.items) {
|
2127
|
if (group.items.contains(key)) {
|
2128
|
this.highlightProvided(providedElement, group.items.get(key));
|
2129
|
}
|
2130
|
}
|
2131
|
|
2132
|
$('#' + providedElement).unbind('click',this.groupHighlightProvided);
|
2133
|
$('#' + providedElement).click(this.groupDisHighlightProvided);
|
2134
|
|
2135
|
if (($('#provided' + id).attr('class') != 'whiteColor') && ($('#required' + id).attr('class') != 'whiteColor')) {
|
2136
|
$('#gr' + id).unbind('click',this.groupHighlightRequiredAndProvided);
|
2137
|
$('#gr' + id).click(this.groupDisHighlightRequiredAndProvided);
|
2138
|
} else {
|
2139
|
$('#gr' + id).unbind('click', this.groupDisHighlightRequiredAndProvided);
|
2140
|
$('#gr' + id).click(this.groupHighlightRequiredAndProvided);
|
2141
|
}
|
2142
|
},
|
2143
|
|
2144
|
|
2145
|
/**
|
2146
|
* Cancels highlighting of all neighbors (required) of vertex in group.
|
2147
|
* Parameters: e - event
|
2148
|
*/
|
2149
|
groupDisHighlightRequired: function(e){
|
2150
|
var providedElement = e.target.parentElement.id;
|
2151
|
|
2152
|
var id = findId(e.target);
|
2153
|
var group = this.groupManager.getGroup(id);
|
2154
|
|
2155
|
for (var key in group.items) {
|
2156
|
if (group.items.contains(key)) {
|
2157
|
this.disHighlightRequired(providedElement, group.items.get(key));
|
2158
|
}
|
2159
|
}
|
2160
|
|
2161
|
$('#' + providedElement).unbind('click', this.groupDisHightlightRequired);
|
2162
|
$('#' + providedElement).click(this.groupHighlightRequired);
|
2163
|
|
2164
|
if (($('#provided' + id).attr('class') != 'whiteColor') && ($('#required' + id).attr('class') != 'whiteColor')) {
|
2165
|
$('#gr' + id).unbind('click',this.groupHighlightRequiredAndProvided);
|
2166
|
$('#gr' + id).click(this.groupDisHighlightRequiredAndProvided);
|
2167
|
} else {
|
2168
|
$('#gr' + id).unbind('click', this.groupDisHighlightRequiredAndProvided);
|
2169
|
$('#gr' + id).click(this.groupHighlightRequiredAndProvided);
|
2170
|
}
|
2171
|
},
|
2172
|
|
2173
|
/**
|
2174
|
* Highlights all neighbors (required) of vertex in group.
|
2175
|
* Parameters: e - event
|
2176
|
*/
|
2177
|
groupHighlightRequired: function(e){
|
2178
|
var providedElement = e.target.parentElement.id;
|
2179
|
|
2180
|
var id = findId(e.target);
|
2181
|
var group = this.groupManager.getGroup(id);
|
2182
|
|
2183
|
for (var key in group.items) {
|
2184
|
if (group.items.contains(key)) {
|
2185
|
this.highlightRequired(providedElement, group.items.get(key));
|
2186
|
}
|
2187
|
}
|
2188
|
|
2189
|
$('#' + providedElement).unbind('click',this.groupHighlightRequired);
|
2190
|
$('#' + providedElement).click(this.groupDisHighlightRequired);
|
2191
|
|
2192
|
if (($('#provided' + id).attr('class') != 'whiteColor') && ($('#required' + id).attr('class') != 'whiteColor')) {
|
2193
|
$('#gr' + id).unbind('click',this.groupHighlightRequiredAndProvided);
|
2194
|
$('#gr' + id).click(this.groupDisHighlightRequiredAndProvided);
|
2195
|
} else {
|
2196
|
$('#gr' + id).unbind('click', this.groupDisHighlightRequiredAndProvided);
|
2197
|
$('#gr' + id).click(this.groupHighlightRequiredAndProvided);
|
2198
|
}
|
2199
|
},
|
2200
|
|
2201
|
/**
|
2202
|
* Highlights required and provided components of a group in SeCo or viewport by its ID.
|
2203
|
* @param id the group identifier
|
2204
|
*/
|
2205
|
groupHighlight: function(id) {
|
2206
|
var group = this.groupManager.getGroup(id);
|
2207
|
|
2208
|
for (var key in group.items) {
|
2209
|
if (group.items.contains(key)) {
|
2210
|
this.highlihgtAll(id, group.items.get(key));
|
2211
|
}
|
2212
|
}
|
2213
|
|
2214
|
$('#required' + id).unbind('click',this.groupHighlightRequired);
|
2215
|
$('#required' + id).click(this.groupDisHighlightRequired);
|
2216
|
$('#provided' + id).unbind('click',this.groupHighlightProvided);
|
2217
|
$('#provided' + id).click(this.groupDisHighlightProvided);
|
2218
|
},
|
2219
|
|
2220
|
/**
|
2221
|
* Dishighlights required and provided components of a group in SeCo or viewport by its ID.
|
2222
|
* @param id the group identifier
|
2223
|
*/
|
2224
|
groupDisHighlight: function(id) {
|
2225
|
var group = this.groupManager.getGroup(id);
|
2226
|
|
2227
|
for (var key in group.items) {
|
2228
|
if (group.items.contains(key)) {
|
2229
|
this.disHighlihgtAll(id, group.items.get(key));
|
2230
|
}
|
2231
|
}
|
2232
|
|
2233
|
$('#required' + id).unbind('click',this.groupDisHighlightRequired);
|
2234
|
$('#required' + id).click(this.groupHighlightRequired);
|
2235
|
$('#provided' + id).unbind('click',this.groupDisHighlightProvided);
|
2236
|
$('#provided' + id).click(this.groupHighlightProvided);
|
2237
|
},
|
2238
|
|
2239
|
/**
|
2240
|
* Highlights all neighbors of vertex in group.
|
2241
|
* Parameters: e - event
|
2242
|
*/
|
2243
|
groupHighlightRequiredAndProvided: function(e) {
|
2244
|
var providedElement = e.target.parentElement.id;
|
2245
|
var id = findId(e.target);
|
2246
|
|
2247
|
$('#' + providedElement).unbind('click', this.groupHighlightRequiredAndProvided);
|
2248
|
$('#' + providedElement).click(this.groupDisHighlightRequiredAndProvided);
|
2249
|
|
2250
|
this.groupHighlight(id);
|
2251
|
},
|
2252
|
|
2253
|
/**
|
2254
|
* Cancels highlighting of all neighbors of vertex in group.
|
2255
|
* Parameters: e - event
|
2256
|
*/
|
2257
|
groupDisHighlightRequiredAndProvided: function(e){
|
2258
|
var providedElement = e.target.parentElement.id;
|
2259
|
var id = findId(e.target);
|
2260
|
|
2261
|
$('#' + providedElement).unbind('click', this.groupDisHighlightRequiredAndProvided);
|
2262
|
$('#' + providedElement).click(this.groupHighlightRequiredAndProvided);
|
2263
|
|
2264
|
this.groupDisHighlight(id);
|
2265
|
},
|
2266
|
|
2267
|
/**
|
2268
|
* Cancels highlighting of all group related lollipops.
|
2269
|
*/
|
2270
|
groupDisHighlightAllLollipops: function(){
|
2271
|
$('.colorHighlightProvided:not(.vertex), .colorHighlightRequired:not(.vertex)').attr('class', 'whiteColor');
|
2272
|
},
|
2273
|
|
2274
|
/**
|
2275
|
* Cancels highlighting of vertices which were searched.
|
2276
|
*/
|
2277
|
deselectHighlightSearchedVertices: function(){
|
2278
|
for (var key in this.vertexSearchHighlighting) {
|
2279
|
this.vertexSearchHighlighting[key][0].classList.remove('vertex--searched');
|
2280
|
|
2281
|
delete this.vertexSearchHighlighting[key];
|
2282
|
}
|
2283
|
|
2284
|
$('#countOfFinded').text(0);
|
2285
|
},
|
2286
|
|
2287
|
/**
|
2288
|
* Highlights the searched vertex in group.
|
2289
|
*/
|
2290
|
highlightSearchedVertexInGroup: function(vertex) {
|
2291
|
// set background of <p> in <li>
|
2292
|
var $selector = $('#li' + (vertex.id) + ' p');
|
2293
|
$selector[0].classList.add('vertex--searched');
|
2294
|
|
2295
|
this.vertexSearchHighlighting['li' + (vertex.id)] = $selector;
|
2296
|
},
|
2297
|
|
2298
|
/**
|
2299
|
* Highlights all vertex if their name contains searched string.
|
2300
|
*/
|
2301
|
search: function(){
|
2302
|
var vertices = GraphManager.graph.vertices;
|
2303
|
var text = $("#searchText").val();
|
2304
|
this.deselectHighlightSearchedVertices();
|
2305
|
|
2306
|
// handle empty search string - tool tip
|
2307
|
if (text === ""){
|
2308
|
$("#searchText").qtip({
|
2309
|
content: {
|
2310
|
text: "Please fill out this field."
|
2311
|
},
|
2312
|
style: {
|
2313
|
classes: "ui-tooltip-yellow ui-tooltip-rounded ui-tooltip-shadow"
|
2314
|
}
|
2315
|
}).qtip("show");
|
2316
|
|
2317
|
$(window).mousemove(function(){
|
2318
|
setTimeout(OffScreenKiv.hideTooltip, 2000);
|
2319
|
$(this).unbind("mousemove");
|
2320
|
});
|
2321
|
return;
|
2322
|
}
|
2323
|
|
2324
|
var countOfFound = 0;
|
2325
|
|
2326
|
for (var i = 0; i < vertices.length; i++) {
|
2327
|
if (vertices[i].name.toLowerCase().indexOf(text.toLowerCase()) >= 0) {
|
2328
|
$(vertices[i].$selector)[0].classList.add('vertex--searched');
|
2329
|
this.vertexSearchHighlighting[vertices[i].symbolicName] = vertices[i].$selector;
|
2330
|
countOfFound++;
|
2331
|
|
2332
|
// handle SeCo panel - w/o unconnected
|
2333
|
if (vertices[i].excluded === true) {
|
2334
|
var $selector = $('#detailVertex' + (vertices[i].id));
|
2335
|
|
2336
|
if ($selector.length) { // is not grouped
|
2337
|
$selector[0].classList.add('vertex--searched');
|
2338
|
|
2339
|
this.vertexSearchHighlighting['detailVertex' + (vertices[i].id)] = $selector;
|
2340
|
} else { // is grouped
|
2341
|
this.highlightSearchedVertexInGroup(vertices[i]);
|
2342
|
}
|
2343
|
}
|
2344
|
|
2345
|
// handle unconnected
|
2346
|
if (vertices[i].edges.length === 0) {
|
2347
|
// show the list if hidden
|
2348
|
if ($('#unconComps').is(':hidden')) {
|
2349
|
$('#unconComps').show();
|
2350
|
}
|
2351
|
|
2352
|
var $selector = $('#liuc' + (vertices[i].id) + ' p');
|
2353
|
$selector[0].classList.add('vertex--searched');
|
2354
|
|
2355
|
this.vertexSearchHighlighting['liuc' + (vertices[i].id)] = $selector;
|
2356
|
}
|
2357
|
}
|
2358
|
}
|
2359
|
|
2360
|
$("#countOfFinded").html(countOfFound);
|
2361
|
},
|
2362
|
|
2363
|
/**
|
2364
|
* Hide tooltip of search textfield.
|
2365
|
*/
|
2366
|
hideTooltip: function(){
|
2367
|
$("#searchText").qtip("hide");
|
2368
|
$("#searchText").qtip("destroy");
|
2369
|
},
|
2370
|
|
2371
|
/**
|
2372
|
* TODO could be merged with the "excludeVerticesWithMostEdgesToGroup" function
|
2373
|
* Excludes vertices whith the most edges from graph to the right panel.
|
2374
|
*/
|
2375
|
excludeVerticesWithMostEdges: function() {
|
2376
|
var vertices = GraphManager.graph.vertices;
|
2377
|
var sortedMappingToVertex = new Array(vertices.length);
|
2378
|
|
2379
|
for (var j = 0; j < vertices.length; j++) {
|
2380
|
sortedMappingToVertex[j] = j;
|
2381
|
}
|
2382
|
|
2383
|
sortedMappingToVertex.sort(function(a, b) {
|
2384
|
if(vertices[a].edges.length > vertices[b].edges.length){
|
2385
|
return -1;
|
2386
|
}
|
2387
|
if(vertices[a].edges.length == vertices[b].edges.length){
|
2388
|
return 0;
|
2389
|
}
|
2390
|
return 1;
|
2391
|
});
|
2392
|
|
2393
|
var countExcludedVertices = Math.round(sortedMappingToVertex.length*0.15);
|
2394
|
var vertex;
|
2395
|
if (countExcludedVertices >= 1) {
|
2396
|
$('input[name="actionMove"]:eq("move")').click();
|
2397
|
}
|
2398
|
|
2399
|
for (var i = 0; i < countExcludedVertices; i++) {
|
2400
|
vertex = vertices[sortedMappingToVertex[i]];
|
2401
|
|
2402
|
if (!vertex.excluded) {
|
2403
|
var e = jQuery.Event('mousedown');
|
2404
|
e.which = 1;
|
2405
|
e.target = vertex.$selector[0];
|
2406
|
this.showVertexInRightPanel(e);
|
2407
|
}
|
2408
|
}
|
2409
|
},
|
2410
|
|
2411
|
/**
|
2412
|
* Merge vertices whith the most edges to one group and excludes them from graph to the right panel.
|
2413
|
*/
|
2414
|
excludeVerticesWithMostEdgesToGroup: function() {
|
2415
|
var vertices = GraphManager.graph.vertices;
|
2416
|
var sortedMappingToVertex = new Array(vertices.length);
|
2417
|
|
2418
|
for (var j = 0; j < vertices.length; j++) {
|
2419
|
sortedMappingToVertex[j] = j;
|
2420
|
}
|
2421
|
|
2422
|
sortedMappingToVertex.sort(function(a, b) {
|
2423
|
if (vertices[a].edges.length > vertices[b].edges.length) {
|
2424
|
return -1;
|
2425
|
}
|
2426
|
if (vertices[a].edges.length == vertices[b].edges.length) {
|
2427
|
return 0;
|
2428
|
}
|
2429
|
return 1;
|
2430
|
});
|
2431
|
|
2432
|
var countExcludedVertices = Math.round(sortedMappingToVertex.length*0.15);
|
2433
|
var vertex;
|
2434
|
if (countExcludedVertices >= 1) {
|
2435
|
$('input[name="actionMove"]:eq("move")').click();
|
2436
|
}
|
2437
|
|
2438
|
var symbol = this.markSymbol.getMarkSymbol();
|
2439
|
var group;
|
2440
|
var idGroup;
|
2441
|
|
2442
|
for (var i = 0; i < countExcludedVertices; i++) {
|
2443
|
vertex = vertices[sortedMappingToVertex[i]];
|
2444
|
|
2445
|
if (!vertex.excluded) {
|
2446
|
vertex.symbol = symbol;
|
2447
|
idGroup = symbol[1].substring(1, symbol[1].length) + symbol[0];
|
2448
|
|
2449
|
if (i === 0) {
|
2450
|
this.addItemToContextMenu(symbol, vertex.id, vertex.name);
|
2451
|
group = new Group(vertex.symbol, idGroup);
|
2452
|
this.groupManager.addGroupToList(idGroup, group);
|
2453
|
this.createGroupDetail(group, vertex.symbol);
|
2454
|
}
|
2455
|
|
2456
|
this.addVertexToGroup(idGroup, $("#vertex"+ vertex.id));
|
2457
|
}
|
2458
|
}
|
2459
|
|
2460
|
$('#includeAllComponents').show();
|
2461
|
}
|
2462
|
};
|