Projekt

Obecné

Profil

Stáhnout (77.4 KB) Statistiky
| Větev: | Tag: | Revize:
1 1e2b2c27 Tomáš Šimandl
/**
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
};