Resizeable comments

This commit is contained in:
barsdeveloper
2022-12-04 22:12:53 +01:00
parent 41e1ffd59b
commit 9e8e25d832
19 changed files with 1103 additions and 443 deletions

View File

@@ -24,6 +24,14 @@ export default class IDraggableElement extends IElement {
type: Number,
attribute: false,
},
sizeX: {
type: Number,
attribute: false,
},
sizeY: {
type: Number,
attribute: false,
},
}
static dragEventName = Configuration.dragEventName
static dragGeneralEventName = Configuration.dragGeneralEventName
@@ -36,6 +44,16 @@ export default class IDraggableElement extends IElement {
super(entity, template)
this.locationX = 0
this.locationY = 0
this.sizeX = -1
this.sizeY = -1
}
/** @param {Map} changedProperties */
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties)
const boundaries = this.getBoundingClientRect()
this.sizeX = boundaries.width
this.sizeY = boundaries.height
}
/** @param {Number[]} param0 */
@@ -80,4 +98,20 @@ export default class IDraggableElement extends IElement {
this.setLocation(snappedLocation)
}
}
topBoundary() {
return this.locationY
}
rightBoundary() {
return this.locationX + this.sizeX
}
bottomBoundary() {
return this.locationY + this.sizeY
}
leftBoundary() {
return this.locationX
}
}

View File

@@ -1,3 +1,4 @@
import CommentNodeTemplate from "../template/CommentNodeTemplate"
import Configuration from "../Configuration"
import IdentifierEntity from "../entity/IdentifierEntity"
import ISelectableDraggableElement from "./ISelectableDraggableElement"
@@ -9,7 +10,6 @@ import PinReferenceEntity from "../entity/PinReferenceEntity"
import SerializerFactory from "../serialization/SerializerFactory"
import Utility from "../Utility"
import VariableAccessNodeTemplate from "../template/VariableAccessNodeTemplate"
import CommentNodeTemplate from "../template/CommentNodeTemplate"
/** @typedef {import("./IElement").default} IElement */
@@ -96,6 +96,12 @@ export default class NodeElement extends ISelectableDraggableElement {
super.setLocation([this.entity.NodePosX.value, this.entity.NodePosY.value])
this.entity.subscribe("AdvancedPinDisplay", value => this.advancedPinDisplay = value)
this.entity.subscribe("Name", value => this.nodeName = value)
if (this.entity.NodeWidth) {
this.sizeX = this.entity.NodeWidth
}
if (this.entity.NodeHeight) {
this.sizeY = this.entity.NodeHeight
}
}
/**

View File

@@ -184,7 +184,11 @@ export default class LinearColorEntity extends IEntity {
}
toNumber() {
return (this.R.value << 24) + (this.G.value << 16) + (this.B.value << 8) + this.A.value
return (
Math.round(this.R.value * 0xff) << 24)
+ (Math.round(this.G.value * 0xff) << 16)
+ (Math.round(this.B.value * 0xff) << 8)
+ Math.round(this.A.value * 0xff)
}
/** @param {Number} number */

View File

@@ -62,7 +62,7 @@ export default class IMouseClickDrag extends IPointing {
this.#trackingMouse = this.target.dispatchEvent(dragEvent) == false
const location = this.locationFromEvent(e)
// Do actual actions
this.mouseLocation = Utility.snapToGrid(this.clickedPosition, this.stepSize)
this.lastLocation = Utility.snapToGrid(this.clickedPosition, this.stepSize)
this.startDrag(location)
this.started = true
}
@@ -111,15 +111,14 @@ export default class IMouseClickDrag extends IPointing {
clickedOffset = [0, 0]
clickedPosition = [0, 0]
mouseLocation = [0, 0]
lastLocation = [0, 0]
started = false
stepSize = 1
/**
*
* @param {T} target
* @param {Blueprint} blueprint
* @param {Object} options
* @param {T} target
* @param {Blueprint} blueprint
* @param {Object} options
*/
constructor(target, blueprint, options = {}) {
options.clickButton ??= 0
@@ -133,12 +132,13 @@ export default class IMouseClickDrag extends IPointing {
super(target, blueprint, options)
this.stepSize = parseInt(options?.stepSize ?? Configuration.gridSize)
this.#movementListenedElement = this.options.moveEverywhere ? document.documentElement : this.movementSpace
this.#draggableElement = this.options.draggableElement
this.#draggableElement = /** @type {HTMLElement} */(this.options.draggableElement)
this.listenEvents()
}
listenEvents() {
super.listenEvents()
this.#draggableElement.addEventListener("mousedown", this.#mouseDownHandler)
if (this.options.clickButton == 2) {
this.#draggableElement.addEventListener("contextmenu", e => e.preventDefault())
@@ -146,6 +146,7 @@ export default class IMouseClickDrag extends IPointing {
}
unlistenEvents() {
super.unlistenEvents()
this.#draggableElement.removeEventListener("mousedown", this.#mouseDownHandler)
}

View File

@@ -0,0 +1,51 @@
import MouseMoveDraggable from "./MouseMoveDraggable"
/** @typedef {import("../../Blueprint").default} Blueprint */
export default class MouseClickDrag extends MouseMoveDraggable {
#onClicked
#onStartDrag
#onDrag
#onEndDrag
/**
* @param {HTMLElement} target
* @param {Blueprint} blueprint
* @param {Object} options
*/
constructor(target, blueprint, options = {}) {
super(target, blueprint, options)
if (options.onClicked) {
this.#onClicked = options.onClicked
}
if (options.onStartDrag) {
this.#onStartDrag = options.onStartDrag
}
if (options.onDrag) {
this.#onDrag = options.onDrag
}
if (options.onEndDrag) {
this.#onEndDrag = options.onEndDrag
}
}
clicked() {
super.clicked()
this.#onClicked?.()
}
startDrag() {
super.startDrag()
this.#onStartDrag?.()
}
dragAction(location, movement) {
this.#onDrag?.(location, movement)
}
endDrag() {
super.endDrag()
this.#onEndDrag?.()
}
}

View File

@@ -23,29 +23,32 @@ export default class MouseMoveDraggable extends IMouseClickDrag {
}
dragTo(location, offset) {
const targetLocation = [this.target.locationX, this.target.locationY]
const targetLocation = [
this.target.locationX ?? this.lastLocation[0],
this.target.locationY ?? this.lastLocation[1],
]
const [adjustedLocation, adjustedTargetLocation] = this.stepSize > 1
? [Utility.snapToGrid(location, this.stepSize), Utility.snapToGrid(targetLocation, this.stepSize)]
: [location, targetLocation]
offset = [
adjustedLocation[0] - this.mouseLocation[0],
adjustedLocation[1] - this.mouseLocation[1]
adjustedLocation[0] - this.lastLocation[0],
adjustedLocation[1] - this.lastLocation[1],
]
if (offset[0] == 0 && offset[1] == 0) {
return
}
// Make sure it snaps on the grid
offset[0] += adjustedTargetLocation[0] - this.target.locationX
offset[1] += adjustedTargetLocation[1] - this.target.locationY
offset[0] += adjustedTargetLocation[0] - targetLocation[0]
offset[1] += adjustedTargetLocation[1] - targetLocation[1]
this.dragAction(adjustedLocation, offset)
// Reassign the position of mouse
this.mouseLocation = adjustedLocation
this.lastLocation = adjustedLocation
}
dragAction(location, offset) {
this.target.setLocation([
location[0] - this.clickedOffset[0],
location[1] - this.clickedOffset[1]
location[1] - this.clickedOffset[1],
])
}
}

View File

@@ -1,13 +1,14 @@
import { css, html } from "lit"
import Configuration from "../Configuration"
import IResizeableTemplate from "./IResizeableTemplate"
import LinearColorEntity from "../entity/LinearColorEntity"
import NodeTemplate from "./NodeTemplate"
/**
* @typedef {import("../element/NodeElement").default} NodeElement
* @typedef {import("../element/PinElement").default} PinElement
*/
export default class CommentNodeTemplate extends NodeTemplate {
export default class CommentNodeTemplate extends IResizeableTemplate {
#color = LinearColorEntity.getWhite()
@@ -19,12 +20,12 @@ export default class CommentNodeTemplate extends NodeTemplate {
// Dimming the colors to 2/3
const factor = 2 / 3
this.#color.setFromRGBA(
this.#color.R.value * factor,
this.#color.G.value * factor,
this.#color.B.value * factor,
this.#color.R.value,
this.#color.G.value,
this.#color.B.value,
)
element.classList.add("ueb-node-style-comment", "ueb-node-resizeable")
super.constructed(element) // Keep it at the end
super.constructed(element) // Keep it at the end because it calls this.getColor() where this.#color must be initialized
}
getColor() {
@@ -36,25 +37,32 @@ export default class CommentNodeTemplate extends NodeTemplate {
}
render() {
const width = this.element.entity.getNodeWidth()
const height = this.element.entity.getNodeHeight()
return html`
<div class="ueb-node-border">
<div class="ueb-node-handler-top"></div>
<div class="ueb-node-handler-right"></div>
<div class="ueb-node-handler-bottom"></div>
<div class="ueb-node-handler-left"></div>
<div class="ueb-node-wrapper">
<div class="ueb-node-top">
${this.element.entity.NodeComment}
</div>
<div class="ueb-node-content"
style="${`width: ${width}px; height: ${height}px;`}">
</div>
</div>
</div>
`
}
/** @param {Number} value */
setSizeX(value) {
if (value >= Configuration.gridSet * Configuration.gridSize) {
this.element.sizeX = value
return true
}
return false
}
/** @param {Number} value */
setSizeY(value) {
if (value >= 3 * Configuration.gridSize) {
this.element.sizeY = Math.max(value, 3 * Configuration.gridSize)
return true
}
return false
}
}

View File

@@ -0,0 +1,142 @@
import MouseClickDrag from "../input/mouse/MouseClickDrag"
import NodeTemplate from "./NodeTemplate"
/** @typedef {import("../element/NodeElement").default} NodeElement */
export default class IResizeableTemplate extends NodeTemplate {
#THandler = document.createElement("div")
#RHandler = document.createElement("div")
#BHandler = document.createElement("div")
#LHandler = document.createElement("div")
#TRHandler = document.createElement("div")
#BRHandler = document.createElement("div")
#BLHandler = document.createElement("div")
#TLHandler = document.createElement("div")
/** @param {NodeElement} element */
constructed(element) {
super.constructed(element)
this.element.classList.add("ueb-resizeable")
}
/** @param {Map} changedProperties */
update(changedProperties) {
super.update(changedProperties)
if (this.element.sizeX >= 0 && changedProperties.has("sizeX")) {
this.element.style.width = `${this.element.sizeX}px`
}
if (this.element.sizeY >= 0 && changedProperties.has("sizeY")) {
this.element.style.height = `${this.element.sizeY}px`
}
}
/** @param {Map} changedProperties */
firstUpdated(changedProperties) {
super.firstUpdated(changedProperties)
this.#THandler.classList.add("ueb-resizeable-top")
this.#RHandler.classList.add("ueb-resizeable-right")
this.#BHandler.classList.add("ueb-resizeable-bottom")
this.#LHandler.classList.add("ueb-resizeable-left")
this.#TRHandler.classList.add("ueb-resizeable-top-right")
this.#BRHandler.classList.add("ueb-resizeable-bottom-right")
this.#BLHandler.classList.add("ueb-resizeable-bottom-left")
this.#TLHandler.classList.add("ueb-resizeable-top-left")
this.element.append(
this.#THandler,
this.#RHandler,
this.#BHandler,
this.#LHandler,
this.#TRHandler,
this.#BRHandler,
this.#BLHandler,
this.#TLHandler
)
}
createInputObjects() {
return [
...super.createInputObjects(),
new MouseClickDrag(this.#THandler, this.element.blueprint, {
onDrag: (location, movement) => {
movement[1] = location[1] - this.element.topBoundary()
if (this.setSizeY(this.element.sizeY - movement[1])) {
this.element.addLocation([0, movement[1]])
}
}
}),
new MouseClickDrag(this.#RHandler, this.element.blueprint, {
onDrag: (location, movement) => {
movement[0] = location[0] - this.element.rightBoundary()
this.setSizeX(this.element.sizeX + movement[0])
}
}),
new MouseClickDrag(this.#BHandler, this.element.blueprint, {
onDrag: (location, movement) => {
movement[1] = location[1] - this.element.bottomBoundary()
this.setSizeY(this.element.sizeY + movement[1])
}
}),
new MouseClickDrag(this.#LHandler, this.element.blueprint, {
onDrag: (location, movement) => {
movement[0] = location[0] - this.element.leftBoundary()
if (this.setSizeX(this.element.sizeX - movement[0])) {
this.element.addLocation([movement[0], 0])
}
}
}),
new MouseClickDrag(this.#TRHandler, this.element.blueprint, {
onDrag: (location, movement) => {
movement[0] = location[0] - this.element.rightBoundary()
movement[1] = location[1] - this.element.topBoundary()
this.setSizeX(this.element.sizeX + movement[0])
if (this.setSizeY(this.element.sizeY - movement[1])) {
this.element.addLocation([0, movement[1]])
}
}
}),
new MouseClickDrag(this.#BRHandler, this.element.blueprint, {
onDrag: (location, movement) => {
movement[0] = location[0] - this.element.rightBoundary()
movement[1] = location[1] - this.element.bottomBoundary()
this.setSizeX(this.element.sizeX + movement[0])
this.setSizeY(this.element.sizeY + movement[1])
}
}),
new MouseClickDrag(this.#BLHandler, this.element.blueprint, {
onDrag: (location, movement) => {
movement[0] = location[0] - this.element.leftBoundary()
movement[1] = location[1] - this.element.bottomBoundary()
if (this.setSizeX(this.element.sizeX - movement[0])) {
this.element.addLocation([movement[0], 0])
}
this.setSizeY(this.element.sizeY + movement[1])
}
}),
new MouseClickDrag(this.#TLHandler, this.element.blueprint, {
onDrag: (location, movement) => {
movement[0] = location[0] - this.element.leftBoundary()
movement[1] = location[1] - this.element.topBoundary()
if (this.setSizeX(this.element.sizeX - movement[0])) {
this.element.addLocation([movement[0], 0])
}
if (this.setSizeY(this.element.sizeY - movement[1])) {
this.element.addLocation([0, movement[1]])
}
}
}),
]
}
/** @param {Number} value */
setSizeX(value) {
this.element.sizeX = value
return true
}
/** @param {Number} value */
setSizeY(value) {
this.element.sizeY = value
return true
}
}