Skip to content
Snippets Groups Projects
node.ts 4.12 KiB
Newer Older
import { Graph } from "./graph";
import { GraphElement } from "./graphelement";
import { NodeType } from "./nodetype";
import { Link } from "./link";
import { GLOBAL_PARAMS } from "../helper/serializableitem";

const NODE_PARAMS = [
    "label",
    "icon",
    "description",
    "references",
    "video",
    "type",
    "banner",
    ...GLOBAL_PARAMS,
];
const NODE_SIM_PARAMS = ["index", "x", "y", "vx", "vy", "fx", "fy"]; // Based on https://github.com/d3/d3-force#simulation_nodes

export class Node extends GraphElement {
    public label: string;
    public description: string;
    public type: NodeType;
    public icon: string;
    public banner: string;
    public video: string;
    public references: string[];
    constructor(graph: Graph = undefined) {
        super(graph);
        this.isNode = true;
    }

    public setType(typeId: number) {
        // Is it even different?
        if (this.type.id === typeId) {
            return;
        }

        const newType = this.graph.getType(typeId);

        // Exists?
        if (newType === undefined) {
            return;
        }

        this.type = newType;

        // Store change
        this.graph.storeCurrentData(
            "Set type [" +
                newType.toString() +
                "] for [" +
                this.toString() +
                "]"
        );
    }

    public delete() {
        return this.graph.deleteNode(this);
    }

    public add(graph: Graph = this.graph) {
        this.graph = graph;
        if (this.graph == undefined) {
            return false;
        }

        return this.graph.addNode(this);
    }

    /**
     * Calculates a list of all connected links to the current node.
     * @returns Array containing all connected links.
     */
    public get links(): Link[] {
        const links: Link[] = [];

        this.graph.links.forEach((link) => {
            if (link.contains(this)) {
                links.push(link);
            }
        });

        return links;
    }

    /**
     * Calculates a list of all connected nodes to the current node.
     * @returns Array containing all connected nodes.
     */
    public get neighbors(): Node[] {
        const nodes: Node[] = [];

        this.links.forEach((link) => {
            // Find "other" node
            let otherNode = link.source;
            if (this.equals(otherNode)) {
                otherNode = link.target;
            }

            // Still undefined?
            if (otherNode == undefined) {
                // Link apparently not properly set up
                return;
            }

            // Add to list if doesn't exist
            if (!nodes.includes(otherNode)) {
                nodes.push(otherNode);
            }
        });

        return nodes;
    }

    /**
     * Connects a given node to itself. Only works if they are in the same graph.
     * @param node Other node to connect.
     * @returns The created link, if successful, otherwise undefined.
     */
    public connect(node: Node): Link {
        if (this.graph !== node.graph) {
            return undefined;
        }

        const link = new Link(this.graph);

        link.source = this;
        link.target = node;

        if (link.add()) {
            return link;
        }
    }

    public serialize(): any {
        return this.serializeProperties(NODE_PARAMS);
    }

    public getCleanInstance(): any {
        return {
            ...this.serialize(),
            ...this.serializeProperties(NODE_SIM_PARAMS),

    public static parse(raw: any): Node {
        const node: Node = new Node();

        if (raw.label !== undefined) {
            node.label = raw.label;
        } else {
            node.label = raw.name;
        }

        node.id = Number(raw.id);
        node.description = raw.description;
        node.type = NodeType.parse(raw.type);

        // Try to parse simulation parameters
        NODE_SIM_PARAMS.forEach((param) => {
            if (raw[param] === undefined) {
                return;
            }

            (node as any)[param] = raw[param];
        });


    public toString(): string {
        return this.label;
    }