Skip to content

Commit d4ccef3

Browse files
refactor: split index into multiple files (#52)
This PR moves all classes from `index.ts` into other new files. It also simplifies some function signatures, the `Device` constructor, and the `AddX` functions from the `viewportManager`. --------- Co-authored-by: Manuel Pol <[email protected]>
1 parent dba1457 commit d4ccef3

File tree

15 files changed

+357
-396
lines changed

15 files changed

+357
-396
lines changed

src/context.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Viewport } from "./graphics/viewport";
2+
import { DataGraph } from "./types/graphs/datagraph";
3+
import { ViewGraph } from "./types/graphs/viewgraph";
4+
import {
5+
loadFromLocalStorage,
6+
saveToLocalStorage,
7+
} from "./types/viewportManager";
8+
import { Layer } from "./types/devices/device";
9+
10+
export class GlobalContext {
11+
private viewport: Viewport = null;
12+
private datagraph: DataGraph;
13+
private viewgraph: ViewGraph;
14+
private saveIntervalId: NodeJS.Timeout | null = null;
15+
16+
initialize(viewport: Viewport) {
17+
this.viewport = viewport;
18+
loadFromLocalStorage(this);
19+
}
20+
21+
private setNetWork(datagraph: DataGraph, layer: Layer) {
22+
this.datagraph = datagraph;
23+
this.viewport.clear();
24+
this.viewgraph = new ViewGraph(this.datagraph, this.viewport, layer);
25+
}
26+
27+
load(datagraph: DataGraph, layer: Layer = Layer.Link) {
28+
this.setNetWork(datagraph, layer);
29+
this.setupAutoSave();
30+
saveToLocalStorage(this);
31+
}
32+
33+
getViewport() {
34+
return this.viewport;
35+
}
36+
37+
getViewGraph() {
38+
return this.viewgraph;
39+
}
40+
41+
getDataGraph() {
42+
return this.datagraph;
43+
}
44+
45+
private setupAutoSave() {
46+
this.clearAutoSave();
47+
48+
this.datagraph.subscribeChanges(() => {
49+
if (this.saveIntervalId) {
50+
clearInterval(this.saveIntervalId);
51+
}
52+
this.saveIntervalId = setInterval(() => {
53+
saveToLocalStorage(this);
54+
clearInterval(this.saveIntervalId);
55+
}, 100);
56+
});
57+
}
58+
59+
private clearAutoSave() {
60+
// Limpia el intervalo y evita duplicados
61+
if (this.saveIntervalId) {
62+
clearInterval(this.saveIntervalId);
63+
this.saveIntervalId = null;
64+
}
65+
}
66+
}

src/graphics/left_bar.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export class LeftBar {
2+
private leftBar: HTMLElement;
3+
4+
constructor(leftBar: HTMLElement) {
5+
this.leftBar = leftBar;
6+
}
7+
8+
static getFrom(document: Document) {
9+
return new LeftBar(document.getElementById("left-bar"));
10+
}
11+
12+
addButton(src: string, onClick: () => void, label: string) {
13+
const button = document.createElement("button");
14+
button.classList.add("icon-button");
15+
button.setAttribute("title", label); // Shows Text
16+
17+
button.onclick = onClick;
18+
this.leftBar.appendChild(button);
19+
20+
const img = document.createElement("img");
21+
img.src = src;
22+
img.classList.add("icon-img");
23+
button.appendChild(img);
24+
}
25+
}

src/graphics/right_bar.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
export class RightBar {
2+
private static instance: RightBar | null = null; // Unique instance
3+
private rightBar: HTMLElement;
4+
5+
private constructor(rightBar: HTMLElement) {
6+
this.rightBar = rightBar;
7+
this.initializeBaseContent();
8+
}
9+
10+
// Static method to get the unique instance of RightBar
11+
static getInstance() {
12+
// If an instance already exists, return it. If not, create it.
13+
if (!RightBar.instance) {
14+
const rightBarElement = document.getElementById("right-bar");
15+
if (!rightBarElement) {
16+
console.error("Element with ID 'right-bar' not found.");
17+
return null;
18+
}
19+
RightBar.instance = new RightBar(rightBarElement);
20+
}
21+
return RightBar.instance;
22+
}
23+
24+
// Initializes the base title and info container (called only once)
25+
private initializeBaseContent() {
26+
const title = document.createElement("h2");
27+
title.textContent = "Information";
28+
this.rightBar.appendChild(title);
29+
30+
const infoContent = document.createElement("div");
31+
infoContent.id = "info-content";
32+
this.rightBar.appendChild(infoContent);
33+
}
34+
35+
// Method to clear only the content of info-content
36+
clearContent() {
37+
const infoContent = this.rightBar.querySelector("#info-content");
38+
if (infoContent) {
39+
infoContent.innerHTML = ""; // Clears only the content of info-content
40+
}
41+
}
42+
43+
// Shows specific information of an element in info-content
44+
renderInfo(title: string, info: { label: string; value: string }[]) {
45+
this.clearContent(); // Clears before adding new content
46+
47+
const infoContent = document.getElementById("info-content");
48+
if (infoContent) {
49+
const header = document.createElement("h3");
50+
header.textContent = title;
51+
infoContent.appendChild(header);
52+
53+
info.forEach((item) => {
54+
const p = document.createElement("p");
55+
p.innerHTML = `<strong>${item.label}:</strong> ${item.value}`;
56+
infoContent.appendChild(p);
57+
});
58+
}
59+
}
60+
61+
// Adds a standard button to the right-bar
62+
addButton(
63+
text: string,
64+
onClick: () => void,
65+
buttonClass = "right-bar-button",
66+
toggleSelected = false,
67+
) {
68+
const infoContent = document.getElementById("info-content");
69+
if (infoContent) {
70+
const button = document.createElement("button");
71+
button.classList.add(...buttonClass.split(" "));
72+
button.textContent = text;
73+
button.onclick = () => {
74+
onClick();
75+
if (toggleSelected) {
76+
button.classList.toggle("selected-button"); // Changes color on click
77+
}
78+
};
79+
infoContent.appendChild(button);
80+
}
81+
}
82+
83+
// Adds a select dropdown to the right-bar
84+
addDropdown(
85+
label: string,
86+
options: { value: string; text: string }[],
87+
selectId?: string,
88+
) {
89+
const infoContent = document.getElementById("info-content");
90+
const container = document.createElement("div");
91+
container.classList.add("dropdown-container");
92+
93+
const labelElement = document.createElement("label");
94+
labelElement.textContent = label;
95+
labelElement.classList.add("right-bar-label");
96+
97+
const select = document.createElement("select");
98+
select.classList.add("right-bar-select");
99+
if (selectId) select.id = selectId;
100+
101+
options.forEach((optionData) => {
102+
const option = document.createElement("option");
103+
option.value = optionData.value;
104+
option.textContent = optionData.text;
105+
select.appendChild(option);
106+
});
107+
108+
// Default onchange behavior: logs the selected value
109+
select.onchange = () => {
110+
console.log(`Selected ${label}:`, select.value);
111+
};
112+
113+
container.appendChild(labelElement);
114+
container.appendChild(select);
115+
infoContent.appendChild(container);
116+
}
117+
}

src/graphics/viewport.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { Graphics, EventSystem } from "pixi.js";
2+
import * as pixi_viewport from "pixi-viewport";
3+
import { selectElement } from "../types/viewportManager";
4+
5+
const WORLD_WIDTH = 10000;
6+
const WORLD_HEIGHT = 10000;
7+
8+
class Background extends Graphics {
9+
constructor() {
10+
super();
11+
this.rect(0, 0, WORLD_WIDTH, WORLD_HEIGHT).fill(0xe3e2e1);
12+
this.zIndex = 0;
13+
}
14+
15+
resize(width: number, height: number) {
16+
this.width = width;
17+
this.height = height;
18+
}
19+
}
20+
21+
export class Viewport extends pixi_viewport.Viewport {
22+
static usedPlugins = ["drag", "pinch"];
23+
24+
constructor(events: EventSystem) {
25+
super({
26+
worldWidth: WORLD_WIDTH,
27+
worldHeight: WORLD_HEIGHT,
28+
events: events,
29+
});
30+
this.moveCenter(WORLD_WIDTH / 2, WORLD_HEIGHT / 2);
31+
this.sortableChildren = true;
32+
this.initializeMovement();
33+
34+
this.addChild(new Background());
35+
36+
this.on("click", (event) => {
37+
// If the click target is the viewport itself, deselect any selected element
38+
if (event.target === this) {
39+
selectElement(null);
40+
}
41+
});
42+
}
43+
44+
clear() {
45+
this.removeChildren();
46+
this.addChild(new Background());
47+
this.moveCenter(WORLD_WIDTH / 2, WORLD_HEIGHT / 2);
48+
}
49+
50+
private initializeMovement() {
51+
this.drag()
52+
.pinch()
53+
.wheel()
54+
.clamp({ direction: "all" })
55+
// TODO: revisit when all icons are finalized
56+
.clampZoom({
57+
minHeight: 200,
58+
minWidth: 200,
59+
maxWidth: WORLD_WIDTH / 2,
60+
maxHeight: WORLD_HEIGHT / 2,
61+
});
62+
}
63+
64+
enableMovement() {
65+
for (const plugin of Viewport.usedPlugins) {
66+
this.plugins.resume(plugin);
67+
}
68+
}
69+
70+
disableMovement() {
71+
for (const plugin of Viewport.usedPlugins) {
72+
this.plugins.pause(plugin);
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)