Input refactoring (#12)

* Fix folder name typo

* Smaller fixes

* Shortcut rename to Shortcuts

* Fix quoted attributes in UE 5.3

* remove KeyboardShortcutAction

* Remove more trivial classes

* Rename IKeyboardShortcut

* Node delete shortcut
This commit is contained in:
barsdeveloper
2023-08-11 02:48:50 +02:00
committed by GitHub
parent 2284789e6e
commit ed43ee3edd
29 changed files with 652 additions and 485 deletions

View File

@@ -1,6 +1,7 @@
export default class Shortcut {
export default class Shortcuts {
static deleteNodes = "Delete"
static duplicateNodes = "(bCtrl=True,Key=D)"
static selectAllNodes = "(bCtrl=True,Key=A)"
static enableLinkDelete = "LeftAlt"
static enableZoomIn = ["LeftControl", "RightControl"] // Button to enable more than 1:1 zoom
static selectAllNodes = "(bCtrl=True,Key=A)"
}

View File

@@ -1,8 +1,14 @@
export default class Action {
apply() {
#blueprint
get blueprint() {
return this.#blueprint
}
revert() {
constructor(blueprint) {
this.#blueprint = blueprint
}
fire() {
}
}

View File

@@ -0,0 +1,8 @@
import Action from "./Actions"
export default class RemoveAllNodes extends Action {
fire() {
this.blueprint.removeGraphElement(...this.blueprint.getNodes(true))
}
}

View File

@@ -129,12 +129,4 @@ export default class IElement extends LitElement {
isSameGraph(element) {
return this.blueprint && this.blueprint == element?.blueprint
}
/**
* @template {IInput} V
* @param {new (...args: any[]) => V} type
*/
getInputObject(type) {
return /** @type {V} */(this.template.inputObjects.find(object => object.constructor == type))
}
}

View File

@@ -2,7 +2,7 @@ import Configuration from "../Configuration.js"
/** @typedef {import("../Blueprint.js").default} Blueprint */
/** @template {HTMLElement} T */
/** @template {Element} T */
export default class IInput {
/** @type {T} */
@@ -17,6 +17,8 @@ export default class IInput {
return this.#blueprint
}
consumeEvent = true
/** @type {Object} */
options
@@ -35,6 +37,7 @@ export default class IInput {
options.unlistenOnTextEdit ??= false
this.#target = target
this.#blueprint = blueprint
this.consumeEvent = options.consumeEvent
this.options = options
}

View File

@@ -0,0 +1,8 @@
import IInput from "./IInput"
/** @typedef {import("../Blueprint.js").default} Blueprint */
export default class InputCombination {
constructor() { }
}

View File

@@ -13,7 +13,7 @@ export default class Copy extends IInput {
options.unlistenOnTextEdit ??= true // No nodes copy if inside a text field, just text (default behavior)
super(target, blueprint, options)
let self = this
this.#copyHandler = _ => self.copied()
this.#copyHandler = () => self.copied()
}
listenEvents() {

View File

@@ -1,6 +1,5 @@
import IInput from "../IInput.js"
import ObjectSerializer from "../../serialization/ObjectSerializer.js"
import KeyboardCanc from "../keybaord/KeyboardCanc.js"
export default class Cut extends IInput {
@@ -14,7 +13,7 @@ export default class Cut extends IInput {
options.unlistenOnTextEdit ??= true // No nodes copy if inside a text field, just text (default behavior)
super(target, blueprint, options)
let self = this
this.#cutHandler = _ => self.cut()
this.#cutHandler = () => self.cut()
}
listenEvents() {
@@ -34,6 +33,6 @@ export default class Cut extends IInput {
cut() {
this.blueprint.template.getCopyInputObject().copied()
this.blueprint.template.getInputObject(KeyboardCanc).fire()
this.blueprint.removeGraphElement(...this.blueprint.getNodes(true))
}
}

View File

@@ -1,21 +0,0 @@
import IKeyboardShortcut from "./IKeyboardShortcut.js"
import Shortcut from "../../Shortcut.js"
/** @typedef {import("../../Blueprint.js").default} Blueprint */
export default class KeyboardCanc extends IKeyboardShortcut {
/**
* @param {HTMLElement} target
* @param {Blueprint} blueprint
* @param {Object} options
*/
constructor(target, blueprint, options = {}) {
options.activationKeys = Shortcut.deleteNodes
super(target, blueprint, options)
}
fire() {
this.blueprint.removeGraphElement(...this.blueprint.getNodes(true))
}
}

View File

@@ -1,21 +0,0 @@
import IKeyboardShortcut from "./IKeyboardShortcut.js"
import Shortcut from "../../Shortcut.js"
/** @typedef {import("../../Blueprint.js").default} Blueprint */
export default class KeyboardSelectAll extends IKeyboardShortcut {
/**
* @param {HTMLElement} target
* @param {Blueprint} blueprint
* @param {Object} options
*/
constructor(target, blueprint, options = {}) {
options.activationKeys = Shortcut.selectAllNodes
super(target, blueprint, options)
}
fire() {
this.blueprint.selectAll()
}
}

View File

@@ -1,41 +0,0 @@
import IKeyboardShortcut from "./IKeyboardShortcut.js"
/** @typedef {import("../../Blueprint.js").default} Blueprint */
/**
* @template {HTMLElement} T
* @extends IKeyboardShortcut<T>
*/
export default class KeyboardShortcutAction extends IKeyboardShortcut {
static #ignoreEvent =
/** @param {KeyboardShortcutAction} self */
self => { }
/**
* @param {T} target
* @param {Blueprint} blueprint
* @param {Object} options
* @param {(self: KeyboardShortcutAction<T>) => void} onKeyDown
* @param {(self: KeyboardShortcutAction<T>) => void} onKeyUp
*/
constructor(
target,
blueprint,
options,
onKeyDown = KeyboardShortcutAction.#ignoreEvent,
onKeyUp = KeyboardShortcutAction.#ignoreEvent
) {
super(target, blueprint, options)
this.onKeyDown = onKeyDown
this.onKeyUp = onKeyUp
}
fire() {
this.onKeyDown(this)
}
unfire() {
this.onKeyUp(this)
}
}

View File

@@ -1,10 +1,10 @@
import IKeyboardShortcut from "./IKeyboardShortcut.js"
import Shortcut from "../../Shortcut.js"
import KeyboardShortcut from "./KeyboardShortcut.js"
import Shortcuts from "../../Shortcuts.js"
import Zoom from "../mouse/Zoom.js"
/** @typedef {import("../../Blueprint.js").default} Blueprint */
export default class KeyboardEnableZoom extends IKeyboardShortcut {
export default class KeyboardEnableZoom extends KeyboardShortcut {
/** @type {Zoom} */
#zoomInputObject
@@ -15,12 +15,12 @@ export default class KeyboardEnableZoom extends IKeyboardShortcut {
* @param {Object} options
*/
constructor(target, blueprint, options = {}) {
options.activationKeys = Shortcut.enableZoomIn
options.activationKeys = Shortcuts.enableZoomIn
super(target, blueprint, options)
}
fire() {
this.#zoomInputObject = this.blueprint.getInputObject(Zoom)
this.#zoomInputObject = this.blueprint.template.getZoomInputObject()
this.#zoomInputObject.enableZoonIn = true
}

View File

@@ -6,10 +6,14 @@ import KeyBindingEntity from "../../entity/KeyBindingEntity.js"
/** @typedef {import("../../Blueprint.js").default} Blueprint */
/**
* @template {HTMLElement} T
* @template {Element} T
* @extends IInput<T>
*/
export default class IKeyboardShortcut extends IInput {
export default class KeyboardShortcut extends IInput {
static #ignoreEvent =
/** @param {KeyboardShortcut} self */
self => { }
/** @type {KeyBindingEntity[]} */
#activationKeys
@@ -21,8 +25,13 @@ export default class IKeyboardShortcut extends IInput {
* @param {Blueprint} blueprint
* @param {Object} options
*/
constructor(target, blueprint, options = {}) {
options.activateAnyKey ??= false
constructor(
target,
blueprint,
options = {},
onKeyDown = KeyboardShortcut.#ignoreEvent,
onKeyUp = KeyboardShortcut.#ignoreEvent
) {
options.activationKeys ??= []
options.consumeEvent ??= true
options.listenOnFocus ??= true
@@ -44,6 +53,8 @@ export default class IKeyboardShortcut extends IInput {
})
super(target, blueprint, options)
this.onKeyDown = onKeyDown
this.onKeyUp = onKeyUp
this.#activationKeys = this.options.activationKeys ?? []
@@ -55,15 +66,14 @@ export default class IKeyboardShortcut extends IInput {
/** @param {KeyboardEvent} e */
this.keyDownHandler = e => {
if (
this.options.activateAnyKey
|| self.#activationKeys.some(keyEntry =>
self.#activationKeys.some(keyEntry =>
wantsShift(keyEntry) == e.shiftKey
&& wantsCtrl(keyEntry) == e.ctrlKey
&& wantsAlt(keyEntry) == e.altKey
&& Configuration.Keys[keyEntry.Key] == e.code
&& Configuration.Keys[keyEntry.Key.value] == e.code
)
) {
if (options.consumeEvent) {
if (this.consumeEvent) {
e.preventDefault()
e.stopImmediatePropagation()
}
@@ -77,16 +87,15 @@ export default class IKeyboardShortcut extends IInput {
/** @param {KeyboardEvent} e */
this.keyUpHandler = e => {
if (
this.options.activateAnyKey
|| self.#activationKeys.some(keyEntry =>
self.#activationKeys.some(keyEntry =>
keyEntry.bShift && e.key == "Shift"
|| keyEntry.bCtrl && e.key == "Control"
|| keyEntry.bAlt && e.key == "Alt"
|| keyEntry.bCmd && e.key == "Meta"
|| Configuration.Keys[keyEntry.Key] == e.code
|| Configuration.Keys[keyEntry.Key.value] == e.code
)
) {
if (options.consumeEvent) {
if (this.consumeEvent) {
e.stopImmediatePropagation()
}
self.unfire()
@@ -105,11 +114,13 @@ export default class IKeyboardShortcut extends IInput {
document.removeEventListener("keydown", this.keyDownHandler)
}
// Subclasses will want to override
/* Subclasses can override */
fire() {
this.onKeyDown(this)
}
unfire() {
this.onKeyUp(this)
}
}

View File

@@ -21,15 +21,17 @@ export default class IMouseClickDrag extends IPointing {
case this.options.clickButton:
// Either doesn't matter or consider the click only when clicking on the parent, not descandants
if (!this.options.strictTarget || e.target == e.currentTarget) {
if (this.options.consumeEvent) {
if (this.consumeEvent) {
e.stopImmediatePropagation() // Captured, don't call anyone else
}
// Attach the listeners
this.#movementListenedElement.addEventListener("mousemove", this.#mouseStartedMovingHandler)
document.addEventListener("mouseup", this.#mouseUpHandler)
this.clickedPosition = this.locationFromEvent(e)
this.blueprint.mousePosition[0] = this.clickedPosition[0]
this.blueprint.mousePosition[1] = this.clickedPosition[1]
this.setLocationFromEvent(e)
this.clickedPosition[0] = this.location[0]
this.clickedPosition[1] = this.location[1]
this.blueprint.mousePosition[0] = this.location[0]
this.blueprint.mousePosition[1] = this.location[1]
if (this.target instanceof IDraggableElement) {
this.clickedOffset = [
this.clickedPosition[0] - this.target.locationX,
@@ -49,7 +51,7 @@ export default class IMouseClickDrag extends IPointing {
/** @param {MouseEvent} e */
#mouseStartedMovingHandler = e => {
if (this.options.consumeEvent) {
if (this.consumeEvent) {
e.stopImmediatePropagation() // Captured, don't call anyone else
}
// Delegate from now on to this.#mouseMoveHandler
@@ -58,19 +60,19 @@ export default class IMouseClickDrag extends IPointing {
// Handler calls e.preventDefault() when it receives the event, this means dispatchEvent returns false
const dragEvent = this.getEvent(Configuration.trackingMouseEventName.begin)
this.#trackingMouse = this.target.dispatchEvent(dragEvent) == false
const location = this.locationFromEvent(e)
this.setLocationFromEvent(e)
// Do actual actions
this.lastLocation = Utility.snapToGrid(this.clickedPosition[0], this.clickedPosition[1], this.stepSize)
this.startDrag(location)
this.startDrag(this.location)
this.started = true
}
/** @param {MouseEvent} e */
#mouseMoveHandler = e => {
if (this.options.consumeEvent) {
if (this.consumeEvent) {
e.stopImmediatePropagation() // Captured, don't call anyone else
}
const location = this.locationFromEvent(e)
const location = this.setLocationFromEvent(e)
const movement = [e.movementX, e.movementY]
this.dragTo(location, movement)
if (this.#trackingMouse) {
@@ -104,7 +106,7 @@ export default class IMouseClickDrag extends IPointing {
/** @param {MouseEvent} e */
#mouseUpHandler = e => {
if (!this.options.exitAnyButton || e.button == this.options.clickButton) {
if (this.options.consumeEvent) {
if (this.consumeEvent) {
e.stopImmediatePropagation() // Captured, don't call anyone else
}
// Remove the handlers of "mousemove" and "mouseup"

View File

@@ -1,12 +1,29 @@
import IInput from "../IInput.js"
import Utility from "../../Utility.js"
/** @typedef {import("../keyboard/KeyboardShortcut.js").default} KeyboardShortcut */
/**
* @template {HTMLElement} T
* @template {Element} T
* @extends {IInput<T>}
*/
export default class IPointing extends IInput {
#location = [0, 0]
get location() {
return this.#location
}
/** @type {KeyboardShortcut?} */
#enablerKey
get enablerKey() {
return this.#enablerKey
}
#enablerActivated = true
get enablerActivated() {
return this.#enablerActivated
}
constructor(target, blueprint, options = {}) {
options.ignoreTranslateCompensate ??= false
options.ignoreScale ??= false
@@ -14,17 +31,28 @@ export default class IPointing extends IInput {
super(target, blueprint, options)
/** @type {HTMLElement} */
this.movementSpace = options.movementSpace
if (options.enablerKey) {
this.#enablerKey = options.enablerKey
this.#enablerKey.onKeyDown = () => this.#enablerActivated = true
this.#enablerKey.onKeyUp = () => this.#enablerActivated = false
this.#enablerKey.consumeEvent = false
this.#enablerKey.listenEvents()
this.#enablerActivated = false
}
}
/** @param {MouseEvent} mouseEvent */
locationFromEvent(mouseEvent) {
const location = Utility.convertLocation(
setLocationFromEvent(mouseEvent) {
let location = Utility.convertLocation(
[mouseEvent.clientX, mouseEvent.clientY],
this.movementSpace,
this.options.ignoreScale
)
return this.options.ignoreTranslateCompensate
location = this.options.ignoreTranslateCompensate
? location
: this.blueprint.compensateTranslation(location[0], location[1])
this.#location[0] = location[0]
this.#location[1] = location[1]
return this.#location
}
}

View File

@@ -2,26 +2,40 @@ import Configuration from "../../Configuration.js"
import IPointing from "./IPointing.js"
/**
* @template {HTMLElement} T
* @typedef {import("../../Blueprint.js").default} Blueprint
* @typedef {import("../keyboard/KeyboardShortcut.js").default} KeyboardShortcut
*/
/**
* @template {Element} T
* @extends {IPointing<T>}
*/
export default class MouseClick extends IPointing {
static #ignoreEvent =
/** @param {MouseClick} self */
self => { }
/** @param {MouseEvent} e */
#mouseDownHandler = e => {
this.blueprint.setFocused(true)
if (this.enablerKey && !this.enablerActivated) {
return
}
switch (e.button) {
case this.options.clickButton:
// Either doesn't matter or consider the click only when clicking on the target, not descandants
if (!this.options.strictTarget || e.target === e.currentTarget) {
if (this.options.consumeEvent) {
if (this.consumeEvent) {
e.stopImmediatePropagation() // Captured, don't call anyone else
}
// Attach the listeners
document.addEventListener("mouseup", this.#mouseUpHandler)
this.clickedPosition = this.locationFromEvent(e)
this.blueprint.mousePosition[0] = this.clickedPosition[0]
this.blueprint.mousePosition[1] = this.clickedPosition[1]
this.setLocationFromEvent(e)
this.clickedPosition[0] = this.location[0]
this.clickedPosition[1] = this.location[1]
this.blueprint.mousePosition[0] = this.location[0]
this.blueprint.mousePosition[1] = this.location[1]
this.clicked(this.clickedPosition)
}
break
@@ -36,7 +50,7 @@ export default class MouseClick extends IPointing {
/** @param {MouseEvent} e */
#mouseUpHandler = e => {
if (!this.options.exitAnyButton || e.button == this.options.clickButton) {
if (this.options.consumeEvent) {
if (this.consumeEvent) {
e.stopImmediatePropagation() // Captured, don't call anyone else
}
// Remove the handlers of "mousemove" and "mouseup"
@@ -47,12 +61,25 @@ export default class MouseClick extends IPointing {
clickedPosition = [0, 0]
constructor(target, blueprint, options = {}) {
/**
* @param {T} target
* @param {Blueprint} blueprint
* @param {Object} options
*/
constructor(
target,
blueprint,
options = {},
onClick = MouseClick.#ignoreEvent,
onUnclick = MouseClick.#ignoreEvent,
) {
options.clickButton ??= Configuration.mouseClickButton
options.consumeEvent ??= true
options.exitAnyButton ??= true
options.strictTarget ??= false
super(target, blueprint, options)
this.onClick = onClick
this.onUnclick = onUnclick
this.listenEvents()
}
@@ -69,8 +96,10 @@ export default class MouseClick extends IPointing {
/* Subclasses will override the following methods */
clicked(location) {
this.onClick(this)
}
unclicked(location) {
this.onUnclick(this)
}
}

View File

@@ -12,10 +12,10 @@ export default class MouseDbClick extends IPointing {
/** @param {MouseEvent} e */
#mouseDbClickHandler = e => {
if (!this.options.strictTarget || e.target === e.currentTarget) {
if (this.options.consumeEvent) {
if (this.consumeEvent) {
e.stopImmediatePropagation() // Captured, don't call anyone else
}
this.clickedPosition = this.locationFromEvent(e)
this.clickedPosition = this.setLocationFromEvent(e)
this.blueprint.mousePosition[0] = this.clickedPosition[0]
this.blueprint.mousePosition[1] = this.clickedPosition[1]
this.dbclicked(this.clickedPosition)

View File

@@ -9,7 +9,9 @@ export default class MouseTracking extends IPointing {
/** @param {MouseEvent} e */
#mousemoveHandler= e => {
e.preventDefault()
this.blueprint.mousePosition = this.locationFromEvent(e)
this.setLocationFromEvent(e)
this.blueprint.mousePosition[0] = this.location[0]
this.blueprint.mousePosition[1] = this.location[1]
}
/** @param {CustomEvent} e */

View File

@@ -2,13 +2,26 @@ import IPointing from "./IPointing.js"
/** @typedef {import("../../Blueprint.js").default} Blueprint */
export default class IMouseWheel extends IPointing {
export default class MouseWheel extends IPointing {
static #ignoreEvent =
/** @param {MouseWheel} self */
self => { }
#variation = 0
get variation() {
return this.#variation
}
/** @param {WheelEvent} e */
#mouseWheelHandler = e => {
if (this.enablerKey && !this.enablerActivated) {
return
}
e.preventDefault()
const location = this.locationFromEvent(e)
this.wheel(e.deltaY, location)
this.#variation = e.deltaY
this.setLocationFromEvent(e)
this.wheel()
}
/** @param {WheelEvent} e */
@@ -19,11 +32,17 @@ export default class IMouseWheel extends IPointing {
* @param {Blueprint} blueprint
* @param {Object} options
*/
constructor(target, blueprint, options = {}) {
constructor(
target,
blueprint,
options = {},
onWheel = MouseWheel.#ignoreEvent,
) {
options.listenOnFocus = true
options.strictTarget ??= false
super(target, blueprint, options)
this.strictTarget = options.strictTarget
this.onWheel = onWheel
}
listenEvents() {
@@ -36,7 +55,8 @@ export default class IMouseWheel extends IPointing {
this.movementSpace.parentElement?.removeEventListener("wheel", this.#mouseParentWheelHandler)
}
/* Subclasses will override the following method */
wheel(variation, location) {
/* Subclasses can override */
wheel() {
this.onWheel(this)
}
}

View File

@@ -1,7 +1,7 @@
import Configuration from "../../Configuration.js"
import IMouseWheel from "./IMouseWheel.js"
import MouseWheel from "./MouseWheel.js"
export default class Zoom extends IMouseWheel {
export default class Zoom extends MouseWheel {
#accumulatedVariation = 0
@@ -16,19 +16,17 @@ export default class Zoom extends IMouseWheel {
this.#enableZoonIn = value
}
wheel(variation, location) {
this.#accumulatedVariation += -variation
variation = this.#accumulatedVariation
wheel() {
this.#accumulatedVariation += -this.variation
if (Math.abs(this.#accumulatedVariation) < Configuration.mouseWheelZoomThreshold) {
return
} else {
this.#accumulatedVariation = 0
}
let zoomLevel = this.blueprint.getZoom()
if (!this.enableZoonIn && zoomLevel == 0 && variation > 0) {
if (!this.enableZoonIn && zoomLevel == 0 && this.#accumulatedVariation > 0) {
return
}
zoomLevel += Math.sign(variation)
this.blueprint.setZoom(zoomLevel, location)
zoomLevel += Math.sign(this.#accumulatedVariation)
this.blueprint.setZoom(zoomLevel, this.location)
this.#accumulatedVariation = 0
}
}

View File

@@ -129,6 +129,13 @@ export default class Grammar {
)
static symbol = P.regex(Grammar.Regex.Symbol)
static attributeName = P.regex(Grammar.Regex.DotSeparatedSymbols)
static attributeNameOptQuotes = Grammar.regexMap(
new RegExp(
"(" + Grammar.Regex.DotSeparatedSymbols.source + ")"
+ '|"' + "(" + Grammar.Regex.DotSeparatedSymbols.source + ")" + '"'
),
([_0, a, b]) => a ?? b
)
static guid = P.regex(new RegExp(`${Grammar.Regex.HexDigit.source}{32}`))
static commaSeparation = P.regex(/\s*,\s*(?!\))/)
static equalSeparation = P.regex(/\s*=\s*/)
@@ -338,9 +345,9 @@ export default class Grammar {
return result
}
static createAttributeGrammar(entityType, valueSeparator = this.equalSeparation) {
static createAttributeGrammar(entityType, attributeName = this.attributeName, valueSeparator = this.equalSeparation) {
return P.seq(
this.attributeName,
attributeName,
valueSeparator,
).chain(([attributeName, _1]) => {
const attributeKey = attributeName.split(Configuration.keysSeparator)
@@ -698,7 +705,7 @@ export default class Grammar {
P.whitespace,
P.alt(
this.customProperty,
this.createAttributeGrammar(ObjectEntity),
this.createAttributeGrammar(ObjectEntity, this.attributeNameOptQuotes),
this.inlinedArrayEntry,
this.subObjectEntity
)

View File

@@ -144,7 +144,7 @@ export default function initializeSerializerFactory() {
SerializerFactory.registerSerializer(
InvariantTextEntity,
new Serializer(InvariantTextEntity, (entity, v) => `${InvariantTextEntity.lookbehind}(${v})`, ", ", false, "", _ => "")
new Serializer(InvariantTextEntity, (entity, v) => `${InvariantTextEntity.lookbehind}(${v})`, ", ", false, "", () => "")
)
SerializerFactory.registerSerializer(
@@ -159,7 +159,7 @@ export default function initializeSerializerFactory() {
SerializerFactory.registerSerializer(
LocalizedTextEntity,
new Serializer(LocalizedTextEntity, (entity, v) => `${LocalizedTextEntity.lookbehind}(${v})`, ", ", false, "", _ => "")
new Serializer(LocalizedTextEntity, (entity, v) => `${LocalizedTextEntity.lookbehind}(${v})`, ", ", false, "", () => "")
)
SerializerFactory.registerSerializer(
@@ -209,7 +209,7 @@ export default function initializeSerializerFactory() {
SerializerFactory.registerSerializer(
PinReferenceEntity,
new Serializer(PinReferenceEntity, undefined, " ", false, "", _ => "")
new Serializer(PinReferenceEntity, undefined, " ", false, "", () => "")
)
SerializerFactory.registerSerializer(

View File

@@ -3,15 +3,13 @@ import Configuration from "../Configuration.js"
import Copy from "../input/common/Copy.js"
import Cut from "../input/common/Cut.js"
import ITemplate from "./ITemplate.js"
import KeyboardCanc from "../input/keybaord/KeyboardCanc.js"
import KeyboardEnableZoom from "../input/keybaord/KeyboardEnableZoom.js"
import KeyboardSelectAll from "../input/keybaord/KeyboardSelectAll.js"
import KeyboardShortcutAction from "../input/keybaord/KeyboardShortcutAction.js"
import KeyboardEnableZoom from "../input/keyboard/KeyboardEnableZoom.js"
import KeyboardShortcut from "../input/keyboard/KeyboardShortcut.js"
import MouseScrollGraph from "../input/mouse/MouseScrollGraph.js"
import MouseTracking from "../input/mouse/MouseTracking.js"
import Paste from "../input/common/Paste.js"
import Select from "../input/mouse/Select.js"
import Shortcut from "../Shortcut.js"
import Shortcuts from "../Shortcuts.js"
import Unfocus from "../input/mouse/Unfocus.js"
import Utility from "../Utility.js"
import Zoom from "../input/mouse/Zoom.js"
@@ -47,6 +45,12 @@ export default class BlueprintTemplate extends ITemplate {
this.viewportSize[1] = size.blockSize
}
})
/** @type {Copy} */
#copyInputObject
/** @type {Paste} */
#pasteInputObject
/** @type {Zoom} */
#zoomInputObject
/** @type {HTMLElement} */ headerElement
/** @type {HTMLElement} */ overlayElement
@@ -102,34 +106,42 @@ export default class BlueprintTemplate extends ITemplate {
}
createInputObjects() {
const gridElement = this.element.getGridDOMElement()
this.#copyInputObject = new Copy(gridElement, this.blueprint)
this.#pasteInputObject = new Paste(gridElement, this.blueprint)
this.#zoomInputObject = new Zoom(gridElement, this.blueprint)
return [
...super.createInputObjects(),
new Copy(this.element.getGridDOMElement(), this.element),
new Paste(this.element.getGridDOMElement(), this.element),
new Cut(this.element.getGridDOMElement(), this.element),
new KeyboardShortcutAction(this.element.getGridDOMElement(), this.element, {
activationKeys: Shortcut.duplicateNodes
this.#copyInputObject,
this.#pasteInputObject,
this.#zoomInputObject,
new Cut(gridElement, this.blueprint),
new KeyboardShortcut(gridElement, this.blueprint, {
activationKeys: Shortcuts.duplicateNodes
}, () =>
this.blueprint.template.getPasteInputObject().pasted(
this.blueprint.template.getCopyInputObject().copied()
)
),
new KeyboardCanc(this.element.getGridDOMElement(), this.element),
new KeyboardSelectAll(this.element.getGridDOMElement(), this.element),
new Zoom(this.element.getGridDOMElement(), this.element),
new Select(this.element.getGridDOMElement(), this.element, {
new KeyboardShortcut(gridElement, this.blueprint, {
activationKeys: Shortcuts.deleteNodes
}, () => this.blueprint.removeGraphElement(...this.blueprint.getNodes(true))),
new KeyboardShortcut(gridElement, this.blueprint, {
activationKeys: Shortcuts.selectAllNodes
}, () => this.blueprint.selectAll()),
new Select(gridElement, this.blueprint, {
clickButton: Configuration.mouseClickButton,
exitAnyButton: true,
moveEverywhere: true,
}),
new MouseScrollGraph(this.element.getGridDOMElement(), this.element, {
new MouseScrollGraph(gridElement, this.blueprint, {
clickButton: Configuration.mouseRightClickButton,
exitAnyButton: false,
moveEverywhere: true,
}),
new Unfocus(this.element.getGridDOMElement(), this.element),
new MouseTracking(this.element.getGridDOMElement(), this.element),
new KeyboardEnableZoom(this.element.getGridDOMElement(), this.element),
new Unfocus(gridElement, this.blueprint),
new MouseTracking(gridElement, this.blueprint),
new KeyboardEnableZoom(gridElement, this.blueprint),
]
}
@@ -219,11 +231,15 @@ export default class BlueprintTemplate extends ITemplate {
}
getCopyInputObject() {
return this.getInputObject(Copy)
return this.#copyInputObject
}
getPasteInputObject() {
return this.getInputObject(Paste)
return this.#pasteInputObject
}
getZoomInputObject() {
return this.#zoomInputObject
}
/**

View File

@@ -1,6 +1,6 @@
import Configuration from "../Configuration.js"
import ITemplate from "./ITemplate.js"
import KeyboardShortcutAction from "../input/keybaord/KeyboardShortcutAction.js"
import KeyboardShortcut from "../input/keyboard/KeyboardShortcut.js"
import MouseMoveDraggable from "../input/mouse/MouseMoveDraggable.js"
/** @typedef {import("../element/IDraggableElement.js").default} IDraggableElement */
@@ -25,7 +25,7 @@ export default class IDraggableTemplate extends ITemplate {
return [
...super.createInputObjects(),
this.createDraggableObject(),
new KeyboardShortcutAction(
new KeyboardShortcut(
this.element,
this.blueprint,
{

View File

@@ -31,14 +31,6 @@ export default class ITemplate {
return /** @type {IInput[]} */([])
}
/**
* @template {IInput} T
* @param {new (...any) => T} type
*/
getInputObject(type) {
return /** @type {T} */(this.inputObjects.find(object => object.constructor == type))
}
setup() {
this.#inputObjects.forEach(v => v.setup())
}

View File

@@ -2,8 +2,11 @@ import { html, nothing } from "lit"
import Configuration from "../Configuration.js"
import ElementFactory from "../element/ElementFactory.js"
import IFromToPositionedTemplate from "./IFromToPositionedTemplate.js"
import KeyboardShortcut from "../input/keyboard/KeyboardShortcut.js"
import KnotEntity from "../entity/objects/KnotEntity.js"
import MouseClick from "../input/mouse/MouseClick.js"
import MouseDbClick from "../input/mouse/MouseDbClick.js"
import Shortcuts from "../Shortcuts.js"
import Utility from "../Utility.js"
/**
@@ -85,10 +88,11 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
}
createInputObjects() {
const linkArea = this.element.querySelector(".ueb-link-area")
return [
...super.createInputObjects(),
new MouseDbClick(
this.element.querySelector(".ueb-link-area"),
linkArea,
this.blueprint,
undefined,
/** @param {[Number, Number]} location */
@@ -97,8 +101,18 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
location[1] += Configuration.knotOffset[1]
location = Utility.snapToGrid(location[0], location[1], Configuration.gridSize)
this.#createKnot(location)
}
)
},
),
new MouseClick(
linkArea,
this.blueprint,
{
enablerKey: new KeyboardShortcut(this.blueprint, this.blueprint, {
activationKeys: Shortcuts.enableLinkDelete,
})
},
() => this.blueprint.removeGraphElement(this.element),
),
]
}

View File

@@ -10,7 +10,7 @@ export default class BoolPinTemplate extends PinTemplate {
/** @type {HTMLInputElement?} */
#input
#onChangeHandler = _ => this.element.setDefaultValue(this.#input.checked)
#onChangeHandler = () => this.element.setDefaultValue(this.#input.checked)
/** @param {PropertyValues} changedProperties */
firstUpdated(changedProperties) {