Skip to content

Commit

Permalink
[sigma] propagate graph types into sigma code #1359
Browse files Browse the repository at this point in the history
  • Loading branch information
sim51 committed Feb 8, 2024
1 parent c89cdce commit 12428c6
Show file tree
Hide file tree
Showing 20 changed files with 257 additions and 125 deletions.
14 changes: 10 additions & 4 deletions packages/sigma/src/core/captors/captor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* ======================
* @module
*/
import { Attributes } from "graphology-types";

import { Coordinates, MouseCoords, TouchCoords, WheelCoords, TypedEventEmitter, EventsMapping } from "../../types";
import Sigma from "../../sigma";

Expand Down Expand Up @@ -103,13 +105,17 @@ export function getWheelDelta(e: WheelEvent): number {
/**
* Abstract class representing a captor like the user's mouse or touch controls.
*/
export default abstract class Captor<Events extends EventsMapping> extends TypedEventEmitter<Events> {
export default abstract class Captor<
Events extends EventsMapping,
N extends Attributes,
E extends Attributes,
G extends Attributes,
> extends TypedEventEmitter<Events> {
container: HTMLElement;
renderer: Sigma;
renderer: Sigma<N, E, G>;

constructor(container: HTMLElement, renderer: Sigma) {
constructor(container: HTMLElement, renderer: Sigma<N, E, G>) {
super();

// Properties
this.container = container;
this.renderer = renderer;
Expand Down
11 changes: 9 additions & 2 deletions packages/sigma/src/core/captors/mouse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Sigma's captor dealing with the user's mouse.
* @module
*/
import { Attributes } from "graphology-types";

import { CameraState, MouseCoords, WheelCoords } from "../../types";
import Sigma from "../../sigma";
import Captor, { getWheelDelta, getMouseCoords, getPosition, getWheelCoords } from "./captor";
Expand Down Expand Up @@ -43,7 +45,12 @@ export type MouseCaptorEvents = {
*
* @constructor
*/
export default class MouseCaptor extends Captor<MouseCaptorEvents> {
export default class MouseCaptor<N extends Attributes, E extends Attributes, G extends Attributes> extends Captor<
MouseCaptorEvents,
N,
E,
G
> {
// State
enabled = true;
draggedEvents = 0;
Expand All @@ -60,7 +67,7 @@ export default class MouseCaptor extends Captor<MouseCaptorEvents> {
currentWheelDirection: -1 | 0 | 1 = 0;
lastWheelTriggerTime?: number;

constructor(container: HTMLElement, renderer: Sigma) {
constructor(container: HTMLElement, renderer: Sigma<N, E, G>) {
super(container, renderer);

// Binding methods
Expand Down
11 changes: 9 additions & 2 deletions packages/sigma/src/core/captors/touch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* Sigma's captor dealing with touch.
* @module
*/
import { Attributes } from "graphology-types";

import { CameraState, Coordinates, Dimensions, TouchCoords } from "../../types";
import Captor, { getPosition, getTouchCoords, getTouchesArray } from "./captor";
import Sigma from "../../sigma";
Expand All @@ -29,7 +31,12 @@ export type TouchCaptorEvents = {
*
* @constructor
*/
export default class TouchCaptor extends Captor<TouchCaptorEvents> {
export default class TouchCaptor<N extends Attributes, E extends Attributes, G extends Attributes> extends Captor<
TouchCaptorEvents,
N,
E,
G
> {
enabled = true;
isMoving = false;
hasMoved = false;
Expand All @@ -43,7 +50,7 @@ export default class TouchCaptor extends Captor<TouchCaptorEvents> {
lastTouchesPositions?: Coordinates[];
lastTouches?: Touch[];

constructor(container: HTMLElement, renderer: Sigma) {
constructor(container: HTMLElement, renderer: Sigma<N, E, G>) {
super(container, renderer);

// Binding methods:
Expand Down
10 changes: 6 additions & 4 deletions packages/sigma/src/rendering/edge-labels.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { Attributes } from "graphology-types";

import { EdgeDisplayData, NodeDisplayData, PartialButFor } from "../types";
import { Settings } from "../settings";

export type EdgeLabelDrawingFunction = (
export type EdgeLabelDrawingFunction<N extends Attributes, E extends Attributes, G extends Attributes> = (
context: CanvasRenderingContext2D,
edgeData: PartialButFor<EdgeDisplayData, "label" | "color" | "size">,
sourceData: PartialButFor<NodeDisplayData, "x" | "y" | "size">,
targetData: PartialButFor<NodeDisplayData, "x" | "y" | "size">,
settings: Settings,
settings: Settings<N, E, G>,
) => void;

export function drawStraightEdgeLabel(
export function drawStraightEdgeLabel<N extends Attributes, E extends Attributes, G extends Attributes>(
context: CanvasRenderingContext2D,
edgeData: PartialButFor<EdgeDisplayData, "label" | "color" | "size">,
sourceData: PartialButFor<NodeDisplayData, "x" | "y" | "size">,
targetData: PartialButFor<NodeDisplayData, "x" | "y" | "size">,
settings: Settings,
settings: Settings<N, E, G>,
): void {
const size = settings.edgeLabelSize,
font = settings.edgeLabelFont,
Expand Down
62 changes: 41 additions & 21 deletions packages/sigma/src/rendering/edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
* @module
*/
import Sigma from "../sigma";
import { Attributes } from "graphology-types";
import { AbstractProgram, Program } from "./program";
import { NodeDisplayData, EdgeDisplayData, RenderParams } from "../types";
import { EdgeLabelDrawingFunction } from "./edge-labels";
import { indexToColor } from "../utils";

export abstract class AbstractEdgeProgram extends AbstractProgram {
static drawLabel: EdgeLabelDrawingFunction | undefined;
export abstract class AbstractEdgeProgram<
N extends Attributes,
E extends Attributes,
G extends Attributes,
> extends AbstractProgram<N, E, G> {
abstract drawLabel: EdgeLabelDrawingFunction<N, E, G> | undefined;

abstract process(
edgeIndex: number,
Expand All @@ -22,11 +27,16 @@ export abstract class AbstractEdgeProgram extends AbstractProgram {
): void;
}

export abstract class EdgeProgram<Uniform extends string = string>
extends Program<Uniform>
implements AbstractEdgeProgram
export abstract class EdgeProgram<
N extends Attributes,
E extends Attributes,
G extends Attributes,
Uniform extends string = string,
>
extends Program<N, E, G, Uniform>
implements AbstractEdgeProgram<N, E, G>
{
static drawLabel: EdgeLabelDrawingFunction | undefined = undefined;
drawLabel: EdgeLabelDrawingFunction<N, E, G> | undefined = undefined;

kill(): void {
return undefined;
Expand Down Expand Up @@ -60,12 +70,18 @@ export abstract class EdgeProgram<Uniform extends string = string>
): void;
}

class EdgeImageClass implements AbstractEdgeProgram {
static drawLabel: EdgeLabelDrawingFunction | undefined = undefined;

constructor(_gl: WebGLRenderingContext, _pickingBuffer: WebGLFramebuffer | null, _renderer: Sigma) {
class EdgeImageClass<
N extends Attributes = Attributes,
E extends Attributes = Attributes,
G extends Attributes = Attributes,
> implements AbstractEdgeProgram<N, E, G>
{
constructor(_gl: WebGLRenderingContext, _pickingBuffer: WebGLFramebuffer | null, _renderer: Sigma<N, E, G>) {
return this;
}

drawLabel: EdgeLabelDrawingFunction<N, E, G> | undefined = undefined;

kill(): void {
return undefined;
}
Expand All @@ -85,7 +101,11 @@ class EdgeImageClass implements AbstractEdgeProgram {
return undefined;
}
}
export type EdgeProgramType = typeof EdgeImageClass;
export type EdgeProgramType<
N extends Attributes = Attributes,
E extends Attributes = Attributes,
G extends Attributes = Attributes,
> = typeof EdgeImageClass<N, E, G>;

/**
* Helper function combining two or more programs into a single compound one.
Expand All @@ -96,21 +116,21 @@ export type EdgeProgramType = typeof EdgeImageClass;
* @param {function} drawLabel - An optional edge "draw label" function.
* @return {function}
*/
export function createEdgeCompoundProgram(
programClasses: Array<EdgeProgramType>,
drawLabel?: EdgeLabelDrawingFunction,
): EdgeProgramType {
return class EdgeCompoundProgram implements AbstractEdgeProgram {
static drawLabel = drawLabel;

programs: Array<AbstractEdgeProgram>;

constructor(gl: WebGLRenderingContext, pickingBuffer: WebGLFramebuffer | null, renderer: Sigma) {
export function createEdgeCompoundProgram<N extends Attributes, E extends Attributes, G extends Attributes>(
programClasses: Array<EdgeProgramType<N, E, G>>,
drawLabel?: EdgeLabelDrawingFunction<N, E, G>,
): EdgeProgramType<N, E, G> {
return class EdgeCompoundProgram implements AbstractEdgeProgram<N, E, G> {
programs: Array<AbstractEdgeProgram<N, E, G>>;

constructor(gl: WebGLRenderingContext, pickingBuffer: WebGLFramebuffer | null, renderer: Sigma<N, E, G>) {
this.programs = programClasses.map((Program) => {
return new Program(gl, pickingBuffer, renderer);
});
}

drawLabel = drawLabel;

reallocate(capacity: number): void {
this.programs.forEach((program) => program.reallocate(capacity));
}
Expand Down
9 changes: 5 additions & 4 deletions packages/sigma/src/rendering/node-hover.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Attributes } from "graphology-types";
import { Settings } from "../settings";
import { NodeDisplayData, PartialButFor } from "../types";
import { drawDiscNodeLabel } from "./node-labels";

export type NodeHoverDrawingFunction = (
export type NodeHoverDrawingFunction<N extends Attributes, E extends Attributes, G extends Attributes> = (
context: CanvasRenderingContext2D,
data: PartialButFor<NodeDisplayData, "x" | "y" | "size" | "label" | "color">,
settings: Settings,
settings: Settings<N, E, G>,
) => void;

/**
Expand All @@ -14,10 +15,10 @@ export type NodeHoverDrawingFunction = (
* - if the label box is bigger than node size => display a label box that contains the node with a shadow
* - else node with shadow and the label box
*/
export function drawDiscNodeHover(
export function drawDiscNodeHover<N extends Attributes, E extends Attributes, G extends Attributes>(
context: CanvasRenderingContext2D,
data: PartialButFor<NodeDisplayData, "x" | "y" | "size" | "label" | "color">,
settings: Settings,
settings: Settings<N, E, G>,
): void {
const size = settings.labelSize,
font = settings.labelFont,
Expand Down
9 changes: 5 additions & 4 deletions packages/sigma/src/rendering/node-labels.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Attributes } from "graphology-types";
import { NodeDisplayData, PartialButFor } from "../types";
import { Settings } from "../settings";

export type NodeLabelDrawingFunction = (
export type NodeLabelDrawingFunction<N extends Attributes, E extends Attributes, G extends Attributes> = (
context: CanvasRenderingContext2D,
data: PartialButFor<NodeDisplayData, "x" | "y" | "size" | "label" | "color">,
settings: Settings,
settings: Settings<N, E, G>,
) => void;

export function drawDiscNodeLabel(
export function drawDiscNodeLabel<N extends Attributes, E extends Attributes, G extends Attributes>(
context: CanvasRenderingContext2D,
data: PartialButFor<NodeDisplayData, "x" | "y" | "size" | "label" | "color">,
settings: Settings,
settings: Settings<N, E, G>,
): void {
if (!data.label) return;

Expand Down
72 changes: 45 additions & 27 deletions packages/sigma/src/rendering/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,36 @@
*
* @module
*/
import { Attributes } from "graphology-types";

import Sigma from "../sigma";
import { AbstractProgram, Program } from "./program";
import { NodeDisplayData, NonEmptyArray, RenderParams } from "../types";
import { NodeLabelDrawingFunction } from "./node-labels";
import { NodeHoverDrawingFunction } from "./node-hover";
import { indexToColor } from "../utils";

export abstract class AbstractNodeProgram extends AbstractProgram {
static drawLabel: NodeLabelDrawingFunction | undefined;
static drawHover: NodeHoverDrawingFunction | undefined;
export abstract class AbstractNodeProgram<
N extends Attributes,
E extends Attributes,
G extends Attributes,
> extends AbstractProgram<N, E, G> {
abstract drawLabel: NodeLabelDrawingFunction<N, E, G> | undefined;
abstract drawHover: NodeHoverDrawingFunction<N, E, G> | undefined;
abstract process(nodeIndex: number, offset: number, data: NodeDisplayData): void;
}

export abstract class NodeProgram<Uniform extends string = string>
extends Program<Uniform>
implements AbstractNodeProgram
export abstract class NodeProgram<
N extends Attributes,
E extends Attributes,
G extends Attributes,
Uniform extends string = string,
>
extends Program<N, E, G, Uniform>
implements AbstractNodeProgram<N, E, G>
{
static drawLabel: NodeLabelDrawingFunction | undefined = undefined;
static drawHover: NodeHoverDrawingFunction | undefined = undefined;
drawLabel: NodeLabelDrawingFunction<N, E, G> | undefined;
drawHover: NodeHoverDrawingFunction<N, E, G> | undefined;

kill(): void {
return undefined;
Expand All @@ -44,13 +55,15 @@ export abstract class NodeProgram<Uniform extends string = string>
abstract processVisibleItem(nodeIndex: number, i: number, data: NodeDisplayData): void;
}

class NodeImageClass implements AbstractNodeProgram {
static drawLabel: NodeLabelDrawingFunction | undefined = undefined;
static drawHover: NodeHoverDrawingFunction | undefined = undefined;

constructor(_gl: WebGLRenderingContext, _pickingBuffer: WebGLFramebuffer | null, _renderer: Sigma) {
class NodeImageClass<N extends Attributes, E extends Attributes, G extends Attributes>
implements AbstractNodeProgram<N, E, G>
{
constructor(_gl: WebGLRenderingContext, _pickingBuffer: WebGLFramebuffer | null, _renderer: Sigma<N, E, G>) {
return this;
}
drawLabel: NodeLabelDrawingFunction<N, E, G> | undefined;
drawHover: NodeHoverDrawingFunction<N, E, G> | undefined;

kill(): void {
return undefined;
}
Expand All @@ -64,7 +77,11 @@ class NodeImageClass implements AbstractNodeProgram {
return undefined;
}
}
export type NodeProgramType = typeof NodeImageClass;
export type NodeProgramType<
N extends Attributes = Attributes,
E extends Attributes = Attributes,
G extends Attributes = Attributes,
> = typeof NodeImageClass<N, E, G>;

/**
* Helper function combining two or more programs into a single compound one.
Expand All @@ -76,23 +93,24 @@ export type NodeProgramType = typeof NodeImageClass;
* @param {function} drawHover - An optional node "draw hover" function.
* @return {function}
*/
export function createNodeCompoundProgram(
programClasses: NonEmptyArray<NodeProgramType>,
drawLabel?: NodeLabelDrawingFunction,
drawHover?: NodeLabelDrawingFunction,
): NodeProgramType {
return class NodeCompoundProgram implements AbstractNodeProgram {
static drawLabel = drawLabel;
static drawHover = drawHover;

programs: NonEmptyArray<AbstractNodeProgram>;

constructor(gl: WebGLRenderingContext, pickingBuffer: WebGLFramebuffer | null, renderer: Sigma) {
export function createNodeCompoundProgram<N extends Attributes, E extends Attributes, G extends Attributes>(
programClasses: NonEmptyArray<NodeProgramType<N, E, G>>,
drawLabel?: NodeLabelDrawingFunction<N, E, G>,
drawHover?: NodeLabelDrawingFunction<N, E, G>,
): NodeProgramType<N, E, G> {
return class NodeCompoundProgram implements AbstractNodeProgram<N, E, G> {
programs: NonEmptyArray<AbstractNodeProgram<N, E, G>>;

constructor(gl: WebGLRenderingContext, pickingBuffer: WebGLFramebuffer | null, renderer: Sigma<N, E, G>) {
this.programs = programClasses.map((Program) => {
return new Program(gl, pickingBuffer, renderer);
}) as unknown as NonEmptyArray<AbstractNodeProgram>;
}) as unknown as NonEmptyArray<AbstractNodeProgram<N, E, G>>;
}

drawLabel = drawLabel;

drawHover = drawHover;

reallocate(capacity: number): void {
this.programs.forEach((program) => program.reallocate(capacity));
}
Expand Down
Loading

0 comments on commit 12428c6

Please sign in to comment.