mirror of
https://github.com/pandorafms/pandorafms.git
synced 2025-09-26 03:19:05 +02:00
Improved the movement of the visual console line element
This commit is contained in:
parent
f6dfe023e9
commit
dbf141d866
@ -469,6 +469,50 @@ function createVisualConsole(
|
|||||||
})
|
})
|
||||||
.init();
|
.init();
|
||||||
});
|
});
|
||||||
|
// VC Line Item moved.
|
||||||
|
visualConsole.onLineMoved(function(e) {
|
||||||
|
var id = e.item.props.id;
|
||||||
|
var data = {
|
||||||
|
startX: e.startPosition.x,
|
||||||
|
startY: e.startPosition.y,
|
||||||
|
endX: e.endPosition.x,
|
||||||
|
endY: e.endPosition.y
|
||||||
|
};
|
||||||
|
var taskId = "visual-console-item-update-" + id;
|
||||||
|
|
||||||
|
// Persist the new position.
|
||||||
|
asyncTaskManager
|
||||||
|
.add(taskId, function(done) {
|
||||||
|
var abortable = updateVisualConsoleItem(
|
||||||
|
baseUrl,
|
||||||
|
visualConsole.props.id,
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
function(error, data) {
|
||||||
|
// if (!error && !data) return;
|
||||||
|
if (error || !data) {
|
||||||
|
console.log(
|
||||||
|
"[ERROR]",
|
||||||
|
"[VISUAL-CONSOLE-CLIENT]",
|
||||||
|
"[API]",
|
||||||
|
error ? error.message : "Invalid response"
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: Move the element to its initial position.
|
||||||
|
}
|
||||||
|
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
cancel: function() {
|
||||||
|
abortable.abort();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.init();
|
||||||
|
});
|
||||||
|
|
||||||
// VC Item resized.
|
// VC Item resized.
|
||||||
visualConsole.onItemResized(function(e) {
|
visualConsole.onItemResized(function(e) {
|
||||||
|
@ -426,10 +426,10 @@ final class Container extends Model
|
|||||||
*
|
*
|
||||||
* @param integer $itemId Identifier of the Item.
|
* @param integer $itemId Identifier of the Item.
|
||||||
*
|
*
|
||||||
* @return Item Item.
|
* @return Model Item or Line.
|
||||||
* @throws \Exception When the data cannot be retrieved from the DB.
|
* @throws \Exception When the data cannot be retrieved from the DB.
|
||||||
*/
|
*/
|
||||||
public static function getItemFromDB(int $itemId): Item
|
public static function getItemFromDB(int $itemId): Model
|
||||||
{
|
{
|
||||||
// Default filter.
|
// Default filter.
|
||||||
$filter = ['id' => $itemId];
|
$filter = ['id' => $itemId];
|
||||||
|
@ -218,64 +218,70 @@ final class Line extends Model
|
|||||||
protected function encode(array $data): array
|
protected function encode(array $data): array
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
|
$result['type'] = LINE_ITEM;
|
||||||
|
|
||||||
$id = static::getId($data);
|
$id = static::getId($data);
|
||||||
if ($id) {
|
if ($id) {
|
||||||
$result['id'] = $id;
|
$result['id'] = $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$id_layout = static::getIdLayout($data);
|
$layoutId = static::getIdLayout($data);
|
||||||
if ($id_layout) {
|
if ($layoutId > 0) {
|
||||||
$result['id_layout'] = $id_layout;
|
$result['id_layout'] = $layoutId;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pos_x = static::parseIntOr(
|
$startX = static::parseIntOr(
|
||||||
static::issetInArray($data, ['x', 'pos_x', 'posX']),
|
static::issetInArray($data, ['pos_x', 'startX']),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
if ($pos_x !== null) {
|
if ($startX !== null) {
|
||||||
$result['pos_x'] = $pos_x;
|
$result['pos_x'] = $startX;
|
||||||
}
|
}
|
||||||
|
|
||||||
$pos_y = static::parseIntOr(
|
$startY = static::parseIntOr(
|
||||||
static::issetInArray($data, ['y', 'pos_y', 'posY']),
|
static::issetInArray($data, ['pos_y', 'startY']),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
if ($pos_y !== null) {
|
if ($startY !== null) {
|
||||||
$result['pos_y'] = $pos_y;
|
$result['pos_y'] = $startY;
|
||||||
}
|
}
|
||||||
|
|
||||||
$height = static::getHeight($data);
|
$endX = static::parseIntOr(
|
||||||
if ($height !== null) {
|
static::issetInArray($data, ['width', 'endX']),
|
||||||
$result['height'] = $height;
|
|
||||||
}
|
|
||||||
|
|
||||||
$width = static::getWidth($data);
|
|
||||||
if ($width !== null) {
|
|
||||||
$result['width'] = $width;
|
|
||||||
}
|
|
||||||
|
|
||||||
$type = static::parseIntOr(
|
|
||||||
static::issetInArray($data, ['type']),
|
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
if ($type !== null) {
|
if ($endX !== null) {
|
||||||
$result['type'] = $type;
|
$result['width'] = $endX;
|
||||||
}
|
}
|
||||||
|
|
||||||
$border_width = static::getBorderWidth($data);
|
$endY = static::parseIntOr(
|
||||||
if ($border_width !== null) {
|
static::issetInArray($data, ['height', 'endY']),
|
||||||
$result['border_width'] = $border_width;
|
null
|
||||||
|
);
|
||||||
|
if ($endY !== null) {
|
||||||
|
$result['height'] = $endY;
|
||||||
}
|
}
|
||||||
|
|
||||||
$border_color = static::extractBorderColor($data);
|
$borderWidth = static::getBorderWidth($data);
|
||||||
if ($border_color !== null) {
|
if ($borderWidth !== null) {
|
||||||
$result['border_color'] = $border_color;
|
$result['border_width'] = $borderWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
$show_on_top = static::issetInArray($data, ['isOnTop', 'show_on_top', 'showOnTop']);
|
$borderColor = static::extractBorderColor($data);
|
||||||
if ($show_on_top !== null) {
|
if ($borderColor !== null) {
|
||||||
$result['show_on_top'] = static::parseBool($show_on_top);
|
$result['border_color'] = $borderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
$showOnTop = static::issetInArray(
|
||||||
|
$data,
|
||||||
|
[
|
||||||
|
'isOnTop',
|
||||||
|
'show_on_top',
|
||||||
|
'showOnTop',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
if ($showOnTop !== null) {
|
||||||
|
$result['show_on_top'] = static::parseBool($showOnTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -23,7 +23,7 @@ import ColorCloud, { colorCloudPropsDecoder } from "./items/ColorCloud";
|
|||||||
import Group, { groupPropsDecoder } from "./items/Group";
|
import Group, { groupPropsDecoder } from "./items/Group";
|
||||||
import Clock, { clockPropsDecoder } from "./items/Clock";
|
import Clock, { clockPropsDecoder } from "./items/Clock";
|
||||||
import Box, { boxPropsDecoder } from "./items/Box";
|
import Box, { boxPropsDecoder } from "./items/Box";
|
||||||
import Line, { linePropsDecoder } from "./items/Line";
|
import Line, { linePropsDecoder, LineMovedEvent } from "./items/Line";
|
||||||
import Label, { labelPropsDecoder } from "./items/Label";
|
import Label, { labelPropsDecoder } from "./items/Label";
|
||||||
import SimpleValue, { simpleValuePropsDecoder } from "./items/SimpleValue";
|
import SimpleValue, { simpleValuePropsDecoder } from "./items/SimpleValue";
|
||||||
import EventsHistory, {
|
import EventsHistory, {
|
||||||
@ -211,6 +211,8 @@ export default class VisualConsole {
|
|||||||
private readonly dblClickEventManager = new TypedEvent<ItemClickEvent>();
|
private readonly dblClickEventManager = new TypedEvent<ItemClickEvent>();
|
||||||
// Event manager for move events.
|
// Event manager for move events.
|
||||||
private readonly movedEventManager = new TypedEvent<ItemMovedEvent>();
|
private readonly movedEventManager = new TypedEvent<ItemMovedEvent>();
|
||||||
|
// Event manager for line move events.
|
||||||
|
private readonly lineMovedEventManager = new TypedEvent<LineMovedEvent>();
|
||||||
// Event manager for resize events.
|
// Event manager for resize events.
|
||||||
private readonly resizedEventManager = new TypedEvent<ItemResizedEvent>();
|
private readonly resizedEventManager = new TypedEvent<ItemResizedEvent>();
|
||||||
// Event manager for remove events.
|
// Event manager for remove events.
|
||||||
@ -275,6 +277,17 @@ export default class VisualConsole {
|
|||||||
// console.log(`Movement finished for element #${e.item.props.id}`, e);
|
// console.log(`Movement finished for element #${e.item.props.id}`, e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React to a line movement.
|
||||||
|
* @param e Event object.
|
||||||
|
*/
|
||||||
|
private handleLineElementMovementFinished: (
|
||||||
|
e: LineMovedEvent
|
||||||
|
) => void = e => {
|
||||||
|
this.lineMovedEventManager.emit(e);
|
||||||
|
// console.log(`Movement finished for element #${e.item.props.id}`, e);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* React to a resizement on an element.
|
* React to a resizement on an element.
|
||||||
* @param e Event object.
|
* @param e Event object.
|
||||||
@ -403,13 +416,20 @@ export default class VisualConsole {
|
|||||||
// Item event handlers.
|
// Item event handlers.
|
||||||
itemInstance.onClick(context.handleElementClick);
|
itemInstance.onClick(context.handleElementClick);
|
||||||
itemInstance.onDblClick(context.handleElementDblClick);
|
itemInstance.onDblClick(context.handleElementDblClick);
|
||||||
itemInstance.onMoved(context.handleElementMovement);
|
|
||||||
itemInstance.onMovementFinished(context.handleElementMovementFinished);
|
|
||||||
itemInstance.onResized(context.handleElementResizement);
|
|
||||||
itemInstance.onResizeFinished(context.handleElementResizementFinished);
|
|
||||||
itemInstance.onRemove(context.handleElementRemove);
|
itemInstance.onRemove(context.handleElementRemove);
|
||||||
itemInstance.onSelectionChanged(context.handleElementSelectionChanged);
|
itemInstance.onSelectionChanged(context.handleElementSelectionChanged);
|
||||||
|
|
||||||
|
if (itemInstance instanceof Line) {
|
||||||
|
itemInstance.onLineMovementFinished(
|
||||||
|
context.handleLineElementMovementFinished
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
itemInstance.onMoved(context.handleElementMovement);
|
||||||
|
itemInstance.onMovementFinished(context.handleElementMovementFinished);
|
||||||
|
itemInstance.onResized(context.handleElementResizement);
|
||||||
|
itemInstance.onResizeFinished(context.handleElementResizementFinished);
|
||||||
|
}
|
||||||
|
|
||||||
// Add the item to the DOM.
|
// Add the item to the DOM.
|
||||||
context.containerRef.append(itemInstance.elementRef);
|
context.containerRef.append(itemInstance.elementRef);
|
||||||
return itemInstance;
|
return itemInstance;
|
||||||
@ -806,6 +826,22 @@ export default class VisualConsole {
|
|||||||
return disposable;
|
return disposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an event handler to the movement of the visual console line elements.
|
||||||
|
* @param listener Function which is going to be executed when a linked console is moved.
|
||||||
|
*/
|
||||||
|
public onLineMoved(listener: Listener<LineMovedEvent>): Disposable {
|
||||||
|
/*
|
||||||
|
* The '.on' function returns a function which will clean the event
|
||||||
|
* listener when executed. We store all the 'dispose' functions to
|
||||||
|
* call them when the item should be cleared.
|
||||||
|
*/
|
||||||
|
const disposable = this.lineMovedEventManager.on(listener);
|
||||||
|
this.disposables.push(disposable);
|
||||||
|
|
||||||
|
return disposable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an event handler to the resizement of the visual console elements.
|
* Add an event handler to the resizement of the visual console elements.
|
||||||
* @param listener Function which is going to be executed when a linked console is moved.
|
* @param listener Function which is going to be executed when a linked console is moved.
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
addMovementListener
|
addMovementListener
|
||||||
} from "../lib";
|
} from "../lib";
|
||||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||||
|
import TypedEvent, { Listener, Disposable } from "../lib/TypedEvent";
|
||||||
|
|
||||||
interface LineProps extends ItemProps {
|
interface LineProps extends ItemProps {
|
||||||
// Overrided properties.
|
// Overrided properties.
|
||||||
@ -68,68 +69,143 @@ export function linePropsDecoder(data: AnyObject): LineProps | never {
|
|||||||
...props,
|
...props,
|
||||||
// Enhance the props extracting the box size and position.
|
// Enhance the props extracting the box size and position.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||||
...Line.extractBoxSizeAndPosition(props)
|
...Line.extractBoxSizeAndPosition(props.startPosition, props.endPosition)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const svgNS = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
|
export interface LineMovedEvent {
|
||||||
|
item: Line;
|
||||||
|
startPosition: LineProps["startPosition"];
|
||||||
|
endPosition: LineProps["endPosition"];
|
||||||
|
}
|
||||||
|
|
||||||
export default class Line extends Item<LineProps> {
|
export default class Line extends Item<LineProps> {
|
||||||
|
private circleRadius = 8;
|
||||||
// To control if the line movement is enabled.
|
// To control if the line movement is enabled.
|
||||||
private moveMode: boolean = false;
|
private moveMode: boolean = false;
|
||||||
|
// To control if the line is moving.
|
||||||
|
private isMoving: boolean = false;
|
||||||
|
|
||||||
// // This function will only run the 2nd arg function after the time
|
// Event manager for moved events.
|
||||||
// // of the first arg have passed after its last execution.
|
private readonly lineMovedEventManager = new TypedEvent<LineMovedEvent>();
|
||||||
// private debouncedMovementSave = debounce(
|
// List of references to clean the event listeners.
|
||||||
// 500, // ms.
|
private readonly lineMovedEventDisposables: Disposable[] = [];
|
||||||
// (x: Position["x"], y: Position["y"]) => {
|
|
||||||
// const prevPosition = {
|
|
||||||
// x: this.props.x,
|
|
||||||
// y: this.props.y
|
|
||||||
// };
|
|
||||||
// const newPosition = {
|
|
||||||
// x: x,
|
|
||||||
// y: y
|
|
||||||
// };
|
|
||||||
|
|
||||||
// if (!this.positionChanged(prevPosition, newPosition)) return;
|
// This function will only run the 2nd arg function after the time
|
||||||
|
// of the first arg have passed after its last execution.
|
||||||
|
private debouncedStartPositionMovementSave = debounce(
|
||||||
|
500, // ms.
|
||||||
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
|
this.isMoving = false;
|
||||||
|
const startPosition = { x, y };
|
||||||
|
// Emit the movement event.
|
||||||
|
this.lineMovedEventManager.emit({
|
||||||
|
item: this,
|
||||||
|
startPosition,
|
||||||
|
endPosition: this.props.endPosition
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// This property will store the function
|
||||||
|
// to clean the movement listener.
|
||||||
|
private removeStartPositionMovement: Function | null = null;
|
||||||
|
|
||||||
// // Save the new position to the props.
|
/**
|
||||||
// this.move(x, y);
|
* Start the movement funtionality for the start position.
|
||||||
// // Emit the movement event.
|
* @param element Element to move inside its container.
|
||||||
// this.movedEventManager.emit({
|
*/
|
||||||
// item: this,
|
private initStartPositionMovementListener(
|
||||||
// prevPosition: prevPosition,
|
element: HTMLElement,
|
||||||
// newPosition: newPosition
|
container: HTMLElement
|
||||||
// });
|
): void {
|
||||||
// }
|
this.removeStartPositionMovement = addMovementListener(
|
||||||
// );
|
element,
|
||||||
// // This property will store the function
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
// // to clean the movement listener.
|
// Calculate the center of the circle.
|
||||||
// private removeMovement: Function | null = null;
|
x += this.circleRadius;
|
||||||
|
y += this.circleRadius;
|
||||||
|
|
||||||
// /**
|
const startPosition = { x, y };
|
||||||
// * Start the movement funtionality.
|
|
||||||
// * @param element Element to move inside its container.
|
this.isMoving = true;
|
||||||
// */
|
this.props = {
|
||||||
// private initMovementListener(element: HTMLElement): void {
|
...this.props,
|
||||||
// this.removeMovement = addMovementListener(
|
startPosition
|
||||||
// element,
|
};
|
||||||
// (x: Position["x"], y: Position["y"]) => {
|
|
||||||
// // Move the DOM element.
|
// Run the end function.
|
||||||
// this.moveElement(x, y);
|
this.debouncedStartPositionMovementSave(x, y);
|
||||||
// // Run the save function.
|
},
|
||||||
// this.debouncedMovementSave(x, y);
|
container
|
||||||
// }
|
);
|
||||||
// );
|
}
|
||||||
// }
|
/**
|
||||||
// /**
|
* Stop the movement fun
|
||||||
// * Stop the movement fun
|
*/
|
||||||
// */
|
private stopStartPositionMovementListener(): void {
|
||||||
// private stopMovementListener(): void {
|
if (this.removeStartPositionMovement) {
|
||||||
// if (this.removeMovement) {
|
this.removeStartPositionMovement();
|
||||||
// this.removeMovement();
|
this.removeStartPositionMovement = null;
|
||||||
// this.removeMovement = null;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
// This function will only run the 2nd arg function after the time
|
||||||
|
// of the first arg have passed after its last execution.
|
||||||
|
private debouncedEndPositionMovementSave = debounce(
|
||||||
|
500, // ms.
|
||||||
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
|
this.isMoving = false;
|
||||||
|
const endPosition = { x, y };
|
||||||
|
// Emit the movement event.
|
||||||
|
this.lineMovedEventManager.emit({
|
||||||
|
item: this,
|
||||||
|
endPosition,
|
||||||
|
startPosition: this.props.startPosition
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// This property will store the function
|
||||||
|
// to clean the movement listener.
|
||||||
|
private removeEndPositionMovement: Function | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End the movement funtionality for the end position.
|
||||||
|
* @param element Element to move inside its container.
|
||||||
|
*/
|
||||||
|
private initEndPositionMovementListener(
|
||||||
|
element: HTMLElement,
|
||||||
|
container: HTMLElement
|
||||||
|
): void {
|
||||||
|
this.removeEndPositionMovement = addMovementListener(
|
||||||
|
element,
|
||||||
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
|
// Calculate the center of the circle.
|
||||||
|
x += this.circleRadius;
|
||||||
|
y += this.circleRadius;
|
||||||
|
|
||||||
|
this.isMoving = true;
|
||||||
|
this.props = {
|
||||||
|
...this.props,
|
||||||
|
endPosition: { x, y }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run the end function.
|
||||||
|
this.debouncedEndPositionMovementSave(x, y);
|
||||||
|
},
|
||||||
|
container
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Stop the movement function.
|
||||||
|
*/
|
||||||
|
private stopEndPositionMovementListener(): void {
|
||||||
|
if (this.removeEndPositionMovement) {
|
||||||
|
this.removeEndPositionMovement();
|
||||||
|
this.removeEndPositionMovement = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
@ -142,7 +218,10 @@ export default class Line extends Item<LineProps> {
|
|||||||
super(
|
super(
|
||||||
{
|
{
|
||||||
...props,
|
...props,
|
||||||
...Line.extractBoxSizeAndPosition(props)
|
...Line.extractBoxSizeAndPosition(
|
||||||
|
props.startPosition,
|
||||||
|
props.endPosition
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...meta,
|
...meta,
|
||||||
@ -164,7 +243,10 @@ export default class Line extends Item<LineProps> {
|
|||||||
public setProps(newProps: LineProps) {
|
public setProps(newProps: LineProps) {
|
||||||
super.setProps({
|
super.setProps({
|
||||||
...newProps,
|
...newProps,
|
||||||
...Line.extractBoxSizeAndPosition(newProps)
|
...Line.extractBoxSizeAndPosition(
|
||||||
|
newProps.startPosition,
|
||||||
|
newProps.endPosition
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,15 +284,11 @@ export default class Line extends Item<LineProps> {
|
|||||||
color // Line color
|
color // Line color
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const startIsLeft = startPosition.x - endPosition.x <= 0;
|
|
||||||
const startIsTop = startPosition.y - endPosition.y <= 0;
|
|
||||||
|
|
||||||
const x1 = startPosition.x - x + lineWidth / 2;
|
const x1 = startPosition.x - x + lineWidth / 2;
|
||||||
const y1 = startPosition.y - y + lineWidth / 2;
|
const y1 = startPosition.y - y + lineWidth / 2;
|
||||||
const x2 = endPosition.x - x + lineWidth / 2;
|
const x2 = endPosition.x - x + lineWidth / 2;
|
||||||
const y2 = endPosition.y - y + lineWidth / 2;
|
const y2 = endPosition.y - y + lineWidth / 2;
|
||||||
|
|
||||||
const svgNS = "http://www.w3.org/2000/svg";
|
|
||||||
// SVG container.
|
// SVG container.
|
||||||
const svg = document.createElementNS(svgNS, "svg");
|
const svg = document.createElementNS(svgNS, "svg");
|
||||||
// Set SVG size.
|
// Set SVG size.
|
||||||
@ -227,36 +305,130 @@ export default class Line extends Item<LineProps> {
|
|||||||
svg.append(line);
|
svg.append(line);
|
||||||
element.append(svg);
|
element.append(svg);
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updateDomElement(element: HTMLElement): void {
|
||||||
|
const {
|
||||||
|
x, // Box x
|
||||||
|
y, // Box y
|
||||||
|
width, // Box width
|
||||||
|
height, // Box height
|
||||||
|
lineWidth, // Line thickness
|
||||||
|
startPosition, // Line start position
|
||||||
|
endPosition, // Line end position
|
||||||
|
color // Line color
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
|
const x1 = startPosition.x - x + lineWidth / 2;
|
||||||
|
const y1 = startPosition.y - y + lineWidth / 2;
|
||||||
|
const x2 = endPosition.x - x + lineWidth / 2;
|
||||||
|
const y2 = endPosition.y - y + lineWidth / 2;
|
||||||
|
|
||||||
|
const svgs = element.getElementsByTagName("svg");
|
||||||
|
|
||||||
|
if (svgs.length > 0) {
|
||||||
|
const svg = svgs.item(0);
|
||||||
|
|
||||||
|
if (svg != null) {
|
||||||
|
// Set SVG size.
|
||||||
|
svg.setAttribute("width", `${width + lineWidth}`);
|
||||||
|
svg.setAttribute("height", `${height + lineWidth}`);
|
||||||
|
|
||||||
|
const lines = svg.getElementsByTagNameNS(svgNS, "line");
|
||||||
|
|
||||||
|
if (lines.length > 0) {
|
||||||
|
const line = lines.item(0);
|
||||||
|
|
||||||
|
if (line != null) {
|
||||||
|
line.setAttribute("x1", `${x1}`);
|
||||||
|
line.setAttribute("y1", `${y1}`);
|
||||||
|
line.setAttribute("x2", `${x2}`);
|
||||||
|
line.setAttribute("y2", `${y2}`);
|
||||||
|
line.setAttribute("stroke", color || "black");
|
||||||
|
line.setAttribute("stroke-width", `${lineWidth}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.moveMode) {
|
if (this.moveMode) {
|
||||||
const startCircle = document.createElement("div");
|
const startIsLeft = startPosition.x - endPosition.x <= 0;
|
||||||
startCircle.style.width = "16px";
|
const startIsTop = startPosition.y - endPosition.y <= 0;
|
||||||
startCircle.style.height = "16px";
|
|
||||||
|
let startCircle: HTMLElement = document.createElement("div");
|
||||||
|
let endCircle: HTMLElement = document.createElement("div");
|
||||||
|
|
||||||
|
if (this.isMoving) {
|
||||||
|
const circlesStart = element.getElementsByClassName(
|
||||||
|
"visual-console-item-line-circle-start"
|
||||||
|
);
|
||||||
|
if (circlesStart.length > 0) {
|
||||||
|
const circle = circlesStart.item(0) as HTMLElement;
|
||||||
|
if (circle) startCircle = circle;
|
||||||
|
}
|
||||||
|
const circlesEnd = element.getElementsByClassName(
|
||||||
|
"visual-console-item-line-circle-end"
|
||||||
|
);
|
||||||
|
if (circlesEnd.length > 0) {
|
||||||
|
const circle = circlesEnd.item(0) as HTMLElement;
|
||||||
|
if (circle) endCircle = circle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
startCircle.classList.add(
|
||||||
|
"visual-console-item-line-circle",
|
||||||
|
"visual-console-item-line-circle-start"
|
||||||
|
);
|
||||||
|
startCircle.style.width = `${this.circleRadius * 2}px`;
|
||||||
|
startCircle.style.height = `${this.circleRadius * 2}px`;
|
||||||
startCircle.style.borderRadius = "50%";
|
startCircle.style.borderRadius = "50%";
|
||||||
startCircle.style.backgroundColor = "white";
|
startCircle.style.backgroundColor = "white";
|
||||||
startCircle.style.position = "absolute";
|
startCircle.style.position = "absolute";
|
||||||
startCircle.style.left = startIsLeft
|
startCircle.style.left = startIsLeft
|
||||||
? "-8px"
|
? `-${this.circleRadius}px`
|
||||||
: `${width + lineWidth - 8}px`;
|
: `${width + lineWidth - this.circleRadius}px`;
|
||||||
startCircle.style.top = startIsTop
|
startCircle.style.top = startIsTop
|
||||||
? "-8px"
|
? `-${this.circleRadius}px`
|
||||||
: `${height + lineWidth - 8}px`;
|
: `${height + lineWidth - this.circleRadius}px`;
|
||||||
|
|
||||||
const endCircle = document.createElement("div");
|
endCircle.classList.add(
|
||||||
endCircle.style.width = "16px";
|
"visual-console-item-line-circle",
|
||||||
endCircle.style.height = "16px";
|
"visual-console-item-line-circle-end"
|
||||||
|
);
|
||||||
|
endCircle.style.width = `${this.circleRadius * 2}px`;
|
||||||
|
endCircle.style.height = `${this.circleRadius * 2}px`;
|
||||||
endCircle.style.borderRadius = "50%";
|
endCircle.style.borderRadius = "50%";
|
||||||
endCircle.style.backgroundColor = "white";
|
endCircle.style.backgroundColor = "black";
|
||||||
endCircle.style.position = "absolute";
|
endCircle.style.position = "absolute";
|
||||||
endCircle.style.left = startIsLeft
|
endCircle.style.left = startIsLeft
|
||||||
? `${width + lineWidth - 8}px`
|
? `${width + lineWidth - 8}px`
|
||||||
: "-8px";
|
: `-${this.circleRadius}px`;
|
||||||
endCircle.style.top = startIsTop ? `${height + lineWidth - 8}px` : "-8px";
|
endCircle.style.top = startIsTop
|
||||||
|
? `${height + lineWidth - this.circleRadius}px`
|
||||||
|
: `-${this.circleRadius}px`;
|
||||||
|
|
||||||
element.append(startCircle);
|
if (!this.isMoving) {
|
||||||
element.append(endCircle);
|
element.appendChild(startCircle);
|
||||||
|
element.appendChild(endCircle);
|
||||||
|
|
||||||
|
// Init the movement listeners.
|
||||||
|
this.initStartPositionMovementListener(startCircle, this.elementRef
|
||||||
|
.parentElement as HTMLElement);
|
||||||
|
this.initEndPositionMovementListener(endCircle, this.elementRef
|
||||||
|
.parentElement as HTMLElement);
|
||||||
|
}
|
||||||
|
} else if (!this.isMoving) {
|
||||||
|
this.stopStartPositionMovementListener();
|
||||||
|
// Remove circles.
|
||||||
|
const circles = element.getElementsByClassName(
|
||||||
|
"visual-console-item-line-circle"
|
||||||
|
);
|
||||||
|
while (circles.length > 0) {
|
||||||
|
const circle = circles.item(0);
|
||||||
|
if (circle) circle.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,12 +436,15 @@ export default class Line extends Item<LineProps> {
|
|||||||
* the start and the finish of the line.
|
* the start and the finish of the line.
|
||||||
* @param props Item properties.
|
* @param props Item properties.
|
||||||
*/
|
*/
|
||||||
public static extractBoxSizeAndPosition(props: LineProps): Size & Position {
|
public static extractBoxSizeAndPosition(
|
||||||
|
startPosition: Position,
|
||||||
|
endPosition: Position
|
||||||
|
): Size & Position {
|
||||||
return {
|
return {
|
||||||
width: Math.abs(props.startPosition.x - props.endPosition.x),
|
width: Math.abs(startPosition.x - endPosition.x),
|
||||||
height: Math.abs(props.startPosition.y - props.endPosition.y),
|
height: Math.abs(startPosition.y - endPosition.y),
|
||||||
x: Math.min(props.startPosition.x, props.endPosition.x),
|
x: Math.min(startPosition.x, endPosition.x),
|
||||||
y: Math.min(props.startPosition.y, props.endPosition.y)
|
y: Math.min(startPosition.y, endPosition.y)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +453,29 @@ export default class Line extends Item<LineProps> {
|
|||||||
* @override Item.remove
|
* @override Item.remove
|
||||||
*/
|
*/
|
||||||
public remove(): void {
|
public remove(): void {
|
||||||
// TODO: clear the item's event listeners.
|
// Clear the item's event listeners.
|
||||||
|
this.stopStartPositionMovementListener();
|
||||||
|
// Call the parent's .remove()
|
||||||
super.remove();
|
super.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To add an event handler to the movement of visual console elements.
|
||||||
|
* @param listener Function which is going to be executed when a linked console is moved.
|
||||||
|
*
|
||||||
|
* @override Item.onMoved
|
||||||
|
*/
|
||||||
|
public onLineMovementFinished(
|
||||||
|
listener: Listener<LineMovedEvent>
|
||||||
|
): Disposable {
|
||||||
|
/*
|
||||||
|
* The '.on' function returns a function which will clean the event
|
||||||
|
* listener when executed. We store all the 'dispose' functions to
|
||||||
|
* call them when the item should be cleared.
|
||||||
|
*/
|
||||||
|
const disposable = this.lineMovedEventManager.on(listener);
|
||||||
|
this.lineMovedEventDisposables.push(disposable);
|
||||||
|
|
||||||
|
return disposable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user