Revize 8ed8cecb
Přidáno uživatelem Pavel Fidranský před více než 6 roky(ů)
sources/src/main/webapp/css/components/header.css | ||
---|---|---|
1 | 1 |
.header { |
2 | 2 |
position: relative; |
3 | 3 |
width: 100%; |
4 |
height: 60px; |
|
4 | 5 |
background: -webkit-linear-gradient(top, #f0f9ff 0%,#cbebff 47%,#a1dbff 100%); |
5 | 6 |
} |
6 | 7 |
|
sources/src/main/webapp/css/components/navbar.css | ||
---|---|---|
1 | 1 |
.navbar { |
2 |
height: 43px; |
|
2 | 3 |
background: -webkit-linear-gradient(top, #1e5799 0%,#7db9e8 100%); |
3 | 4 |
color: #cceefc; |
4 | 5 |
} |
sources/src/main/webapp/css/components/sidebar.css | ||
---|---|---|
1 | 1 |
.sidebar { |
2 |
z-index: 0; |
|
2 | 3 |
display: flex; |
3 | 4 |
flex-basis: 350px; |
4 | 5 |
flex-direction: column; |
... | ... | |
18 | 19 |
max-width: 100%; |
19 | 20 |
} |
20 | 21 |
|
21 |
.sidebar-navbar { |
|
22 |
position: fixed; |
|
23 |
width: 350px; |
|
24 |
padding-top: 10px; |
|
25 |
padding-bottom: 10px; |
|
26 |
} |
|
27 |
|
|
28 |
.sidebar-navbar .button { |
|
29 |
height: 30px; |
|
30 |
} |
|
31 |
|
|
32 |
.sidebar-navbar .button img { |
|
33 |
max-height: 20px; |
|
34 |
margin-top: -4px; |
|
35 |
margin-right: 5px; |
|
36 |
vertical-align: -4px; |
|
37 |
} |
|
38 |
|
|
39 |
.sidebar-container { |
|
40 |
margin-top: 50px; |
|
41 |
overflow-y: overlay; |
|
42 |
} |
|
43 |
|
|
44 | 22 |
.sidebar .node-container { |
45 | 23 |
position: relative; |
24 |
overflow-y: overlay; |
|
46 | 25 |
} |
47 | 26 |
|
48 | 27 |
.sidebar .node-container-title { |
49 | 28 |
font-size: 1.2em; |
50 | 29 |
padding-left: 0.5em; |
51 | 30 |
padding-right: 0.5em; |
31 |
cursor: pointer; |
|
52 | 32 |
} |
53 | 33 |
|
54 | 34 |
.sidebar .button-group { |
55 | 35 |
position: absolute; |
56 |
top: 0;
|
|
57 |
right: 1em; |
|
36 |
top: 1em;
|
|
37 |
right: 1.5em;
|
|
58 | 38 |
} |
59 | 39 |
|
60 | 40 |
.sidebar .button-group > * { |
... | ... | |
94 | 74 |
.sidebar .excluded-nodes { |
95 | 75 |
min-height: 20%; |
96 | 76 |
border-top: 1px solid #7db9e8; |
97 |
overflow-y: auto; |
|
98 | 77 |
} |
99 | 78 |
|
100 | 79 |
.sidebar .excluded-nodes .button-group { |
sources/src/main/webapp/js/components/attribute.js | ||
---|---|---|
25 | 25 |
]); |
26 | 26 |
|
27 | 27 |
return this._rootElement; |
28 |
};
|
|
28 |
} |
|
29 | 29 |
|
30 | 30 |
/** |
31 | 31 |
* @private |
sources/src/main/webapp/js/components/groupVertexList.js | ||
---|---|---|
36 | 36 |
this._rootElement.setAttribute('class', 'group-vertex-list'); |
37 | 37 |
|
38 | 38 |
return this._rootElement; |
39 |
};
|
|
39 |
} |
|
40 | 40 |
|
41 | 41 |
/** |
42 | 42 |
* Adds a new vertex to the list. Binds user interactions to local handler functions. |
sources/src/main/webapp/js/components/navbar.js | ||
---|---|---|
313 | 313 |
applyLayoutImg.setAttribute('src', 'images/layout_on.png'); |
314 | 314 |
|
315 | 315 |
layouting = true; |
316 |
layoutingInterval = window.setInterval(app.viewportComponent.forceDirected.run, 10);
|
|
316 |
layoutingInterval = window.setInterval(() => app.viewportComponent.forceDirected.run(), 10);
|
|
317 | 317 |
} |
318 | 318 |
}, |
319 | 319 |
}, [ |
sources/src/main/webapp/js/components/node.js | ||
---|---|---|
59 | 59 |
this._symbolListComponent.removeChild(symbol); |
60 | 60 |
} |
61 | 61 |
|
62 |
/** |
|
63 |
* @returns {string} Unique identifier of a graph node (group or vertex). |
|
64 |
*/ |
|
65 |
get uniqueId() { |
|
66 |
let prefix; |
|
67 |
if (this instanceof Vertex) { |
|
68 |
prefix = 'vertex-'; |
|
69 |
} else if (this instanceof Group) { |
|
70 |
prefix = 'group-'; |
|
71 |
} else { |
|
72 |
prefix = ''; |
|
73 |
} |
|
74 |
|
|
75 |
return prefix + this.id; |
|
76 |
} |
|
77 |
|
|
62 | 78 |
/** |
63 | 79 |
* @returns {Coordinates} Current position of the node. |
64 | 80 |
*/ |
sources/src/main/webapp/js/components/sidebar.js | ||
---|---|---|
8 | 8 |
/** @prop {SidebarExcludedNodeList} excludedNodeListComponent */ |
9 | 9 |
this.excludedNodeListComponent = new SidebarExcludedNodeList; |
10 | 10 |
/** @prop {Minimap} minimapComponent */ |
11 |
this.minimapComponent = new Minimap; |
|
11 |
this.minimapComponent = new Minimap('#graph');
|
|
12 | 12 |
/** @prop {StatusBar} statusBarComponent */ |
13 | 13 |
this.statusBarComponent = new StatusBar; |
14 | 14 |
} |
... | ... | |
18 | 18 |
class: 'sidebar', |
19 | 19 |
id: 'sidebar', |
20 | 20 |
}, [ |
21 |
DOM.h('nav', { |
|
22 |
class: 'sidebar-navbar', |
|
23 |
id: 'uploadMenu', |
|
24 |
}, [ |
|
25 |
// toggle unconnected list button |
|
26 |
DOM.h('button', { |
|
27 |
class: 'button', |
|
28 |
id: 'unconnectedButton', |
|
29 |
title: 'Unconnected nodes', |
|
30 |
innerText: 'Unconnected nodes', |
|
31 |
onClick: () => { |
|
32 |
this.unconnectedNodeListComponent.toggle(); |
|
33 |
app.redrawEdges(); |
|
34 |
}, |
|
35 |
}, [ |
|
36 |
DOM.h('img', { |
|
37 |
src: 'images/tochange/unconnected.gif', |
|
38 |
alt: 'Icon of "toggle unconnected nodes list" action', |
|
39 |
}), |
|
40 |
]), |
|
41 |
]), |
|
42 |
DOM.h('div', { |
|
43 |
class: 'sidebar-container', |
|
44 |
}, [ |
|
45 |
this.unconnectedNodeListComponent.render(), |
|
46 |
]), |
|
21 |
this.unconnectedNodeListComponent.render(), |
|
47 | 22 |
this.excludedNodeListComponent.render(), |
48 | 23 |
DOM.h('div', { |
49 | 24 |
class: 'sidebar-bottom', |
sources/src/main/webapp/js/components/sidebarExcludedNodeList.js | ||
---|---|---|
10 | 10 |
super({ |
11 | 11 |
title: 'Excluded nodes', |
12 | 12 |
class: 'node-container excluded-nodes', |
13 |
id: '', // TODO: remove as soon as Sidebar is reworked
|
|
13 |
id: 'excludedNodeListComponent',
|
|
14 | 14 |
}); |
15 | 15 |
} |
16 | 16 |
|
sources/src/main/webapp/js/components/sidebarNodeList.js | ||
---|---|---|
79 | 79 |
this._nodeListElement = DOM.h('ul', { |
80 | 80 |
class: 'node-list', |
81 | 81 |
}); |
82 |
|
|
83 |
// content |
|
84 |
const containerContent = DOM.h('div', { |
|
85 |
class: 'node-container-content', |
|
86 |
hidden: 'hidden', |
|
87 |
}, [ |
|
88 |
this._buttonGroupElement, |
|
89 |
this._sortOptionsElement, |
|
90 |
this._nodeListElement, |
|
91 |
]); |
|
82 | 92 |
|
83 | 93 |
// root |
84 | 94 |
this._rootElement = DOM.h('div', { |
... | ... | |
90 | 100 |
DOM.h('h2', { |
91 | 101 |
class: 'node-container-title', |
92 | 102 |
innerText: this._properties.title, |
103 |
onClick: () => { |
|
104 |
if (containerContent.hasAttribute('hidden')) { |
|
105 |
containerContent.removeAttribute('hidden'); |
|
106 |
} else { |
|
107 |
containerContent.setAttribute('hidden', 'hidden'); |
|
108 |
} |
|
109 |
|
|
110 |
app.redrawEdges(); |
|
111 |
}, |
|
93 | 112 |
}), |
94 |
this._buttonGroupElement, |
|
95 |
this._sortOptionsElement, |
|
96 |
this._nodeListElement, |
|
113 |
// content |
|
114 |
containerContent, |
|
97 | 115 |
]); |
98 | 116 |
|
99 | 117 |
return this._rootElement; |
... | ... | |
115 | 133 |
} |
116 | 134 |
|
117 | 135 |
_sortByCount(sortOrder) { |
118 |
nodeList.sort((a, b) => { |
|
119 |
var aCount = (a instanceof Group) ? a.countVertices : 1; |
|
120 |
var bCount = (b instanceof Group) ? b.countVertices : 1; |
|
136 |
this._nodeList.sort((a, b) => {
|
|
137 |
var aCount = (a instanceof Group) ? a.countVertices() : 1;
|
|
138 |
var bCount = (b instanceof Group) ? b.countVertices() : 1;
|
|
121 | 139 |
|
122 | 140 |
return sortOrder * (aCount - bCount); |
123 | 141 |
}); |
sources/src/main/webapp/js/components/sidebarUnconnectedNodeList.js | ||
---|---|---|
7 | 7 |
title: 'Unconnected vertices', |
8 | 8 |
class: 'node-container unconnected-nodes', |
9 | 9 |
id: 'unconnectedNodeListComponent', |
10 |
hidden: 'hidden', |
|
11 | 10 |
}); |
12 | 11 |
} |
13 | 12 |
|
sources/src/main/webapp/js/components/statusBar.js | ||
---|---|---|
41 | 41 |
*/ |
42 | 42 |
reset() { |
43 | 43 |
this._componentCounterElement.innerText = ''; |
44 |
};
|
|
44 |
} |
|
45 | 45 |
|
46 | 46 |
/** |
47 | 47 |
* @private |
sources/src/main/webapp/js/components/vertexContextMenuList.js | ||
---|---|---|
27 | 27 |
]); |
28 | 28 |
|
29 | 29 |
return this._rootElement; |
30 |
};
|
|
30 |
} |
|
31 | 31 |
|
32 | 32 |
/** |
33 | 33 |
* Sets a vertex that this context menu is bound to. The vertex is then added to a group. |
sources/src/main/webapp/js/services/forceDirected.js | ||
---|---|---|
1 |
/** |
|
2 |
* @constructor |
|
3 |
*/ |
|
4 |
function ForceDirected() { |
|
5 |
|
|
6 |
var forceField = {}; |
|
7 |
var canvas = 0; |
|
8 |
|
|
9 |
// parametry layoutu |
|
10 |
var inumber = 30; // pocet iteraci; default 300 |
|
11 |
var inumberClick = 20; // pocet iteraci u tlacitka |
|
12 |
var repulsiveStrength = 400; // odpudiva sila (prima umera); default 450 |
|
13 |
var attractiveStrength = 510; // pritazliva sila (neprima umera, nesmi byt 0); default 110 |
|
14 |
var dampeningEffect = 1000; // tlumeni sily (nesmi byt 0); default 200 |
|
15 |
var borderRatio = 1; // hranice layoutu (cislo kterym se deli velikost canvasu) |
|
16 |
// tahle funkce se mi nelibi, je treba to vyresit jinak, nici to layout (nechat na 1) |
|
1 |
class ForceDirected { |
|
2 |
/** |
|
3 |
* @constructor |
|
4 |
*/ |
|
5 |
constructor() { |
|
6 |
this._forceField = {}; |
|
7 |
this._canvas = 0; |
|
8 |
|
|
9 |
// parametry layoutu |
|
10 |
this._repulsiveStrength = 400; // odpudiva sila (prima umera); default 450 |
|
11 |
this._attractiveStrength = 510; // pritazliva sila (neprima umera, nesmi byt 0); default 110 |
|
12 |
this._dampeningEffect = 1000; // tlumeni sily (nesmi byt 0); default 200 |
|
13 |
this._borderRatio = 1; // hranice layoutu (cislo kterym se deli velikost canvasu) |
|
14 |
// tahle funkce se mi nelibi, je treba to vyresit jinak, nici to layout (nechat na 1) |
|
15 |
} |
|
17 | 16 |
|
18 | 17 |
/** |
19 | 18 |
* Force directed layout for visible components. |
20 | 19 |
*/ |
21 |
this.run = function() {
|
|
22 |
var border = canvas / borderRatio;
|
|
20 |
run() {
|
|
21 |
var border = this._canvas / this._borderRatio;
|
|
23 | 22 |
|
24 |
var visibleNodes = app.viewportComponent.nodeList,
|
|
25 |
otherVisibleNodes = [];
|
|
23 |
var visibleNodes = app.viewportComponent.nodeList;
|
|
24 |
var otherVisibleNodes = [];
|
|
26 | 25 |
|
27 | 26 |
for (let i = 0; i < visibleNodes.length; i++) { |
28 |
forceField[Utils.getUniqueId(visibleNodes[i])] = [0, 0];
|
|
27 |
this._forceField[visibleNodes[i].uniqueId] = [0, 0];
|
|
29 | 28 |
} |
30 | 29 |
|
31 | 30 |
// calculate repulsive force |
... | ... | |
53 | 52 |
var distance = Math.sqrt(sum); |
54 | 53 |
|
55 | 54 |
if (distance !== 0) { |
56 |
forceField[Utils.getUniqueId(currNode)][0] += Math.floor(x * (repulsiveStrength / distance));
|
|
57 |
forceField[Utils.getUniqueId(currNode)][1] += Math.floor(y * (repulsiveStrength / distance));
|
|
55 |
this._forceField[currNode.uniqueId][0] += Math.floor(x * (this._repulsiveStrength / distance));
|
|
56 |
this._forceField[currNode.uniqueId][1] += Math.floor(y * (this._repulsiveStrength / distance));
|
|
58 | 57 |
} |
59 | 58 |
} |
60 | 59 |
} |
61 | 60 |
|
62 | 61 |
// calculate attractive forces |
63 |
for (let i = 0; i < visibleNodes.length; i++){ |
|
62 |
for (let i = 0; i < visibleNodes.length; i++) {
|
|
64 | 63 |
let currNode = visibleNodes[i]; |
65 | 64 |
|
66 | 65 |
let inEdgeList = currNode.inEdgeList; |
... | ... | |
77 | 76 |
var sum = Math.pow(x, 2) + Math.pow(y, 2); |
78 | 77 |
var distance = Math.sqrt(sum); |
79 | 78 |
|
80 |
forceField[Utils.getUniqueId(currNode)][0] += Math.round(-1 * x * (distance / attractiveStrength));
|
|
81 |
forceField[Utils.getUniqueId(currNode)][1] += Math.round(-1 * y * (distance / attractiveStrength));
|
|
79 |
this._forceField[currNode.uniqueId][0] += Math.round(-1 * x * (distance / this._attractiveStrength));
|
|
80 |
this._forceField[currNode.uniqueId][1] += Math.round(-1 * y * (distance / this._attractiveStrength));
|
|
82 | 81 |
} |
83 | 82 |
|
84 | 83 |
let outEdgeList = currNode.outEdgeList; |
... | ... | |
95 | 94 |
var sum = Math.pow(x, 2) + Math.pow(y, 2); |
96 | 95 |
var distance = Math.sqrt(sum); |
97 | 96 |
|
98 |
forceField[Utils.getUniqueId(currNode)][0] += Math.round(-1 * x * (distance / attractiveStrength));
|
|
99 |
forceField[Utils.getUniqueId(currNode)][1] += Math.round(-1 * y * (distance / attractiveStrength));
|
|
97 |
this._forceField[currNode.uniqueId][0] += Math.round(-1 * x * (distance / this._attractiveStrength));
|
|
98 |
this._forceField[currNode.uniqueId][1] += Math.round(-1 * y * (distance / this._attractiveStrength));
|
|
100 | 99 |
} |
101 | 100 |
} |
102 | 101 |
|
... | ... | |
104 | 103 |
for (let i = 0; i < visibleNodes.length; i++){ |
105 | 104 |
var currNode = visibleNodes[i], |
106 | 105 |
|
107 |
halfCan = canvas / 2, |
|
106 |
halfCan = this._canvas / 2,
|
|
108 | 107 |
|
109 | 108 |
deltaX = currNode.position.x - halfCan, |
110 | 109 |
deltaY = currNode.position.y - halfCan; |
... | ... | |
112 | 111 |
// tohle drzi layout uprostred, chtelo by to vymyslet nejak lip, docela ho to kurvi |
113 | 112 |
/* |
114 | 113 |
if (deltaX > 0) { |
115 |
currNode.x = Math.min(currNode.position.x, (canvas/2)+border); |
|
114 |
currNode.x = Math.min(currNode.position.x, (this._canvas/2)+border);
|
|
116 | 115 |
} else { |
117 |
currNode.x = Math.max(currNode.position.x, (canvas/2)-border); |
|
116 |
currNode.x = Math.max(currNode.position.x, (this._canvas/2)-border);
|
|
118 | 117 |
} |
119 | 118 |
if (deltaY > 0) { |
120 |
currNode.y = Math.min(currNode.position.y, (canvas/2)+border); |
|
119 |
currNode.y = Math.min(currNode.position.y, (this._canvas/2)+border);
|
|
121 | 120 |
} else { |
122 |
currNode.y = Math.max(currNode.position.y, (canvas/2)-border); |
|
121 |
currNode.y = Math.max(currNode.position.y, (this._canvas/2)-border);
|
|
123 | 122 |
} |
124 | 123 |
*/ |
125 | 124 |
|
... | ... | |
138 | 137 |
} |
139 | 138 |
|
140 | 139 |
// force dampening |
141 |
var forceX = Math.floor(forceField[Utils.getUniqueId(currNode)][0] / dampeningEffect),
|
|
142 |
forceY = Math.floor(forceField[Utils.getUniqueId(currNode)][1] / dampeningEffect);
|
|
140 |
var forceX = Math.floor(this._forceField[currNode.uniqueId][0] / this._dampeningEffect),
|
|
141 |
forceY = Math.floor(this._forceField[currNode.uniqueId][1] / this._dampeningEffect);
|
|
143 | 142 |
|
144 | 143 |
// adding a random effect |
145 | 144 |
/* |
... | ... | |
159 | 158 |
currNode.move(coords); |
160 | 159 |
} |
161 | 160 |
} |
162 |
}; |
|
163 |
} |
|
161 |
} |
|
162 |
} |
sources/src/main/webapp/js/services/markSymbol.js | ||
---|---|---|
1 | 1 |
/** |
2 | 2 |
* This class represents creation of symbols. |
3 |
* @constructor |
|
4 | 3 |
*/ |
5 |
function MarkSymbol() { |
|
6 |
var CONST_MARK_SYMBOLS = ["☺", "☻", "♥", "♦", "♣", "♠", "♫", "☼", "►", "◄", |
|
7 |
"▲", "▼", "■", "▬", "░", "▒", "↕", "↑", "↓", "→", "←", "↔", "╣", "╩", "╠", |
|
8 |
"╚", "╝", "║", "╔", "╦", "═", "╬", "╗", "┴", "┬", "∟", "┌", "├", "┤", |
|
9 |
"⌂", "+", "-", "*", "÷", "×", "=", "±", "Ø", "~", "«", "»", "¤", "¶", "§", |
|
10 |
"‼", "!", "#", "$", "%", "&", "@", "A", "B", "C", "D", "E", "F", "G", "H", |
|
11 |
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", |
|
12 |
"X", "Y", "Z", "©", "®", "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", |
|
13 |
"λ", "μ", "ν", "ξ", "π", "ρ", "σ", "τ", "υ", "φ", "χ", "ψ", "ω", "Ω", "Φ", |
|
14 |
"Σ", "Λ", "Δ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; |
|
15 |
|
|
16 |
var CONST_MARK_COLORS = ["#DC143C", "#B23AEE", "#63B8FF", "#3D9140", "#B3EE3A", |
|
17 |
"#FFD700", "#B7B7B7", "#FF8000"]; |
|
18 |
|
|
19 |
var removeMarkSymbolList = []; |
|
20 |
var index = 0; |
|
21 |
var symbolIndex = -1; |
|
22 |
var colorIndex = -1; |
|
23 |
var startColorIndex = 0; |
|
4 |
class MarkSymbol { |
|
5 |
/** |
|
6 |
* @constructor |
|
7 |
*/ |
|
8 |
constructor() { |
|
9 |
this._removedSymbolList = []; |
|
10 |
this._index = 0; |
|
11 |
this._symbolIndex = -1; |
|
12 |
this._colorIndex = -1; |
|
13 |
this._startColorIndex = 0; |
|
14 |
} |
|
24 | 15 |
|
25 | 16 |
/** |
26 | 17 |
* Returns symbol with unique char and color. |
27 | 18 |
*/ |
28 |
this.getMarkSymbol = function() {
|
|
29 |
if (removeMarkSymbolList.length > 0) {
|
|
30 |
return removeMarkSymbolList.shift();
|
|
19 |
getMarkSymbol() {
|
|
20 |
if (this._removedSymbolList.length > 0) {
|
|
21 |
return this._removedSymbolList.shift();
|
|
31 | 22 |
} |
32 | 23 |
|
33 |
symbolIndex++; |
|
34 |
colorIndex++; |
|
24 |
this._symbolIndex++;
|
|
25 |
this._colorIndex++;
|
|
35 | 26 |
|
36 |
if (colorIndex === CONST_MARK_COLORS.length) {
|
|
37 |
colorIndex = 0; |
|
27 |
if (this._colorIndex === MarkSymbol.CONST_MARK_COLORS.length) {
|
|
28 |
this._colorIndex = 0;
|
|
38 | 29 |
} |
39 | 30 |
|
40 |
if (symbolIndex === CONST_MARK_SYMBOLS.length) {
|
|
41 |
if (startColorIndex === CONST_MARK_COLORS.length) {
|
|
42 |
startColorIndex = 0; |
|
31 |
if (this._symbolIndex === MarkSymbol.CONST_MARK_SYMBOLS.length) {
|
|
32 |
if (this._startColorIndex === MarkSymbol.CONST_MARK_COLORS.length) {
|
|
33 |
this._startColorIndex = 0;
|
|
43 | 34 |
} |
44 |
|
|
45 |
symbolIndex = 0; |
|
46 |
startColorIndex++; |
|
47 |
colorIndex = startColorIndex;
|
|
35 |
|
|
36 |
this._symbolIndex = 0;
|
|
37 |
this._startColorIndex++;
|
|
38 |
this._colorIndex = this._startColorIndex;
|
|
48 | 39 |
} |
49 | 40 |
|
50 |
return [CONST_MARK_SYMBOLS[symbolIndex], CONST_MARK_COLORS[colorIndex], 'symbol-' + index++]; |
|
51 |
}; |
|
41 |
return [ |
|
42 |
MarkSymbol.CONST_MARK_SYMBOLS[this._symbolIndex], |
|
43 |
MarkSymbol.CONST_MARK_COLORS[this._colorIndex], |
|
44 |
'symbol-' + this._index++, |
|
45 |
]; |
|
46 |
} |
|
52 | 47 |
|
53 | 48 |
/** |
54 | 49 |
* Save removed symbol (char + color) to the list of removes symbols. |
55 | 50 |
* |
56 | 51 |
* @param symbol symbol to be removed |
57 | 52 |
*/ |
58 |
this.removeSymbol = function(symbol) {
|
|
59 |
removeMarkSymbolList.push(symbol);
|
|
60 |
};
|
|
53 |
removeSymbol(symbol) {
|
|
54 |
this._removedSymbolList.push(symbol);
|
|
55 |
} |
|
61 | 56 |
} |
57 |
|
|
58 |
MarkSymbol.CONST_MARK_SYMBOLS = [ |
|
59 |
"☺", "☻", "♥", "♦", "♣", "♠", "♫", "☼", "►", "◄", "▲", "▼", "■", "▬", |
|
60 |
"░", "▒", "↕", "↑", "↓", "→", "←", "↔", "╣", "╩", "╠", "╚", "╝", "║", |
|
61 |
"╔", "╦", "═", "╬", "╗", "┴", "┬", "∟", "┌", "├", "┤", "⌂", "+", "-", |
|
62 |
"*", "÷", "×", "=", "±", "Ø", "~", "«", "»", "¤", "¶", "§", "‼", "!", |
|
63 |
"#", "$", "%", "&", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", |
|
64 |
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", |
|
65 |
"X", "Y", "Z", "©", "®", "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", |
|
66 |
"κ", "λ", "μ", "ν", "ξ", "π", "ρ", "σ", "τ", "υ", "φ", "χ", "ψ", "ω", |
|
67 |
"Ω", "Φ", "Σ", "Λ", "Δ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", |
|
68 |
]; |
|
69 |
|
|
70 |
MarkSymbol.CONST_MARK_COLORS = [ |
|
71 |
"#DC143C", "#B23AEE", "#63B8FF", "#3D9140", "#B3EE3A", |
|
72 |
"#FFD700", "#B7B7B7", "#FF8000", |
|
73 |
]; |
sources/src/main/webapp/js/services/zoom.js | ||
---|---|---|
1 |
/**
|
|
2 |
* @constructor
|
|
3 |
* @param {float} defaultScale Default zoom scale.
|
|
4 |
*/ |
|
5 |
function Zoom(defaultScale) {
|
|
6 |
/** @prop {float} scale Current zoom scale. */
|
|
7 |
this.scale = defaultScale || 1; |
|
8 |
|
|
9 |
var steps = [ 0.1, 0.25, 0.4, 0.55, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.45, 1.6, 1.75, 1.9, 2.5, 3.5, 5 ];
|
|
10 |
var step = steps.indexOf(this.scale);
|
|
11 |
|
|
1 |
class Zoom {
|
|
2 |
/**
|
|
3 |
* @param {float} scale Default zoom scale.
|
|
4 |
*/
|
|
5 |
constructor(scale = 1) {
|
|
6 |
this.scale = scale;
|
|
7 |
|
|
8 |
this._steps = [ 0.1, 0.25, 0.4, 0.55, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.45, 1.6, 1.75, 1.9, 2.5, 3.5, 5 ]; |
|
9 |
this._step = this._steps.indexOf(this.scale);
|
|
10 |
}
|
|
11 |
|
|
12 | 12 |
/** |
13 | 13 |
* Zoom in. If the current scale is maximal, it does nothing. |
14 | 14 |
*/ |
15 |
this.zoomIn = function() {
|
|
16 |
if (step === steps.length - 1) return;
|
|
15 |
zoomIn() {
|
|
16 |
if (this._step === this._steps.length - 1) return;
|
|
17 | 17 |
|
18 |
if (step === 0) { |
|
18 |
if (this._step === 0) {
|
|
19 | 19 |
document.querySelector('#zoomOut').classList.remove('disabled'); |
20 | 20 |
document.querySelector('#zoomOut img').src = 'images/zoom_out.png'; |
21 | 21 |
} |
22 | 22 |
|
23 |
step++; |
|
24 |
zoomChanged.call(this);
|
|
23 |
this._step++;
|
|
24 |
this._onChange();
|
|
25 | 25 |
|
26 |
if (step === steps.length - 1) {
|
|
26 |
if (this._step === this._steps.length - 1) {
|
|
27 | 27 |
document.querySelector('#zoomIn').classList.add('disabled'); |
28 | 28 |
document.querySelector('#zoomIn img').src = 'images/zoom_in_disabled.png'; |
29 | 29 |
} |
30 |
};
|
|
30 |
} |
|
31 | 31 |
|
32 | 32 |
/** |
33 | 33 |
* Zoom out. If the current scale is minimal, it does nothing. |
34 | 34 |
*/ |
35 |
this.zoomOut = function() {
|
|
36 |
if (step === 0) return; |
|
35 |
zoomOut() {
|
|
36 |
if (this._step === 0) return;
|
|
37 | 37 |
|
38 |
if (step === steps.length - 1) {
|
|
38 |
if (this._step === this._steps.length - 1) {
|
|
39 | 39 |
document.querySelector('#zoomIn').classList.remove('disabled'); |
40 | 40 |
document.querySelector('#zoomIn img').src = 'images/zoom_in.png'; |
41 | 41 |
} |
42 | 42 |
|
43 |
step--; |
|
44 |
zoomChanged.call(this);
|
|
43 |
this._step--;
|
|
44 |
this._onChange();
|
|
45 | 45 |
|
46 |
if (step === 0) { |
|
46 |
if (this._step === 0) {
|
|
47 | 47 |
document.querySelector('#zoomOut').classList.add('disabled'); |
48 | 48 |
document.querySelector('#zoomOut img').src = 'images/zoom_out_disabled.png'; |
49 | 49 |
} |
50 |
};
|
|
50 |
} |
|
51 | 51 |
|
52 | 52 |
/** |
53 | 53 |
* Change current zoom scale according to currently selected step. |
54 | 54 |
*/ |
55 |
function zoomChanged() {
|
|
56 |
this.scale = steps[step];
|
|
55 |
_onChange() {
|
|
56 |
this.scale = this._steps[this._step];
|
|
57 | 57 |
|
58 | 58 |
document.getElementById('zoomValue').innerText = Math.round(this.scale * 100) + '%'; |
59 | 59 |
document.getElementById('graph').setAttribute('transform', 'scale(' + this.scale + ')'); |
60 | 60 |
|
61 | 61 |
// TODO: zoom to mouse position / center |
62 |
|
|
62 |
|
|
63 | 63 |
app.redrawEdges(); |
64 | 64 |
} |
65 | 65 |
} |
sources/src/main/webapp/js/utils/utils.js | ||
---|---|---|
56 | 56 |
|
57 | 57 |
return false; |
58 | 58 |
} |
59 |
|
|
60 |
/** |
|
61 |
* @param {(Vertex|Group)} node Graph node. |
|
62 |
* @returns {string} Unique identifier of a graph node (group or vertex). |
|
63 |
*/ |
|
64 |
static getUniqueId(node) { |
|
65 |
if (Utils.isUndefined(node)) return ''; |
|
66 |
|
|
67 |
var prefix; |
|
68 |
if (node instanceof Vertex) { |
|
69 |
prefix = 'vertex-'; |
|
70 |
} else if (node instanceof Group) { |
|
71 |
prefix = 'group-'; |
|
72 |
} else { |
|
73 |
prefix = ''; |
|
74 |
} |
|
75 |
|
|
76 |
return prefix + node.id; |
|
77 |
} |
|
78 | 59 |
} |
Také k dispozici: Unified diff
various fixes