mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-02-13 16:44:49 +08:00
Blueprint focusable
This commit is contained in:
@@ -55,10 +55,14 @@ u-blueprint {
|
||||
position : relative;
|
||||
height : var(--ueb-viewport-height);
|
||||
width : var(--ueb-viewport-width);
|
||||
overflow : scroll;
|
||||
overflow : hidden;
|
||||
scrollbar-width: 0;
|
||||
}
|
||||
|
||||
u-blueprint[data-focused="true"] .ueb-viewport-body {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.ueb-grid {
|
||||
--ueb-grid-line-actual-width: calc(var(--ueb-grid-line-width) / var(--ueb-scale));
|
||||
position : absolute;
|
||||
@@ -297,10 +301,10 @@ u-blueprint {
|
||||
display : block;
|
||||
position : absolute;
|
||||
visibility: hidden;
|
||||
top : min(var(--ueb-select-from-y) * 1px, var(--ueb-select-to-y) * 1px);
|
||||
left : min(var(--ueb-select-from-x) * 1px, var(--ueb-select-to-x) * 1px);
|
||||
width : calc(max(var(--ueb-select-from-x) - var(--ueb-select-to-x), var(--ueb-select-to-x) - var(--ueb-select-from-x)) * 1px);
|
||||
height : calc(max(var(--ueb-select-from-y) - var(--ueb-select-to-y), var(--ueb-select-to-y) - var(--ueb-select-from-y)) * 1px);
|
||||
top : 0;
|
||||
left : 0;
|
||||
width : 0;
|
||||
height : 0;
|
||||
background-image:
|
||||
/* Top */
|
||||
repeating-linear-gradient(90deg,
|
||||
@@ -389,4 +393,8 @@ u-blueprint {
|
||||
|
||||
.ueb-selector[data-selecting="true"] {
|
||||
visibility: visible;
|
||||
top : min(var(--ueb-select-from-y) * 1px, var(--ueb-select-to-y) * 1px);
|
||||
left : min(var(--ueb-select-from-x) * 1px, var(--ueb-select-to-x) * 1px);
|
||||
width : calc(max(var(--ueb-select-from-x) - var(--ueb-select-to-x), var(--ueb-select-to-x) - var(--ueb-select-from-x)) * 1px);
|
||||
height : calc(max(var(--ueb-select-from-y) - var(--ueb-select-to-y), var(--ueb-select-to-y) - var(--ueb-select-from-y)) * 1px);
|
||||
}
|
||||
180
dist/ueblueprint.js
vendored
180
dist/ueblueprint.js
vendored
@@ -798,13 +798,34 @@ class BlueprintTemplate extends Template {
|
||||
}
|
||||
}
|
||||
|
||||
class Pointing {
|
||||
class Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
/** @type {HTMLElement} */
|
||||
this.target = target;
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
this.blueprint = blueprint;
|
||||
this.options = options;
|
||||
if (options?.wantsFocusCallback ?? false) {
|
||||
let self = this;
|
||||
this.blueprint.addEventListener("blueprintfocus", _ => self.blueprintFocused());
|
||||
this.blueprint.addEventListener("blueprintunfocus", _ => self.blueprintUnfocused());
|
||||
}
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
console.log("focused");
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Pointing extends Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
/** @type {HTMLElement} */
|
||||
this.target = target;
|
||||
/** @type {import("../Blueprint").Blueprint}" */
|
||||
this.blueprint = blueprint;
|
||||
super(target, blueprint, options);
|
||||
this.movementSpace = this.blueprint?.getGridDOMElement() ?? document.documentElement;
|
||||
}
|
||||
|
||||
@@ -835,6 +856,7 @@ class MouseClickDrag extends Pointing {
|
||||
let self = this;
|
||||
|
||||
this.mouseDownHandler = e => {
|
||||
this.blueprint.setFocused(true);
|
||||
switch (e.button) {
|
||||
case self.clickButton:
|
||||
// Either doesn't matter or consider the click only when clicking on the parent, not descandants
|
||||
@@ -1344,10 +1366,11 @@ class MouseWheel extends Pointing {
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} target
|
||||
* @param {import("../Blueprint").Blueprint} blueprint
|
||||
* @param {import("../Blueprint").default} blueprint
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(target, blueprint, options) {
|
||||
options.wantsFocusCallback = true;
|
||||
super(target, blueprint, options);
|
||||
this.looseTarget = options?.looseTarget ?? true;
|
||||
let self = this;
|
||||
@@ -1357,15 +1380,25 @@ class MouseWheel extends Pointing {
|
||||
const location = self.getLocation(e);
|
||||
self.wheel(Math.sign(e.deltaY), location);
|
||||
};
|
||||
this.mouseParentWheelHandler = e => e.preventDefault();
|
||||
|
||||
if (this.blueprint.focused) {
|
||||
this.movementSpace.addEventListener('wheel', this.mouseWheelHandler, false);
|
||||
}
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
this.movementSpace.addEventListener('wheel', this.mouseWheelHandler, false);
|
||||
// Prevent movement space from being scrolled
|
||||
this.movementSpace.parentElement?.addEventListener('wheel', e => e.preventDefault());
|
||||
this.movementSpace.parentElement?.addEventListener('wheel', this.mouseParentWheelHandler);
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
this.movementSpace.removeEventListener('wheel', this.mouseWheelHandler, false);
|
||||
this.movementSpace.parentElement?.removeEventListener('wheel', this.mouseParentWheelHandler);
|
||||
}
|
||||
|
||||
/* Subclasses will override the following method */
|
||||
wheel(variation, location) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1494,7 +1527,7 @@ class Drag extends MouseClickDrag {
|
||||
return
|
||||
}
|
||||
|
||||
this.target.dragDispatch(d);
|
||||
this.target.dispatchDragEvent(d);
|
||||
|
||||
// Reassign the position of mouse
|
||||
this.mousePosition = mousePosition;
|
||||
@@ -1517,7 +1550,7 @@ class SelectableDraggable extends GraphElement {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.dragObject = new Drag(this, null, { // UDrag doesn't need blueprint
|
||||
this.dragObject = new Drag(this, this.blueprint, { // UDrag doesn't need blueprint
|
||||
looseTarget: true
|
||||
});
|
||||
}
|
||||
@@ -1536,7 +1569,7 @@ class SelectableDraggable extends GraphElement {
|
||||
this.setLocation([this.location[0] + value[0], this.location[1] + value[1]]);
|
||||
}
|
||||
|
||||
dragDispatch(value) {
|
||||
dispatchDragEvent(value) {
|
||||
if (!this.selected) {
|
||||
this.blueprint.unselectAll();
|
||||
this.setSelected(true);
|
||||
@@ -1597,40 +1630,103 @@ class GraphNode extends SelectableDraggable {
|
||||
|
||||
customElements.define('u-node', GraphNode);
|
||||
|
||||
class Paste {
|
||||
class KeyboardShortcut extends Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
/** @type {HTMLElement} */
|
||||
this.target = target;
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
this.blueprint = blueprint;
|
||||
this.serializer = new ObjectSerializer();
|
||||
super(target, blueprint, options);
|
||||
/** @type {String[]} */
|
||||
this.keys = this.options?.keys ?? [];
|
||||
/** @type Numeric */
|
||||
this.currentKey = 0;
|
||||
|
||||
|
||||
let self = this;
|
||||
this.pasteHandler = e => {
|
||||
self.pasted(e.clipboardData.getData("text"));
|
||||
this.keyDownHandler = e => {
|
||||
e.preventDefault();
|
||||
if (Utility.equals(e.keys[self.currentKey], e.key)) {
|
||||
if (++self.currentKey == this.keys.length) {
|
||||
self.fire();
|
||||
}
|
||||
}
|
||||
};
|
||||
this.target.addEventListener("paste", this.pasteHandler);
|
||||
}
|
||||
|
||||
pasted(value) {
|
||||
let nodes = this.serializer.readMultiple(value).map(entity => new GraphNode(entity));
|
||||
this.blueprint.addNode(...nodes);
|
||||
this.keyUpHandler = e => {
|
||||
e.preventDefault();
|
||||
for (let i = 0; i < self.currentKey; ++i) {
|
||||
if (Utility.equals(e.keys[self.currentKey], e.key)) {
|
||||
self.currentKey = i;
|
||||
break
|
||||
}
|
||||
}
|
||||
};
|
||||
if (this.keys.length > 0) {
|
||||
this.target.addEventListener("keydown", this.keyDownHandler);
|
||||
this.target.addEventListener("keyup", this.keyUpHandler);
|
||||
}
|
||||
}
|
||||
|
||||
unlistenDOMElement() {
|
||||
this.target.removeEventListener("paste", this.pasteHandler);
|
||||
this.target.removeEventListener('keydown', this.keyDownHandler);
|
||||
this.target.removeEventListener('keyup', this.keyUpHandler);
|
||||
}
|
||||
|
||||
fire() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Paste extends KeyboardShortcut {
|
||||
|
||||
constructor(target, blueprint) {
|
||||
super(target, blueprint, {
|
||||
keys: ["Control", "C"]
|
||||
});
|
||||
}
|
||||
|
||||
fire() {
|
||||
let value = navigator.clipboard.readText();
|
||||
let nodes = this.serializer.readMultiple(value).map(entity => new GraphNode(entity));
|
||||
this.blueprint.addNode(...nodes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Unfocus extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true;
|
||||
super(target, blueprint, options);
|
||||
|
||||
let self = this;
|
||||
this.clickHandler = e => self.clickedSomewhere(e);
|
||||
if (this.blueprint.focuse) {
|
||||
document.addEventListener("click", this.clickHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
clickedSomewhere(e) {
|
||||
// If target is inside the blueprint grid
|
||||
if (e.target.closest("u-blueprint")) {
|
||||
return
|
||||
}
|
||||
this.blueprint.setFocused(false);
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.addEventListener("click", this.clickHandler);
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.removeEventListener("click", this.clickHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/** @typedef {import("./graph/GraphNode").default} GraphNode */
|
||||
class Blueprint extends GraphElement {
|
||||
|
||||
insertChildren() {
|
||||
this.querySelector('[data-nodes]').append(...this.entity.nodes);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super(new BlueprintData(), new BlueprintTemplate());
|
||||
/** @type {HTMLElement} */
|
||||
@@ -1649,8 +1745,9 @@ class Blueprint extends GraphElement {
|
||||
this.zoom = 0;
|
||||
/** @type {HTMLElement} */
|
||||
this.headerElement = null;
|
||||
this.focused = false;
|
||||
/** @type {(node: GraphNode) => BoundariesInfo} */
|
||||
this.nodeBoundariesSupplier = (node) => {
|
||||
this.nodeBoundariesSupplier = node => {
|
||||
let rect = node.getBoundingClientRect();
|
||||
let gridRect = this.nodesContainerElement.getBoundingClientRect();
|
||||
const scaleCorrection = 1 / this.getScale();
|
||||
@@ -1684,7 +1781,9 @@ class Blueprint extends GraphElement {
|
||||
this.nodesContainerElement = this.querySelector('[data-nodes]');
|
||||
console.assert(this.nodesContainerElement, "Nodes container element not provided by the template.");
|
||||
this.nodesContainerElement.append(this.selectorElement);
|
||||
this.insertChildren();
|
||||
this.querySelector('[data-nodes]').append(...this.entity.nodes);
|
||||
|
||||
this.pasteObject = new Paste(this.getGridDOMElement(), this);
|
||||
|
||||
this.dragObject = new DragScroll(this.getGridDOMElement(), this, {
|
||||
clickButton: 2,
|
||||
@@ -1702,7 +1801,7 @@ class Blueprint extends GraphElement {
|
||||
exitAnyButton: true
|
||||
});
|
||||
|
||||
this.pasteObject = new Paste(this.getGridDOMElement(), this);
|
||||
this.unfocusObject = new Unfocus(this.getGridDOMElement(), this);
|
||||
}
|
||||
|
||||
getGridDOMElement() {
|
||||
@@ -1928,6 +2027,19 @@ class Blueprint extends GraphElement {
|
||||
this.nodesContainerElement.append(...graphNodes);
|
||||
}
|
||||
}
|
||||
|
||||
setFocused(value = true) {
|
||||
if (this.focused == value) {
|
||||
return;
|
||||
}
|
||||
let event = new CustomEvent(value ? "blueprintfocus" : "blueprintunfocus");
|
||||
this.focused = value;
|
||||
this.dataset.focused = this.focused;
|
||||
if (!this.focused) {
|
||||
this.unselectAll();
|
||||
}
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('u-blueprint', Blueprint);
|
||||
|
||||
@@ -7,14 +7,11 @@ import Utility from "./Utility"
|
||||
import Zoom from "./input/Zoom"
|
||||
import BlueprintData from "./BlueprintData"
|
||||
import Paste from "./input/Paste"
|
||||
import Unfocus from "./input/Unfocus"
|
||||
|
||||
/** @typedef {import("./graph/GraphNode").default} GraphNode */
|
||||
export default class Blueprint extends GraphElement {
|
||||
|
||||
insertChildren() {
|
||||
this.querySelector('[data-nodes]').append(...this.entity.nodes)
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super(new BlueprintData(), new BlueprintTemplate())
|
||||
/** @type {HTMLElement} */
|
||||
@@ -33,8 +30,9 @@ export default class Blueprint extends GraphElement {
|
||||
this.zoom = 0
|
||||
/** @type {HTMLElement} */
|
||||
this.headerElement = null
|
||||
this.focused = false
|
||||
/** @type {(node: GraphNode) => BoundariesInfo} */
|
||||
this.nodeBoundariesSupplier = (node) => {
|
||||
this.nodeBoundariesSupplier = node => {
|
||||
let rect = node.getBoundingClientRect()
|
||||
let gridRect = this.nodesContainerElement.getBoundingClientRect()
|
||||
const scaleCorrection = 1 / this.getScale()
|
||||
@@ -68,7 +66,9 @@ export default class Blueprint extends GraphElement {
|
||||
this.nodesContainerElement = this.querySelector('[data-nodes]')
|
||||
console.assert(this.nodesContainerElement, "Nodes container element not provided by the template.")
|
||||
this.nodesContainerElement.append(this.selectorElement)
|
||||
this.insertChildren()
|
||||
this.querySelector('[data-nodes]').append(...this.entity.nodes)
|
||||
|
||||
this.pasteObject = new Paste(this.getGridDOMElement(), this)
|
||||
|
||||
this.dragObject = new DragScroll(this.getGridDOMElement(), this, {
|
||||
clickButton: 2,
|
||||
@@ -86,7 +86,7 @@ export default class Blueprint extends GraphElement {
|
||||
exitAnyButton: true
|
||||
})
|
||||
|
||||
this.pasteObject = new Paste(this.getGridDOMElement(), this)
|
||||
this.unfocusObject = new Unfocus(this.getGridDOMElement(), this)
|
||||
}
|
||||
|
||||
getGridDOMElement() {
|
||||
@@ -312,6 +312,19 @@ export default class Blueprint extends GraphElement {
|
||||
this.nodesContainerElement.append(...graphNodes)
|
||||
}
|
||||
}
|
||||
|
||||
setFocused(value = true) {
|
||||
if (this.focused == value) {
|
||||
return;
|
||||
}
|
||||
let event = new CustomEvent(value ? "blueprintfocus" : "blueprintunfocus")
|
||||
this.focused = value
|
||||
this.dataset.focused = this.focused
|
||||
if (!this.focused) {
|
||||
this.unselectAll()
|
||||
}
|
||||
this.dispatchEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('u-blueprint', Blueprint)
|
||||
|
||||
@@ -17,7 +17,7 @@ export default class SelectableDraggable extends GraphElement {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
this.dragObject = new Drag(this, null, { // UDrag doesn't need blueprint
|
||||
this.dragObject = new Drag(this, this.blueprint, { // UDrag doesn't need blueprint
|
||||
looseTarget: true
|
||||
})
|
||||
}
|
||||
@@ -36,7 +36,7 @@ export default class SelectableDraggable extends GraphElement {
|
||||
this.setLocation([this.location[0] + value[0], this.location[1] + value[1]])
|
||||
}
|
||||
|
||||
dragDispatch(value) {
|
||||
dispatchDragEvent(value) {
|
||||
if (!this.selected) {
|
||||
this.blueprint.unselectAll()
|
||||
this.setSelected(true)
|
||||
|
||||
23
js/input/Context.js
Normal file
23
js/input/Context.js
Normal file
@@ -0,0 +1,23 @@
|
||||
export default class Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
/** @type {HTMLElement} */
|
||||
this.target = target
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
this.blueprint = blueprint
|
||||
this.options = options
|
||||
if (options?.wantsFocusCallback ?? false) {
|
||||
let self = this
|
||||
this.blueprint.addEventListener("blueprintfocus", _ => self.blueprintFocused())
|
||||
this.blueprint.addEventListener("blueprintunfocus", _ => self.blueprintUnfocused())
|
||||
}
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
console.log("focused")
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import MouseClickDrag from "./MouseClickDrag"
|
||||
|
||||
export default class Drag extends MouseClickDrag {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
super(target, blueprint, options)
|
||||
this.stepSize = parseInt(options?.stepSize)
|
||||
@@ -33,7 +34,7 @@ export default class Drag extends MouseClickDrag {
|
||||
return
|
||||
}
|
||||
|
||||
this.target.dragDispatch(d)
|
||||
this.target.dispatchDragEvent(d)
|
||||
|
||||
// Reassign the position of mouse
|
||||
this.mousePosition = mousePosition
|
||||
|
||||
46
js/input/KeyboardShortcut.js
Normal file
46
js/input/KeyboardShortcut.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import Context from "./Context"
|
||||
import Utility from "../Utility"
|
||||
|
||||
export default class KeyboardShortcut extends Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
super(target, blueprint, options)
|
||||
/** @type {String[]} */
|
||||
this.keys = this.options?.keys ?? []
|
||||
/** @type Numeric */
|
||||
this.currentKey = 0
|
||||
|
||||
|
||||
let self = this
|
||||
this.keyDownHandler = e => {
|
||||
e.preventDefault()
|
||||
if (Utility.equals(e.keys[self.currentKey], e.key)) {
|
||||
if (++self.currentKey == this.keys.length) {
|
||||
self.fire()
|
||||
}
|
||||
}
|
||||
}
|
||||
this.keyUpHandler = e => {
|
||||
e.preventDefault()
|
||||
for (let i = 0; i < self.currentKey; ++i) {
|
||||
if (Utility.equals(e.keys[self.currentKey], e.key)) {
|
||||
self.currentKey = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.keys.length > 0) {
|
||||
this.target.addEventListener("keydown", this.keyDownHandler)
|
||||
this.target.addEventListener("keyup", this.keyUpHandler)
|
||||
}
|
||||
}
|
||||
|
||||
unlistenDOMElement() {
|
||||
this.target.removeEventListener('keydown', this.keyDownHandler)
|
||||
this.target.removeEventListener('keyup', this.keyUpHandler)
|
||||
}
|
||||
|
||||
fire() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import Pointing from "./Pointing"
|
||||
* This class manages the ui gesture of mouse click and drag. Tha actual operations are implemented by the subclasses.
|
||||
*/
|
||||
export default class MouseClickDrag extends Pointing {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
super(target, blueprint, options)
|
||||
this.clickButton = options?.clickButton ?? 0
|
||||
@@ -16,6 +17,7 @@ export default class MouseClickDrag extends Pointing {
|
||||
let self = this
|
||||
|
||||
this.mouseDownHandler = e => {
|
||||
this.blueprint.setFocused(true)
|
||||
switch (e.button) {
|
||||
case self.clickButton:
|
||||
// Either doesn't matter or consider the click only when clicking on the parent, not descandants
|
||||
|
||||
@@ -5,10 +5,11 @@ export default class MouseWheel extends Pointing {
|
||||
/**
|
||||
*
|
||||
* @param {HTMLElement} target
|
||||
* @param {import("../Blueprint").Blueprint} blueprint
|
||||
* @param {import("../Blueprint").default} blueprint
|
||||
* @param {Object} options
|
||||
*/
|
||||
constructor(target, blueprint, options) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
this.looseTarget = options?.looseTarget ?? true
|
||||
let self = this
|
||||
@@ -18,14 +19,24 @@ export default class MouseWheel extends Pointing {
|
||||
const location = self.getLocation(e)
|
||||
self.wheel(Math.sign(e.deltaY), location)
|
||||
}
|
||||
this.mouseParentWheelHandler = e => e.preventDefault()
|
||||
|
||||
if (this.blueprint.focused) {
|
||||
this.movementSpace.addEventListener('wheel', this.mouseWheelHandler, false)
|
||||
}
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
this.movementSpace.addEventListener('wheel', this.mouseWheelHandler, false)
|
||||
// Prevent movement space from being scrolled
|
||||
this.movementSpace.parentElement?.addEventListener('wheel', e => e.preventDefault())
|
||||
this.movementSpace.parentElement?.addEventListener('wheel', this.mouseParentWheelHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
this.movementSpace.removeEventListener('wheel', this.mouseWheelHandler, false)
|
||||
this.movementSpace.parentElement?.removeEventListener('wheel', this.mouseParentWheelHandler)
|
||||
}
|
||||
|
||||
/* Subclasses will override the following method */
|
||||
wheel(variation, location) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,18 @@
|
||||
import GraphNode from "../graph/GraphNode"
|
||||
import ObjectSerializer from "../serialization/ObjectSerializer"
|
||||
import KeyboardShortcut from "./KeyboardShortcut"
|
||||
|
||||
export default class Paste {
|
||||
export default class Paste extends KeyboardShortcut {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
/** @type {HTMLElement} */
|
||||
this.target = target
|
||||
/** @type {import("../Blueprint").default}" */
|
||||
this.blueprint = blueprint
|
||||
this.serializer = new ObjectSerializer()
|
||||
|
||||
let self = this
|
||||
this.pasteHandler = e => {
|
||||
self.pasted(e.clipboardData.getData("text"))
|
||||
}
|
||||
this.target.addEventListener("paste", this.pasteHandler)
|
||||
constructor(target, blueprint) {
|
||||
super(target, blueprint, {
|
||||
keys: ["Control", "C"]
|
||||
})
|
||||
}
|
||||
|
||||
pasted(value) {
|
||||
fire() {
|
||||
let value = navigator.clipboard.readText()
|
||||
let nodes = this.serializer.readMultiple(value).map(entity => new GraphNode(entity))
|
||||
this.blueprint.addNode(...nodes)
|
||||
}
|
||||
|
||||
unlistenDOMElement() {
|
||||
this.target.removeEventListener("paste", this.pasteHandler)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import Context from "./Context"
|
||||
import Utility from "../Utility"
|
||||
|
||||
export default class Pointing {
|
||||
export default class Pointing extends Context {
|
||||
|
||||
constructor(target, blueprint, options) {
|
||||
/** @type {HTMLElement} */
|
||||
this.target = target
|
||||
/** @type {import("../Blueprint").Blueprint}" */
|
||||
this.blueprint = blueprint
|
||||
super(target, blueprint, options)
|
||||
this.movementSpace = this.blueprint?.getGridDOMElement() ?? document.documentElement
|
||||
}
|
||||
|
||||
|
||||
35
js/input/Unfocus.js
Normal file
35
js/input/Unfocus.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import Context from "./Context";
|
||||
|
||||
export default class Unfocus extends Context {
|
||||
|
||||
constructor(target, blueprint, options = {}) {
|
||||
options.wantsFocusCallback = true
|
||||
super(target, blueprint, options)
|
||||
|
||||
let self = this
|
||||
this.clickHandler = e => self.clickedSomewhere(e)
|
||||
if (this.blueprint.focuse) {
|
||||
document.addEventListener("click", this.clickHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {MouseEvent} e
|
||||
*/
|
||||
clickedSomewhere(e) {
|
||||
// If target is inside the blueprint grid
|
||||
if (e.target.closest("u-blueprint")) {
|
||||
return
|
||||
}
|
||||
this.blueprint.setFocused(false)
|
||||
}
|
||||
|
||||
blueprintFocused() {
|
||||
document.addEventListener("click", this.clickHandler)
|
||||
}
|
||||
|
||||
blueprintUnfocused() {
|
||||
document.removeEventListener("click", this.clickHandler)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import MouseWheel from "./MouseWheel";
|
||||
import MouseWheel from "./MouseWheel"
|
||||
|
||||
export default class Zoom extends MouseWheel {
|
||||
|
||||
wheel(variation, location) {
|
||||
let zoomLevel = this.blueprint.getZoom()
|
||||
zoomLevel -= variation
|
||||
|
||||
Reference in New Issue
Block a user