mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-05-21 13:47:37 +08:00
Link implementation wip
This commit is contained in:
@@ -1,19 +1,19 @@
|
||||
import BlueprintTemplate from "./template/BlueprintTemplate"
|
||||
import Configuration from "./Configuration"
|
||||
import Copy from "./input/common/Copy"
|
||||
import MouseScrollGraph from "./input/mouse/MouseScrollGraph"
|
||||
import GraphElement from "./graph/GraphElement"
|
||||
import GraphLink from "./graph/GraphLink"
|
||||
import GraphNode from "./graph/GraphNode"
|
||||
import GraphSelector from "./graph/GraphSelector"
|
||||
import KeyboardCanc from "./input/keybaord/KeyboardCanc"
|
||||
import KeyboardSelectAll from "./input/keybaord/KeyboardSelectAll"
|
||||
import MouseScrollGraph from "./input/mouse/MouseScrollGraph"
|
||||
import MouseTracking from "./input/mouse/MouseTracking"
|
||||
import Paste from "./input/common/Paste"
|
||||
import Select from "./input/mouse/Select"
|
||||
import Unfocus from "./input/mouse/Unfocus"
|
||||
import Utility from "./Utility"
|
||||
import Zoom from "./input/mouse/Zoom"
|
||||
import KeyboardSelectAll from "./input/keybaord/KeyboardSelectAll"
|
||||
|
||||
export default class Blueprint extends GraphElement {
|
||||
|
||||
@@ -94,7 +94,6 @@ export default class Blueprint extends GraphElement {
|
||||
|
||||
createInputObjects() {
|
||||
return [
|
||||
|
||||
new Copy(this.getGridDOMElement(), this),
|
||||
new Paste(this.getGridDOMElement(), this),
|
||||
new KeyboardCanc(this.getGridDOMElement(), this),
|
||||
|
||||
@@ -10,6 +10,16 @@ export default class Utility {
|
||||
return getComputedStyle(element).getPropertyValue("--ueb-scale")
|
||||
}
|
||||
|
||||
static convertLocation(viewportLocation, movementElement) {
|
||||
const scaleCorrection = 1 / Utility.getScale(movementElement)
|
||||
const targetOffset = movementElement.getBoundingClientRect()
|
||||
let location = [
|
||||
Math.round((viewportLocation[0] - targetOffset.x) * scaleCorrection),
|
||||
Math.round((viewportLocation[1] - targetOffset.y) * scaleCorrection)
|
||||
]
|
||||
return location
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in an object
|
||||
* @param {String[]} keys The chained keys to access from object in order to set the value
|
||||
|
||||
@@ -14,11 +14,11 @@ export default class GraphElement extends HTMLElement {
|
||||
*/
|
||||
constructor(entity, template) {
|
||||
super()
|
||||
/** @type {Blueprint}" */
|
||||
/** @type {Blueprint} */
|
||||
this.blueprint = null
|
||||
/** @type {Entity}" */
|
||||
/** @type {Entity} */
|
||||
this.entity = entity
|
||||
/** @type {Template}" */
|
||||
/** @type {Template} */
|
||||
this.template = template
|
||||
/** @type {Context[]} */
|
||||
this.inputObjects = []
|
||||
|
||||
@@ -3,7 +3,7 @@ import LinkTemplate from "../template/LinkTemplate"
|
||||
|
||||
|
||||
/**
|
||||
* @type {import("./GraphPin").default} GraphPin
|
||||
* @typedef {import("./GraphPin").default} GraphPin
|
||||
*/
|
||||
export default class GraphLink extends GraphElement {
|
||||
|
||||
@@ -20,19 +20,30 @@ export default class GraphLink extends GraphElement {
|
||||
* @param {?GraphPin} destination
|
||||
*/
|
||||
constructor(source, destination) {
|
||||
super(this, new LinkTemplate())
|
||||
super({}, new LinkTemplate())
|
||||
/** @type {import("../template/LinkTemplate").default} */
|
||||
this.template
|
||||
this.setSource(source)
|
||||
this.setDestination(destination)
|
||||
this.setSourcePin(source)
|
||||
this.setDestinationPin(destination)
|
||||
}
|
||||
|
||||
setSourceLocation(location) {
|
||||
this.template.applySourceLocation(this.#source.getLinkLocation())
|
||||
if (location == null) {
|
||||
location = this.#source.template.getLinkLocation(this.#source)
|
||||
}
|
||||
this.template.applySourceLocation(this, location)
|
||||
}
|
||||
|
||||
setDestinationLocation(location) {
|
||||
this.template.applyDestinationLocation(this.#destination.getLinkLocation())
|
||||
if (location == null) {
|
||||
location = this.#destination.template.getLinkLocation(this.#destination)
|
||||
}
|
||||
this.template.applyDestinationLocation(this, location)
|
||||
}
|
||||
|
||||
|
||||
getSourcePin() {
|
||||
return this.#source
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,6 +55,12 @@ export default class GraphLink extends GraphElement {
|
||||
this.#source = graphPin
|
||||
this.#source?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler)
|
||||
this.#source?.addEventListener("ueb-node-drag", this.#nodeDragSourceHandler)
|
||||
this.setSourceLocation()
|
||||
this.originatesFromInput = this.#destination == null
|
||||
}
|
||||
|
||||
getDestinationPin() {
|
||||
return this.#destination
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,6 +73,7 @@ export default class GraphLink extends GraphElement {
|
||||
this.#destination = graphPin
|
||||
this.#destination?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler)
|
||||
this.#destination?.addEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler)
|
||||
this.originatesFromInput = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import NodeTemplate from "../template/NodeTemplate"
|
||||
import ObjectEntity from "../entity/ObjectEntity"
|
||||
import PinEntity from "../entity/PinEntity"
|
||||
import SelectableDraggable from "./SelectableDraggable"
|
||||
import SerializerFactory from "../serialization/SerializerFactory"
|
||||
import PinEntity from "../entity/PinEntity"
|
||||
|
||||
export default class GraphNode extends SelectableDraggable {
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import GraphElement from "./GraphElement"
|
||||
import PinTemplate from "../template/PinTemplate"
|
||||
import MouseCreateLink from "../input/mouse/MouseCreateLink"
|
||||
import GraphLink from "./GraphLink"
|
||||
|
||||
export default class GraphPin extends GraphElement {
|
||||
|
||||
@@ -9,6 +8,8 @@ export default class GraphPin extends GraphElement {
|
||||
super(entity, new PinTemplate())
|
||||
/** @type {import("../entity/PinEntity").default} */
|
||||
this.entity
|
||||
/** @type {PinTemplate} */
|
||||
this.template
|
||||
/** @type {HTMLElement} */
|
||||
this.clickableElement = null
|
||||
}
|
||||
@@ -16,7 +17,8 @@ export default class GraphPin extends GraphElement {
|
||||
createInputObjects() {
|
||||
return [
|
||||
new MouseCreateLink(this.clickableElement, this.blueprint, {
|
||||
moveEverywhere: true
|
||||
moveEverywhere: true,
|
||||
looseTarget: true
|
||||
}),
|
||||
]
|
||||
}
|
||||
@@ -49,15 +51,6 @@ export default class GraphPin extends GraphElement {
|
||||
return this.entity.getType()
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {GraphLink} The link created
|
||||
*/
|
||||
dragLink() {
|
||||
let link = new GraphLink(this)
|
||||
return link
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns The exact location where the link originates from or arrives at.
|
||||
* @returns {Number[]} The location array
|
||||
|
||||
@@ -29,7 +29,7 @@ export default class MouseClickDrag extends Pointing {
|
||||
// Attach the listeners
|
||||
movementListenedElement.addEventListener("mousemove", self.mouseStartedMovingHandler)
|
||||
document.addEventListener("mouseup", self.mouseUpHandler)
|
||||
self.clickedPosition = self.getLocation(e)
|
||||
self.clickedPosition = self.locationFromEvent(e)
|
||||
self.clicked(self.clickedPosition)
|
||||
return true
|
||||
}
|
||||
@@ -59,7 +59,7 @@ export default class MouseClickDrag extends Pointing {
|
||||
this.mouseMoveHandler = e => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
const location = self.getLocation(e)
|
||||
const location = self.locationFromEvent(e)
|
||||
const movement = [e.movementX, e.movementY]
|
||||
self.dragTo(location, movement)
|
||||
}
|
||||
|
||||
@@ -1,29 +1,61 @@
|
||||
import GraphLink from "../../graph/GraphLink"
|
||||
import MouseClickDrag from "./MouseClickDrag"
|
||||
|
||||
export default class MouseCreateLink extends MouseClickDrag {
|
||||
|
||||
/** @type {(e: MouseEvent) => void} */
|
||||
#mouseenterHandler
|
||||
|
||||
/** @type {(e: MouseEvent) => void} */
|
||||
#mouseleaveHandler
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
super(target, blueprint, options)
|
||||
/** @type {import("../../graph/GraphPin").default} */
|
||||
this.target
|
||||
/** @type {import("../../graph/GraphLink").default} */
|
||||
this.link
|
||||
/** @type {import("../../entity/PinEntity").default} */
|
||||
this.enteredPin
|
||||
|
||||
let self = this
|
||||
this.#mouseenterHandler = e => {
|
||||
if (!self.enteredPin) {
|
||||
self.enteredPin = e.target
|
||||
}
|
||||
}
|
||||
this.#mouseleaveHandler = e => {
|
||||
if (self.enteredPin == e.target) {
|
||||
self.enteredPin = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startDrag() {
|
||||
let link = this.target.dragLink()
|
||||
|
||||
this.link = new GraphLink(this.target, null)
|
||||
this.blueprint.nodesContainerElement.insertBefore(this.link, this.blueprint.selectorElement.nextElementSibling)
|
||||
this.blueprint.querySelectorAll("ueb-pin." + this.target.isInput() ? "output" : "input")
|
||||
.forEach(pin => {
|
||||
pin.addEventListener("mouseenter", this.#mouseenterHandler)
|
||||
pin.addEventListener("mouseleave", this.#mouseleaveHandler)
|
||||
})
|
||||
}
|
||||
|
||||
dragTo(location, movement) {
|
||||
//this.selectorElement.doSelecting(location)
|
||||
this.link.setDestinationLocation(location)
|
||||
}
|
||||
|
||||
endDrag() {
|
||||
if (this.started) {
|
||||
//this.selectorElement.finishSelecting()
|
||||
this.blueprint.querySelectorAll("ueb-pin." + this.target.isInput() ? "output" : "input")
|
||||
.forEach(pin => {
|
||||
pin.removeEventListener("mouseenter", this.#mouseenterHandler)
|
||||
pin.removeEventListener("mouseleave", this.#mouseleaveHandler)
|
||||
})
|
||||
if (this.enteredPin) {
|
||||
this.link.setDestinationPin(this.link)
|
||||
} else {
|
||||
// this.blueprint.unselectAll()
|
||||
// this.link.remove()
|
||||
}
|
||||
this.link = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export default class MouseTracking extends Pointing {
|
||||
|
||||
let self = this
|
||||
this.mousemoveHandler = e => {
|
||||
self.blueprint.entity.mousePosition = self.getLocation(e)
|
||||
self.blueprint.entity.mousePosition = self.locationFromEvent(e)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export default class MouseWheel extends Pointing {
|
||||
|
||||
this.mouseWheelHandler = e => {
|
||||
e.preventDefault()
|
||||
const location = self.getLocation(e)
|
||||
const location = self.locationFromEvent(e)
|
||||
self.wheel(Math.sign(e.deltaY), location)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -13,13 +13,7 @@ export default class Pointing extends Context {
|
||||
* @param {MouseEvent} mouseEvent
|
||||
* @returns
|
||||
*/
|
||||
getLocation(mouseEvent) {
|
||||
const scaleCorrection = 1 / Utility.getScale(this.target)
|
||||
const targetOffset = this.movementSpace.getBoundingClientRect()
|
||||
let location = [
|
||||
Math.round((mouseEvent.clientX - targetOffset.x) * scaleCorrection),
|
||||
Math.round((mouseEvent.clientY - targetOffset.y) * scaleCorrection)
|
||||
]
|
||||
return location
|
||||
locationFromEvent(mouseEvent) {
|
||||
return Utility.convertLocation([mouseEvent.clientX, mouseEvent.clientY], this.movementSpace)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import html from "./html"
|
||||
import sanitizeText from "./sanitizeText"
|
||||
import Template from "./Template"
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,6 @@ export default class LinkTemplate extends Template {
|
||||
*/
|
||||
apply(link) {
|
||||
super.apply(link)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,8 +34,8 @@ export default class LinkTemplate extends Template {
|
||||
*/
|
||||
applySourceLocation(link, initialPosition) {
|
||||
// Set initial position
|
||||
link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]))
|
||||
link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]))
|
||||
link.style.setProperty("--ueb-from-x", sanitizeText(initialPosition[0]))
|
||||
link.style.setProperty("--ueb-from-y", sanitizeText(initialPosition[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,7 +43,7 @@ export default class LinkTemplate extends Template {
|
||||
* @param {GraphLink} link Link element
|
||||
*/
|
||||
applyDestinationLocation(link, finalPosition) {
|
||||
link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]))
|
||||
link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]))
|
||||
link.style.setProperty("--ueb-to-x", sanitizeText(finalPosition[0]))
|
||||
link.style.setProperty("--ueb-to-y", sanitizeText(finalPosition[1]))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Utility from "../Utility"
|
||||
import html from "./html"
|
||||
import sanitizeText from "./sanitizeText"
|
||||
import Template from "./Template"
|
||||
@@ -33,6 +34,18 @@ export default class PinTemplate extends Template {
|
||||
apply(pin) {
|
||||
super.apply(pin)
|
||||
pin.classList.add("ueb-node-" + pin.isInput() ? "input" : "output", "ueb-node-value-" + sanitizeText(pin.getType()))
|
||||
pin.clickableElement = pin.querySelector(".ueb-node-value-icon")
|
||||
pin.clickableElement = pin
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {GraphPin} pin
|
||||
* @returns
|
||||
*/
|
||||
getLinkLocation(pin) {
|
||||
const rect = pin.querySelector(".ueb-node-value-icon").getBoundingClientRect()
|
||||
return Utility.convertLocation(
|
||||
[(rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2],
|
||||
pin.blueprint.gridElement)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ export default class SelectorTemplate extends Template {
|
||||
*/
|
||||
apply(selector) {
|
||||
super.apply(selector)
|
||||
selector.classList.add("ueb-selector")
|
||||
this.applyFinishSelecting(selector)
|
||||
}
|
||||
|
||||
@@ -22,11 +21,11 @@ export default class SelectorTemplate extends Template {
|
||||
*/
|
||||
applyStartSelecting(selector, initialPosition) {
|
||||
// Set initial position
|
||||
selector.style.setProperty("--ueb-select-from-x", sanitizeText(initialPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-from-y", sanitizeText(initialPosition[1]))
|
||||
selector.style.setProperty("--ueb-from-x", sanitizeText(initialPosition[0]))
|
||||
selector.style.setProperty("--ueb-from-y", sanitizeText(initialPosition[1]))
|
||||
// Final position coincide with the initial position, at the beginning of selection
|
||||
selector.style.setProperty("--ueb-select-to-x", sanitizeText(initialPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-to-y", sanitizeText(initialPosition[1]))
|
||||
selector.style.setProperty("--ueb-to-x", sanitizeText(initialPosition[0]))
|
||||
selector.style.setProperty("--ueb-to-y", sanitizeText(initialPosition[1]))
|
||||
selector.dataset.selecting = "true"
|
||||
}
|
||||
|
||||
@@ -35,8 +34,8 @@ export default class SelectorTemplate extends Template {
|
||||
* @param {GraphSelector} selector Selector element
|
||||
*/
|
||||
applyDoSelecting(selector, finalPosition) {
|
||||
selector.style.setProperty("--ueb-select-to-x", sanitizeText(finalPosition[0]))
|
||||
selector.style.setProperty("--ueb-select-to-y", sanitizeText(finalPosition[1]))
|
||||
selector.style.setProperty("--ueb-to-x", sanitizeText(finalPosition[0]))
|
||||
selector.style.setProperty("--ueb-to-y", sanitizeText(finalPosition[1]))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
/**
|
||||
* This solves the sole purpose of providing compression capability for html inside template literals strings. Check rollup.config.js function minifyHTML()
|
||||
*/
|
||||
const html = String.raw
|
||||
export default html
|
||||
|
||||
Reference in New Issue
Block a user