Skip to content

Commit

Permalink
Further implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenthoms committed Oct 5, 2023
1 parent 9b9112e commit 74edfd3
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 16 deletions.
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";

import { DrawerContent, GuiState } from "@framework/GuiMessageBroker";
import { DrawerContent, GuiState, useGuiValue } from "@framework/GuiMessageBroker";
import { LayoutElement, Workbench } from "@framework/Workbench";
import { DataChannelVisualization } from "@framework/internal/components/Content/private-components/DataChannelVisualization";
import { NavBar } from "@framework/internal/components/NavBar";
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/framework/GuiMessageBroker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export enum GuiState {
SettingsPanelWidthInPercent = "settingsPanelWidthInPercent",
LoadingEnsembleSet = "loadingEnsembleSet",
ActiveModuleInstanceId = "activeModuleInstanceId",
DataChannelConnectionLayerVisible = "dataChannelConnectionLayerVisible",
}

export enum GuiEvent {
Expand Down Expand Up @@ -72,6 +73,7 @@ type GuiStateValueTypes = {
[GuiState.SettingsPanelWidthInPercent]: number;
[GuiState.LoadingEnsembleSet]: boolean;
[GuiState.ActiveModuleInstanceId]: string;
[GuiState.DataChannelConnectionLayerVisible]: boolean;
};

const defaultStates: Map<GuiState, any> = new Map();
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/framework/Workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Template } from "./TemplateRegistry";
import { WorkbenchServices } from "./WorkbenchServices";
import { WorkbenchSession } from "./WorkbenchSession";
import { loadEnsembleSetMetadataFromBackend } from "./internal/EnsembleSetLoader";
import { GlobalCursor } from "./internal/GlobalCursor";
import { PrivateWorkbenchServices } from "./internal/PrivateWorkbenchServices";
import { PrivateWorkbenchSettings } from "./internal/PrivateWorkbenchSettings";
import { WorkbenchSessionPrivate } from "./internal/WorkbenchSessionPrivate";
Expand All @@ -36,6 +37,7 @@ export class Workbench {
private _workbenchSettings: PrivateWorkbenchSettings;
private _broadcaster: Broadcaster;
private _guiMessageBroker: GuiMessageBroker;
private _globalCursor: GlobalCursor;
private _subscribersMap: { [key: string]: Set<() => void> };
private _layout: LayoutElement[];
private _perModuleRunningInstanceNumber: Record<string, number>;
Expand All @@ -47,6 +49,7 @@ export class Workbench {
this._workbenchSettings = new PrivateWorkbenchSettings();
this._broadcaster = new Broadcaster();
this._guiMessageBroker = new GuiMessageBroker();
this._globalCursor = new GlobalCursor();
this._subscribersMap = {};
this._layout = [];
this._perModuleRunningInstanceNumber = {};
Expand Down Expand Up @@ -85,6 +88,10 @@ export class Workbench {
return this._guiMessageBroker;
}

getGlobalCursor(): GlobalCursor {
return this._globalCursor;
}

private notifySubscribers(event: WorkbenchEvents): void {
const subscribers = this._subscribersMap[event];
if (!subscribers) return;
Expand Down
65 changes: 65 additions & 0 deletions frontend/src/framework/internal/GlobalCursor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
export enum GlobalCursorType {
Default = "default",
Copy = "copy",
Pointer = "pointer",
Grab = "grab",
Grabbing = "grabbing",
Crosshair = "crosshair",
Move = "move",
Text = "text",
Wait = "wait",
Help = "help",
Progress = "progress",
Cell = "cell",
VerticalText = "vertical-text",
Alias = "alias",
ContextMenu = "context-menu",
NoDrop = "no-drop",
NotAllowed = "not-allowed",
}

export class GlobalCursor {
private _cursorStack: GlobalCursorType[];
private _lastCursor: GlobalCursorType = GlobalCursorType.Default;

constructor() {
this._cursorStack = [];
}

private updateBodyCursor() {
if (this._lastCursor !== GlobalCursorType.Default) {
const oldCursorClass = `cursor-${this._lastCursor}`;
document.body.classList.remove(oldCursorClass);
}

if (this._cursorStack.length === 0) {
this._lastCursor = GlobalCursorType.Default;
return;
}

const newCursor = this._cursorStack[this._cursorStack.length - 1];
const newCursorClass = `cursor-${newCursor}`;
document.body.classList.add(newCursorClass);
this._lastCursor = newCursor;
}

setOverrideCursor(cursorType: GlobalCursorType) {
this._cursorStack.push(cursorType);
this.updateBodyCursor();
}

restoreOverrideCursor() {
if (this._cursorStack.length > 0) {
this._cursorStack.pop();
this.updateBodyCursor();
}
}

changeOverrideCursor(cursorType: GlobalCursorType) {
if (this._cursorStack.length > 0) {
this._cursorStack.pop();
}
this._cursorStack.push(cursorType);
this.updateBodyCursor();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from "react";

import { GuiEvent, GuiEventPayloads } from "@framework/GuiMessageBroker";
import { GuiEvent, GuiEventPayloads, GuiState, useGuiState } from "@framework/GuiMessageBroker";
import { Workbench } from "@framework/Workbench";
import { GlobalCursorType } from "@framework/internal/GlobalCursor";
import { useElementBoundingRect } from "@lib/hooks/useElementBoundingRect";
import { Point } from "@lib/utils/geometry";
import { resolveClassNames } from "@lib/utils/resolveClassNames";
Expand All @@ -27,7 +28,10 @@ export const DataChannelVisualization: React.FC<DataChannelVisualizationProps> =
const [originPoint, setOriginPoint] = React.useState<Point>({ x: 0, y: 0 });
const [currentPointerPosition, setCurrentPointerPosition] = React.useState<Point>({ x: 0, y: 0 });
const [currentChannelName, setCurrentChannelName] = React.useState<string | null>(null);
const [showDataChannelConnections, setShowDataChannelConnections] = React.useState<boolean>(false);
const [showDataChannelConnections, setShowDataChannelConnections] = useGuiState(
props.workbench.getGuiMessageBroker(),
GuiState.DataChannelConnectionLayerVisible
);
const [highlightedDataChannelConnection, setHighlightedDataChannelConnection] = React.useState<{
moduleInstanceId: string;
dataChannelName: string;
Expand Down Expand Up @@ -58,7 +62,7 @@ export const DataChannelVisualization: React.FC<DataChannelVisualizationProps> =
};
setVisible(true);
setOriginPoint(currentOriginPoint);
document.body.classList.add("cursor-crosshair");
props.workbench.getGlobalCursor().setOverrideCursor(GlobalCursorType.Crosshair);
mousePressed = true;
setCurrentPointerPosition(currentOriginPoint);
setCurrentChannelName(null);
Expand All @@ -79,9 +83,7 @@ export const DataChannelVisualization: React.FC<DataChannelVisualizationProps> =
setVisible(false);
setEditDataChannelConnectionsForModuleInstanceId(null);
setShowDataChannelConnections(false);
document.body.classList.remove("cursor-crosshair");
document.body.classList.remove("cursor-not-allowed");
document.body.classList.remove("cursor-copy");
props.workbench.getGlobalCursor().restoreOverrideCursor();
}

function handlePointerUp() {
Expand Down Expand Up @@ -118,18 +120,15 @@ export const DataChannelVisualization: React.FC<DataChannelVisualizationProps> =
}

function handleNodeHover(payload: GuiEventPayloads[GuiEvent.DataChannelNodeHover]) {
document.body.classList.remove("cursor-crosshair");
if (payload.connectionAllowed) {
document.body.classList.add("cursor-copy");
props.workbench.getGlobalCursor().setOverrideCursor(GlobalCursorType.Copy);
} else {
document.body.classList.add("cursor-not-allowed");
props.workbench.getGlobalCursor().setOverrideCursor(GlobalCursorType.NotAllowed);
}
}

function handleNodeUnhover() {
document.body.classList.remove("cursor-copy");
document.body.classList.remove("cursor-not-allowed");
document.body.classList.add("cursor-crosshair");
props.workbench.getGlobalCursor().restoreOverrideCursor();
}

function handleEditDataChannelConnectionsRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const InputChannelNode: React.FC<InputChannelNodeProps> = (props) => {
}, [props.moduleInstanceId, props.inputName, props.workbench]);

React.useEffect(() => {
console.debug("effect");
let isHovered = false;
let isConnectable = false;
let moduleInstanceId = "";
Expand Down Expand Up @@ -111,6 +112,7 @@ export const InputChannelNode: React.FC<InputChannelNodeProps> = (props) => {
}

function handlePointerUp(e: PointerEvent) {
console.debug("pointer up", isHovered, isConnectable);
if (isHovered) {
if (isConnectable) {
props.onChannelConnect(props.inputName, moduleInstanceId, pointerEventToPoint(e));
Expand All @@ -130,17 +132,22 @@ export const InputChannelNode: React.FC<InputChannelNodeProps> = (props) => {
setConnectable(false);
isConnectable = false;
setEditDataChannelConnections(false);
console.debug("done");
}

function handlePointerMove(e: PointerEvent) {
const boundingRect = ref.current?.getBoundingClientRect();
if (boundingRect && rectContainsPoint(boundingRect, pointerEventToPoint(e))) {
setHovered(true);
isHovered = true;
console.debug("hovered");
return;
}
setHovered(false);
isHovered = false;
if (isHovered) {
setHovered(false);
isHovered = false;
console.debug("unhovered");
}
}

const removeDataChannelOriginPointerDownHandler = guiMessageBroker.subscribeToEvent(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";

import { DrawerContent, GuiEvent, GuiState, useGuiState } from "@framework/GuiMessageBroker";
import { DrawerContent, GuiEvent, GuiState, useGuiState, useGuiValue } from "@framework/GuiMessageBroker";
import { ModuleInstance } from "@framework/ModuleInstance";
import { Workbench } from "@framework/Workbench";
import { Point, pointDifference, pointRelativeToDomRect, pointerEventToPoint } from "@lib/utils/geometry";
Expand Down Expand Up @@ -38,6 +38,11 @@ export const ViewWrapper: React.FC<ViewWrapperProps> = (props) => {

const guiMessageBroker = props.workbench.getGuiMessageBroker();

const dataChannelConnectionsLayerVisible = useGuiValue(
guiMessageBroker,
GuiState.DataChannelConnectionLayerVisible
);

const timeRef = React.useRef<number | null>(null);

const [currentInputName, setCurrentInputName] = React.useState<string | null>(null);
Expand Down Expand Up @@ -86,6 +91,9 @@ export const ViewWrapper: React.FC<ViewWrapperProps> = (props) => {
}

function handlePointerUp() {
if (dataChannelConnectionsLayerVisible) {
return;
}
if (drawerContent === DrawerContent.ModulesList) {
if (!timeRef.current || Date.now() - timeRef.current < 800) {
handleModuleClick();
Expand Down

0 comments on commit 74edfd3

Please sign in to comment.