diff --git a/services/static-webserver/client/source/class/osparc/ui/basic/AvatarGroup.js b/services/static-webserver/client/source/class/osparc/ui/basic/AvatarGroup.js index be5991d1240b..acac59180318 100644 --- a/services/static-webserver/client/source/class/osparc/ui/basic/AvatarGroup.js +++ b/services/static-webserver/client/source/class/osparc/ui/basic/AvatarGroup.js @@ -36,6 +36,7 @@ qx.Class.define("osparc.ui.basic.AvatarGroup", { this.__orientation = orientation; this.__maxVisible = Math.max(1, Math.floor(maxWidth/size) - 1); // Ensure at least 1 visible avatar this.__userGroupIds = []; + this.__avatars = []; this.__isPointerInside = false; this.__onGlobalPointerMove = this.__onGlobalPointerMove.bind(this); diff --git a/services/static-webserver/client/source/class/osparc/workbench/BaseNodeUI.js b/services/static-webserver/client/source/class/osparc/workbench/BaseNodeUI.js deleted file mode 100644 index 6ea4228772cd..000000000000 --- a/services/static-webserver/client/source/class/osparc/workbench/BaseNodeUI.js +++ /dev/null @@ -1,308 +0,0 @@ -/* ************************************************************************ - - osparc - the simcore frontend - - https://osparc.io - - Copyright: - 2021 IT'IS Foundation, https://itis.swiss - - License: - MIT: https://opensource.org/licenses/MIT - - Authors: - * Odei Maiz (odeimaiz) - -************************************************************************ */ - -qx.Class.define("osparc.workbench.BaseNodeUI", { - extend: qx.ui.window.Window, - type: "abstract", - - construct: function() { - this.base(); - - const grid = new qx.ui.layout.Grid(4, 1); - grid.setColumnFlex(1, 1); - - this.set({ - appearance: "node-ui-cap", - layout: grid, - showMinimize: false, - showMaximize: false, - showClose: false, - showStatusbar: false, - resizable: false, - allowMaximize: false, - contentPadding: this.self().CONTENT_PADDING - }); - - this.getContentElement().setStyles({ - "border-radius": "4px" - }); - - const captionBar = this.getChildControl("captionbar"); - captionBar.set({ - cursor: "move", - paddingRight: 0, - paddingLeft: this.self().PORT_WIDTH - }); - - const menuBtn = this.__getMenuButton(); - captionBar.add(menuBtn, { - row: 0, - column: this.self().CAPTION_POS.MENU - }); - - const captionTitle = this.getChildControl("title"); - captionTitle.set({ - rich: true, - cursor: "move" - }); - captionTitle.addListener("appear", () => { - qx.event.Timer.once(() => { - const labelDom = captionTitle.getContentElement().getDomElement(); - const maxWidth = parseInt(labelDom.style.width); - // eslint-disable-next-line no-underscore-dangle - const width = captionTitle.__contentSize.width; - if (width > maxWidth) { - this.getNode().bind("label", captionTitle, "toolTipText"); - } - }, this, 50); - }); - - this.__nodeMoving = false; - }, - - properties: { - scale: { - check: "Number", - event: "changeScale", - nullable: false - }, - - isMovable: { - check: "Boolean", - init: true, - nullable: false - } - }, - - statics: { - PORT_HEIGHT: 18, - PORT_WIDTH: 11, - CONTENT_PADDING: 2, - PORT_CONNECTED: "@FontAwesome5Regular/dot-circle/18", - PORT_DISCONNECTED: "@FontAwesome5Regular/circle/18", - - CAPTION_POS: { - ICON: 0, // from qooxdoo - TITLE: 1, // from qooxdoo - LOCK: 2, - MARKER: 3, - DEPRECATED: 4, - MENU: 5 - }, - - captionHeight: function() { - return osparc.theme.Appearance.appearances["node-ui-cap/captionbar"].style().height || - osparc.theme.Appearance.appearances["node-ui-cap/captionbar"].style().minHeight; - } - }, - - events: { - "renameNode": "qx.event.type.Data", - "infoNode": "qx.event.type.Data", - "markerClicked": "qx.event.type.Data", - "removeNode": "qx.event.type.Data", - "edgeDragStart": "qx.event.type.Data", - "edgeDragOver": "qx.event.type.Data", - "edgeDrop": "qx.event.type.Data", - "edgeDragEnd": "qx.event.type.Data", - "nodeMovingStart": "qx.event.type.Event", - "nodeMoving": "qx.event.type.Event", - "nodeMovingStop": "qx.event.type.Event" - }, - - members: { - __inputLayout: null, - __outputLayout: null, - _optionsMenu: null, - _markerBtn: null, - _deleteBtn: null, - __nodeMoving: null, - - __getMenuButton: function() { - const optionsMenu = this._optionsMenu = new qx.ui.menu.Menu().set({ - position: "bottom-right" - }); - - const renameBtn = new qx.ui.menu.Button().set({ - label: this.tr("Rename"), - icon: "@FontAwesome5Solid/i-cursor/10" - }); - renameBtn.getChildControl("shortcut").setValue("F2"); - renameBtn.addListener("execute", () => this.fireDataEvent("renameNode", this.getNodeId())); - optionsMenu.add(renameBtn); - - const markerBtn = this._markerBtn = new qx.ui.menu.Button().set({ - icon: "@FontAwesome5Solid/bookmark/10", - visibility: "excluded" - }); - optionsMenu.add(markerBtn); - - const infoBtn = new qx.ui.menu.Button().set({ - label: this.tr("Information..."), - icon: "@FontAwesome5Solid/info/10" - }); - infoBtn.getChildControl("shortcut").setValue("I"); - infoBtn.addListener("execute", () => this.fireDataEvent("infoNode", this.getNodeId())); - optionsMenu.add(infoBtn); - - const deleteBtn = this._deleteBtn = new qx.ui.menu.Button().set({ - label: this.tr("Delete"), - icon: "@FontAwesome5Solid/trash/10" - }); - deleteBtn.getChildControl("shortcut").setValue("Del"); - deleteBtn.addListener("execute", () => this.fireDataEvent("removeNode", this.getNodeId())); - optionsMenu.add(deleteBtn); - - const menuBtn = new qx.ui.form.MenuButton().set({ - menu: optionsMenu, - icon: "@FontAwesome5Solid/ellipsis-v/9", - height: 18, - width: 18, - allowGrowX: false, - allowGrowY: false - }); - return menuBtn; - }, - - getInputPort: function() { - return this.__inputLayout; - }, - - getOutputPort: function() { - return this.__outputLayout; - }, - - _createPort: function(isInput, placeholder = false) { - let port = null; - const width = this.self().PORT_HEIGHT; - if (placeholder) { - port = new qx.ui.core.Spacer(width, width); - } else { - port = new qx.ui.basic.Image().set({ - source: this.self().PORT_DISCONNECTED, // disconnected by default - height: width, - draggable: true, - droppable: true, - width: width, - alignY: "top", - backgroundColor: "background-main" - }); - port.setCursor("pointer"); - port.getContentElement().setStyles({ - "border-radius": width+"px" - }); - port.isInput = isInput; - } - // make the ports exit the NodeUI - port.set({ - marginLeft: isInput ? (-10 + this.self().CONTENT_PADDING) : 0, - marginRight: isInput ? 0 : (-10 - this.self().CONTENT_PADDING) - }); - - this.add(port, { - row: 0, - column: isInput ? 0 : 2 - }); - - if (isInput) { - this.__inputLayout = port; - } else { - this.__outputLayout = port; - } - - return port; - }, - - getEdgePoint: function(port) { - const bounds = this.getCurrentBounds(); - const captionHeight = Math.max(this.getChildControl("captionbar").getSizeHint().height, this.self().captionHeight()); - const x = port.isInput ? bounds.left - 6 : bounds.left + bounds.width - 1; - const y = bounds.top + captionHeight + this.self().PORT_HEIGHT/2 + 2; - return [x, y]; - }, - - getCurrentBounds: function() { - let bounds = this.getBounds(); - let cel = this.getContentElement(); - if (cel) { - let domeEle = cel.getDomElement(); - if (domeEle) { - bounds.left = parseInt(domeEle.style.left); - bounds.top = parseInt(domeEle.style.top); - } - } - return bounds; - }, - - __scaleCoordinates: function(x, y) { - return { - x: parseInt(x / this.getScale()), - y: parseInt(y / this.getScale()) - }; - }, - - _setPositionFromEvent: function(e) { - const sideBarWidth = this.__dragRange.left; - const navigationBarHeight = this.__dragRange.top; - const native = e.getNativeEvent(); - const x = native.clientX + this.__dragLeft - sideBarWidth; - const y = native.clientY + this.__dragTop - navigationBarHeight; - const coords = this.__scaleCoordinates(x, y); - const insets = this.getLayoutParent().getInsets(); - this.setDomPosition(coords.x - (insets.left || 0), coords.y - (insets.top || 0)); - return coords; - }, - - // override qx.ui.core.MMovable - _onMovePointerMove: function(e) { - // Only react when dragging is active - if (!this.hasState("move") || !this.getIsMovable()) { - return; - } - e.stopPropagation(); - if (this.__nodeMoving === false) { - this.__nodeMoving = true; - this.fireEvent("nodeMovingStart"); - } - this.fireEvent("nodeMoving"); - }, - - // override qx.ui.core.MMovable - _onMovePointerUp : function(e) { - if (this.hasListener("roll")) { - this.removeListener("roll", this._onMoveRoll, this); - } - - // Only react when dragging is active - if (!this.hasState("move") || !this.getIsMovable()) { - return; - } - - this._onMovePointerMove(e); - - this.__nodeMoving = false; - this.fireEvent("nodeMovingStop"); - - // Remove drag state - this.removeState("move"); - - this.releaseCapture(); - - e.stopPropagation(); - }, - } -}); diff --git a/services/static-webserver/client/source/class/osparc/workbench/NodeUI.js b/services/static-webserver/client/source/class/osparc/workbench/NodeUI.js index 80fb1522b45e..b0f2bc4bec07 100644 --- a/services/static-webserver/client/source/class/osparc/workbench/NodeUI.js +++ b/services/static-webserver/client/source/class/osparc/workbench/NodeUI.js @@ -32,7 +32,7 @@ */ qx.Class.define("osparc.workbench.NodeUI", { - extend: osparc.workbench.BaseNodeUI, + extend: qx.ui.window.Window, /** * @param node {osparc.data.model.Node} Node owning the widget @@ -40,9 +40,61 @@ qx.Class.define("osparc.workbench.NodeUI", { construct: function(node) { this.base(arguments); + const grid = new qx.ui.layout.Grid(4, 1); + grid.setColumnFlex(1, 1); + + this.set({ + appearance: "node-ui-cap", + layout: grid, + showMinimize: false, + showMaximize: false, + showClose: false, + showStatusbar: false, + resizable: false, + allowMaximize: false, + contentPadding: this.self().CONTENT_PADDING + }); + + this.getContentElement().setStyles({ + "border-radius": "4px" + }); + + const captionBar = this.getChildControl("captionbar"); + captionBar.set({ + cursor: "move", + paddingRight: 0, + paddingLeft: this.self().PORT_WIDTH + }); + + const menuBtn = this.__getMenuButton(); + captionBar.add(menuBtn, { + row: 0, + column: this.self().CAPTION_POS.MENU + }); + + const captionTitle = this.getChildControl("title"); + captionTitle.set({ + rich: true, + cursor: "move" + }); + + this.__nodeMoving = false; + this.setNode(node); this.__resetNodeUILayout(); + + captionTitle.addListener("appear", () => { + qx.event.Timer.once(() => { + const labelDom = captionTitle.getContentElement().getDomElement(); + const maxWidth = parseInt(labelDom.style.width); + // eslint-disable-next-line no-underscore-dangle + const width = captionTitle.__contentSize.width; + if (width > maxWidth) { + this.getNode().bind("label", captionTitle, "toolTipText"); + } + }, this, 50); + }); }, properties: { @@ -63,16 +115,57 @@ qx.Class.define("osparc.workbench.NodeUI", { check: "String", nullable: true, apply: "__applyThumbnail" - } + }, + scale: { + check: "Number", + event: "changeScale", + nullable: false + }, + + isMovable: { + check: "Boolean", + init: true, + nullable: false + }, }, statics: { NODE_WIDTH: 180, NODE_HEIGHT: 80, FILE_NODE_WIDTH: 120, + PORT_HEIGHT: 18, + PORT_WIDTH: 11, + CONTENT_PADDING: 2, + PORT_CONNECTED: "@FontAwesome5Regular/dot-circle/18", + PORT_DISCONNECTED: "@FontAwesome5Regular/circle/18", + + CAPTION_POS: { + ICON: 0, // from qooxdoo + TITLE: 1, // from qooxdoo + LOCK: 2, + MARKER: 3, + DEPRECATED: 4, + MENU: 5 + }, + + captionHeight: function() { + return osparc.theme.Appearance.appearances["node-ui-cap/captionbar"].style().height || + osparc.theme.Appearance.appearances["node-ui-cap/captionbar"].style().minHeight; + }, }, events: { + "renameNode": "qx.event.type.Data", + "infoNode": "qx.event.type.Data", + "markerClicked": "qx.event.type.Data", + "removeNode": "qx.event.type.Data", + "edgeDragStart": "qx.event.type.Data", + "edgeDragOver": "qx.event.type.Data", + "edgeDrop": "qx.event.type.Data", + "edgeDragEnd": "qx.event.type.Data", + "nodeMovingStart": "qx.event.type.Event", + "nodeMoving": "qx.event.type.Data", + "nodeMovingStop": "qx.event.type.Event", "updateNodeDecorator": "qx.event.type.Event", "requestOpenLogger": "qx.event.type.Event", }, @@ -80,6 +173,12 @@ qx.Class.define("osparc.workbench.NodeUI", { members: { __thumbnail: null, __svgWorkbenchCanvas: null, + __inputLayout: null, + __outputLayout: null, + __optionsMenu: null, + __markerBtn: null, + __deleteBtn: null, + __nodeMoving: null, getNodeType: function() { return "service"; @@ -100,7 +199,7 @@ qx.Class.define("osparc.workbench.NodeUI", { }); this.getChildControl("captionbar").add(control, { row: 0, - column: osparc.workbench.BaseNodeUI.CAPTION_POS.LOCK + column: this.self().CAPTION_POS.LOCK }); break; case "marker": @@ -111,7 +210,7 @@ qx.Class.define("osparc.workbench.NodeUI", { }); this.getChildControl("captionbar").add(control, { row: 0, - column: osparc.workbench.BaseNodeUI.CAPTION_POS.MARKER + column: this.self().CAPTION_POS.MARKER }); control.addListener("tap", () => this.fireDataEvent("markerClicked", this.getNode().getNodeId())); break; @@ -122,7 +221,7 @@ qx.Class.define("osparc.workbench.NodeUI", { }); this.getChildControl("captionbar").add(control, { row: 0, - column: osparc.workbench.BaseNodeUI.CAPTION_POS.DEPRECATED + column: this.self().CAPTION_POS.DEPRECATED }); break; case "chips": { @@ -248,14 +347,14 @@ qx.Class.define("osparc.workbench.NodeUI", { icon: "@FontAwesome5Solid/play/10" }); node.attachHandlersToStartButton(startButton); - this._optionsMenu.addAt(startButton, 0); + this.__optionsMenu.addAt(startButton, 0); const stopButton = new qx.ui.menu.Button().set({ label: this.tr("Stop"), icon: "@FontAwesome5Solid/stop/10" }); node.attachHandlersToStopButton(stopButton); - this._optionsMenu.addAt(stopButton, 1); + this.__optionsMenu.addAt(stopButton, 1); } if (node.getKey().includes("parameter/int")) { @@ -264,14 +363,14 @@ qx.Class.define("osparc.workbench.NodeUI", { icon: "@FontAwesome5Solid/sync-alt/10" }); makeIterator.addListener("execute", () => node.convertToIterator("int"), this); - this._optionsMenu.add(makeIterator); + this.__optionsMenu.add(makeIterator); } else if (node.getKey().includes("data-iterator/int-range")) { const convertToParameter = new qx.ui.menu.Button().set({ label: this.tr("Convert to Parameter"), icon: "@FontAwesome5Solid/sync-alt/10" }); convertToParameter.addListener("execute", () => node.convertToParameter("int"), this); - this._optionsMenu.add(convertToParameter); + this.__optionsMenu.add(convertToParameter); } const lock = this.getChildControl("lock"); @@ -280,11 +379,11 @@ qx.Class.define("osparc.workbench.NodeUI", { converter: val => val ? "excluded" : "visible" }); } - this._markerBtn.show(); - this.getNode().bind("marker", this._markerBtn, "label", { + this.__markerBtn.show(); + this.getNode().bind("marker", this.__markerBtn, "label", { converter: val => val ? this.tr("Remove Marker") : this.tr("Add Marker") }); - this._markerBtn.addListener("execute", () => node.toggleMarker()); + this.__markerBtn.addListener("execute", () => node.toggleMarker()); const marker = this.getChildControl("marker"); const updateMarker = () => { @@ -298,7 +397,7 @@ qx.Class.define("osparc.workbench.NodeUI", { node.addListener("changeMarker", () => updateMarker()); updateMarker(); - node.getStudy().bind("pipelineRunning", this._deleteBtn, "enabled", { + node.getStudy().bind("pipelineRunning", this.__deleteBtn, "enabled", { converter: running => !running }); @@ -551,17 +650,17 @@ qx.Class.define("osparc.workbench.NodeUI", { __createPorts: function(isInput, draw) { if (draw === false) { - this._createPort(isInput, true); + this.__createPort(isInput, true); return; } - const port = this._createPort(isInput); + const port = this.__createPort(isInput); port.addListener("mouseover", () => { - port.setSource(osparc.workbench.BaseNodeUI.PORT_CONNECTED); + port.setSource(this.self().PORT_CONNECTED); }, this); port.addListener("mouseout", () => { const isConnected = isInput ? this.getNode().getInputConnected() : this.getNode().getOutputConnected(); port.set({ - source: isConnected ? osparc.workbench.BaseNodeUI.PORT_CONNECTED : osparc.workbench.BaseNodeUI.PORT_DISCONNECTED + source: isConnected ? this.self().PORT_CONNECTED : this.self().PORT_DISCONNECTED }); }, this); if (isInput) { @@ -574,14 +673,14 @@ qx.Class.define("osparc.workbench.NodeUI", { } }); this.getNode().bind("inputConnected", port, "source", { - converter: isConnected => isConnected ? osparc.workbench.BaseNodeUI.PORT_CONNECTED : osparc.workbench.BaseNodeUI.PORT_DISCONNECTED + converter: isConnected => isConnected ? this.self().PORT_CONNECTED : this.self().PORT_DISCONNECTED }); } else { this.getNode().getStatus().bind("output", port, "textColor", { converter: output => osparc.service.StatusUI.getColor(output) }); this.getNode().bind("outputConnected", port, "source", { - converter: isConnected => isConnected ? osparc.workbench.BaseNodeUI.PORT_CONNECTED : osparc.workbench.BaseNodeUI.PORT_DISCONNECTED + converter: isConnected => isConnected ? this.self().PORT_CONNECTED : this.self().PORT_DISCONNECTED }); } @@ -610,17 +709,6 @@ qx.Class.define("osparc.workbench.NodeUI", { }; }, - // override qx.ui.core.MMovable - _onMovePointerMove: function(e) { - // Only react when dragging is active - if (!this.hasState("move") || !this.getIsMovable()) { - return; - } - const coords = this._setPositionFromEvent(e); - this.getNode().setPosition(coords); - this.base(arguments, e); - }, - setPosition: function(pos) { const node = this.getNode(); node.setPosition(pos); @@ -666,5 +754,185 @@ qx.Class.define("osparc.workbench.NodeUI", { }); } }, + + __getMenuButton: function() { + const optionsMenu = this.__optionsMenu = new qx.ui.menu.Menu().set({ + position: "bottom-right" + }); + + const renameBtn = new qx.ui.menu.Button().set({ + label: this.tr("Rename"), + icon: "@FontAwesome5Solid/i-cursor/10" + }); + renameBtn.getChildControl("shortcut").setValue("F2"); + renameBtn.addListener("execute", () => this.fireDataEvent("renameNode", this.getNodeId())); + optionsMenu.add(renameBtn); + + const markerBtn = this.__markerBtn = new qx.ui.menu.Button().set({ + icon: "@FontAwesome5Solid/bookmark/10", + visibility: "excluded" + }); + optionsMenu.add(markerBtn); + + const infoBtn = new qx.ui.menu.Button().set({ + label: this.tr("Information..."), + icon: "@FontAwesome5Solid/info/10" + }); + infoBtn.getChildControl("shortcut").setValue("I"); + infoBtn.addListener("execute", () => this.fireDataEvent("infoNode", this.getNodeId())); + optionsMenu.add(infoBtn); + + const deleteBtn = this.__deleteBtn = new qx.ui.menu.Button().set({ + label: this.tr("Delete"), + icon: "@FontAwesome5Solid/trash/10" + }); + deleteBtn.getChildControl("shortcut").setValue("Del"); + deleteBtn.addListener("execute", () => this.fireDataEvent("removeNode", this.getNodeId())); + optionsMenu.add(deleteBtn); + + const menuBtn = new qx.ui.form.MenuButton().set({ + menu: optionsMenu, + icon: "@FontAwesome5Solid/ellipsis-v/9", + height: 18, + width: 18, + allowGrowX: false, + allowGrowY: false + }); + return menuBtn; + }, + + getInputPort: function() { + return this.__inputLayout; + }, + + getOutputPort: function() { + return this.__outputLayout; + }, + + __createPort: function(isInput, placeholder = false) { + let port = null; + const width = this.self().PORT_HEIGHT; + if (placeholder) { + port = new qx.ui.core.Spacer(width, width); + } else { + port = new qx.ui.basic.Image().set({ + source: this.self().PORT_DISCONNECTED, // disconnected by default + height: width, + draggable: true, + droppable: true, + width: width, + alignY: "top", + backgroundColor: "background-main" + }); + port.setCursor("pointer"); + port.getContentElement().setStyles({ + "border-radius": width+"px" + }); + port.isInput = isInput; + } + // make the ports exit the NodeUI + port.set({ + marginLeft: isInput ? (-10 + this.self().CONTENT_PADDING) : 0, + marginRight: isInput ? 0 : (-10 - this.self().CONTENT_PADDING) + }); + + this.add(port, { + row: 0, + column: isInput ? 0 : 2 + }); + + if (isInput) { + this.__inputLayout = port; + } else { + this.__outputLayout = port; + } + + return port; + }, + + getEdgePoint: function(port) { + const bounds = this.getCurrentBounds(); + const captionHeight = Math.max(this.getChildControl("captionbar").getSizeHint().height, this.self().captionHeight()); + const x = port.isInput ? bounds.left - 6 : bounds.left + bounds.width - 1; + const y = bounds.top + captionHeight + this.self().PORT_HEIGHT/2 + 2; + return [x, y]; + }, + + getCurrentBounds: function() { + let bounds = this.getBounds(); + let cel = this.getContentElement(); + if (cel) { + let domeEle = cel.getDomElement(); + if (domeEle) { + bounds.left = parseInt(domeEle.style.left); + bounds.top = parseInt(domeEle.style.top); + } + } + return bounds; + }, + + __scaleCoordinates: function(x, y) { + return { + x: parseInt(x / this.getScale()), + y: parseInt(y / this.getScale()) + }; + }, + + __setPositionFromEvent: function(e) { + // this.__dragRange is defined in qx.ui.core.MMovable + const sideBarWidth = this.__dragRange.left; + const navigationBarHeight = this.__dragRange.top; + const native = e.getNativeEvent(); + const x = native.clientX + this.__dragLeft - sideBarWidth; + const y = native.clientY + this.__dragTop - navigationBarHeight; + const coords = this.__scaleCoordinates(x, y); + const insets = this.getLayoutParent().getInsets(); + this.setDomPosition(coords.x - (insets.left || 0), coords.y - (insets.top || 0)); + return coords; + }, + + // override qx.ui.core.MMovable + _onMovePointerMove: function(e) { + // Only react when dragging is active + if (!this.hasState("move") || !this.getIsMovable()) { + return; + } + const coords = this.__setPositionFromEvent(e); + e.stopPropagation(); + if (this.__nodeMoving === false) { + this.__nodeMoving = true; + this.fireEvent("nodeMovingStart"); + } + this.fireDataEvent("nodeMoving", coords); + }, + + // override qx.ui.core.MMovable + _onMovePointerUp : function(e) { + if (this.hasListener("roll")) { + this.removeListener("roll", this._onMoveRoll, this); + } + + // Only react when dragging is active + if (!this.hasState("move") || !this.getIsMovable()) { + return; + } + + this._onMovePointerMove(e); + + this.__nodeMoving = false; + + // Only consolidate position when it stops moving + const coords = this.__setPositionFromEvent(e); + this.getNode().setPosition(coords); + + this.fireEvent("nodeMovingStop"); + + // Remove drag state + this.removeState("move"); + + this.releaseCapture(); + + e.stopPropagation(); + }, } }); diff --git a/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js b/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js index d3a0671bad6a..4114221d7c04 100644 --- a/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js +++ b/services/static-webserver/client/source/class/osparc/workbench/WorkbenchUI.js @@ -465,7 +465,7 @@ qx.Class.define("osparc.workbench.WorkbenchUI", { this.getSelectedAnnotations().forEach(selectedAnnotation => delete selectedAnnotation["initPos"]); if (nodeUI && osparc.Preferences.getInstance().isSnapNodeToGrid()) { - nodeUI.snapToGrid(); + this.getSelectedNodeUIs().forEach(selectedNodeUI => selectedNodeUI.snapToGrid()); // make sure nodeUI is moved, then update edges setTimeout(() => this.__updateNodeUIPos(nodeUI), 10); } @@ -495,12 +495,13 @@ qx.Class.define("osparc.workbench.WorkbenchUI", { this.__itemStartedMoving(); }, this); - nodeUI.addListener("nodeMoving", () => { + nodeUI.addListener("nodeMoving", e => { this.__updateNodeUIPos(nodeUI); if ("initPos" in nodeUI) { // multi node move - const xDiff = nodeUI.getNode().getPosition().x - nodeUI.initPos.x; - const yDiff = nodeUI.getNode().getPosition().y - nodeUI.initPos.y; + const coords = e.getData(); + const xDiff = coords.x - nodeUI.initPos.x; + const yDiff = coords.y - nodeUI.initPos.y; this.__itemMoving(nodeUI.getNodeId(), xDiff, yDiff); } }, this); @@ -988,7 +989,7 @@ qx.Class.define("osparc.workbench.WorkbenchUI", { osparc.workbench.SvgWidget.updateCurve(this.__tempEdgeRepr, x1, y1, x2, y2); } const portLabel = port.isInput ? nodeUI.getInputPort() : nodeUI.getOutputPort(); - portLabel.setSource(osparc.workbench.BaseNodeUI.PORT_CONNECTED); + portLabel.setSource(osparc.workbench.NodeUI.PORT_CONNECTED); if (!this.__tempEdgeIsInput) { const modified = nodeUI.getNode().getStatus().getModified(); @@ -1007,7 +1008,7 @@ qx.Class.define("osparc.workbench.WorkbenchUI", { const isConnected = this.__tempEdgeIsInput ? nodeUI.getNode().getInputConnected() : nodeUI.getNode().getOutputConnected(); const portLabel = this.__tempEdgeIsInput ? nodeUI.getInputPort() : nodeUI.getOutputPort(); portLabel.set({ - source: isConnected ? osparc.workbench.BaseNodeUI.PORT_CONNECTED : osparc.workbench.BaseNodeUI.PORT_DISCONNECTED + source: isConnected ? osparc.workbench.NodeUI.PORT_CONNECTED : osparc.workbench.NodeUI.PORT_DISCONNECTED }); }