WIP Networklink POC
This commit is contained in:
parent
27ba6a3adf
commit
8e09a30a05
|
@ -119,6 +119,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($layoutData['type']) {
|
switch ($layoutData['type']) {
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
visual_map_print_user_line_handles($layoutData);
|
visual_map_print_user_line_handles($layoutData);
|
||||||
visual_map_print_user_lines($layoutData);
|
visual_map_print_user_lines($layoutData);
|
||||||
|
|
|
@ -271,6 +271,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
$table->data[($i + 1)]['icon'] = html_print_image(
|
$table->data[($i + 1)]['icon'] = html_print_image(
|
||||||
'images/line_item.png',
|
'images/line_item.png',
|
||||||
|
@ -303,6 +304,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
switch ($layoutData['type']) {
|
switch ($layoutData['type']) {
|
||||||
case ICON:
|
case ICON:
|
||||||
case BOX_ITEM:
|
case BOX_ITEM:
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
// hasn't the label.
|
// hasn't the label.
|
||||||
$table->data[($i + 1)][0] = '';
|
$table->data[($i + 1)][0] = '';
|
||||||
|
@ -345,6 +347,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
|
|
||||||
// Width and height
|
// Width and height
|
||||||
switch ($layoutData['type']) {
|
switch ($layoutData['type']) {
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
// hasn't the width and height.
|
// hasn't the width and height.
|
||||||
$table->data[($i + 1)][2] = '';
|
$table->data[($i + 1)][2] = '';
|
||||||
|
@ -361,6 +364,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
|
|
||||||
// Position
|
// Position
|
||||||
switch ($layoutData['type']) {
|
switch ($layoutData['type']) {
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
// hasn't the width and height.
|
// hasn't the width and height.
|
||||||
$table->data[($i + 1)][3] = '';
|
$table->data[($i + 1)][3] = '';
|
||||||
|
@ -375,6 +379,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
// Parent
|
// Parent
|
||||||
switch ($layoutData['type']) {
|
switch ($layoutData['type']) {
|
||||||
case BOX_ITEM:
|
case BOX_ITEM:
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
case COLOR_CLOUD:
|
case COLOR_CLOUD:
|
||||||
$table->data[($i + 1)][4] = '';
|
$table->data[($i + 1)][4] = '';
|
||||||
|
@ -434,6 +439,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
case BOX_ITEM:
|
case BOX_ITEM:
|
||||||
case ICON:
|
case ICON:
|
||||||
case LABEL:
|
case LABEL:
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
$table->data[($i + 2)][0] = '';
|
$table->data[($i + 2)][0] = '';
|
||||||
break;
|
break;
|
||||||
|
@ -494,6 +500,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
case ICON:
|
case ICON:
|
||||||
case LABEL:
|
case LABEL:
|
||||||
case BOX_ITEM:
|
case BOX_ITEM:
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
case GROUP_ITEM:
|
case GROUP_ITEM:
|
||||||
$table->data[($i + 2)][1] = '';
|
$table->data[($i + 2)][1] = '';
|
||||||
|
@ -598,6 +605,7 @@ foreach ($layoutDatas as $layoutData) {
|
||||||
|
|
||||||
// Map linked
|
// Map linked
|
||||||
switch ($layoutData['type']) {
|
switch ($layoutData['type']) {
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
case BOX_ITEM:
|
case BOX_ITEM:
|
||||||
case AUTO_SLA_GRAPH:
|
case AUTO_SLA_GRAPH:
|
||||||
|
|
|
@ -1449,6 +1449,16 @@ switch ($action) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
|
case 'network_link':
|
||||||
|
$values['type'] = NETWORK_LINK;
|
||||||
|
$values['border_width'] = $line_width;
|
||||||
|
$values['border_color'] = $line_color;
|
||||||
|
$values['pos_x'] = $line_start_x;
|
||||||
|
$values['pos_y'] = $line_start_y;
|
||||||
|
$values['width'] = $line_end_x;
|
||||||
|
$values['height'] = $line_end_y;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'line_item':
|
case 'line_item':
|
||||||
$values['type'] = LINE_ITEM;
|
$values['type'] = LINE_ITEM;
|
||||||
$values['border_width'] = $line_width;
|
$values['border_width'] = $line_width;
|
||||||
|
|
|
@ -3670,6 +3670,7 @@ function visual_map_print_visual_map(
|
||||||
$layout_data['label'] = visual_map_macro($layout_data['label'], $layout_data['id_agente_modulo']);
|
$layout_data['label'] = visual_map_macro($layout_data['label'], $layout_data['id_agente_modulo']);
|
||||||
|
|
||||||
switch ($layout_data['type']) {
|
switch ($layout_data['type']) {
|
||||||
|
case NETWORK_LINK:
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
visual_map_print_user_lines($layout_data, $proportion);
|
visual_map_print_user_lines($layout_data, $proportion);
|
||||||
break;
|
break;
|
||||||
|
@ -4382,6 +4383,9 @@ function visual_map_type_in_js($type)
|
||||||
case LINE_ITEM:
|
case LINE_ITEM:
|
||||||
return 'line_item';
|
return 'line_item';
|
||||||
|
|
||||||
|
case NETWORK_LINK:
|
||||||
|
return 'network_link';
|
||||||
|
|
||||||
case COLOR_CLOUD:
|
case COLOR_CLOUD:
|
||||||
return 'color_cloud';
|
return 'color_cloud';
|
||||||
|
|
||||||
|
|
|
@ -186,13 +186,17 @@ function createVisualConsole(
|
||||||
var item = e.item || {};
|
var item = e.item || {};
|
||||||
var meta = item.meta || {};
|
var meta = item.meta || {};
|
||||||
|
|
||||||
if ((meta.editMode || meta.lineMode) && !meta.isUpdating) {
|
if (meta.editMode && !meta.isUpdating) {
|
||||||
createOrUpdateVisualConsoleItem(
|
createOrUpdateVisualConsoleItem(
|
||||||
visualConsole,
|
visualConsole,
|
||||||
asyncTaskManager,
|
asyncTaskManager,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
item
|
item
|
||||||
);
|
);
|
||||||
|
} else if (meta.lineMode && item.props.type == 21) {
|
||||||
|
confirmDialog({
|
||||||
|
title: "todo"
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// VC Item moved.
|
// VC Item moved.
|
||||||
|
@ -203,7 +207,7 @@ function createVisualConsole(
|
||||||
y: e.newPosition.y,
|
y: e.newPosition.y,
|
||||||
type: e.item.props.type
|
type: e.item.props.type
|
||||||
};
|
};
|
||||||
if (e.item.props.type === 13) {
|
if (e.item.props.type === 13 || e.item.props.type === 21) {
|
||||||
var startIsLeft =
|
var startIsLeft =
|
||||||
e.item.props.startPosition.x - e.item.props.endPosition.x <= 0;
|
e.item.props.startPosition.x - e.item.props.endPosition.x <= 0;
|
||||||
var startIsTop =
|
var startIsTop =
|
||||||
|
@ -427,6 +431,7 @@ function createVisualConsole(
|
||||||
},
|
},
|
||||||
createItem: function(typeString) {
|
createItem: function(typeString) {
|
||||||
var type;
|
var type;
|
||||||
|
console.log(typeString);
|
||||||
switch (typeString) {
|
switch (typeString) {
|
||||||
case "STATIC_GRAPH":
|
case "STATIC_GRAPH":
|
||||||
type = 0;
|
type = 0;
|
||||||
|
@ -479,6 +484,9 @@ function createVisualConsole(
|
||||||
case "COLOR_CLOUD":
|
case "COLOR_CLOUD":
|
||||||
type = 20;
|
type = 20;
|
||||||
break;
|
break;
|
||||||
|
case "NETWORK_LINK":
|
||||||
|
type = 21;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
type = 0;
|
type = 0;
|
||||||
}
|
}
|
||||||
|
@ -565,7 +573,7 @@ function createVisualConsole(
|
||||||
item.setMeta({ isUpdating: false });
|
item.setMeta({ isUpdating: false });
|
||||||
|
|
||||||
var itemRetrieved = item.props;
|
var itemRetrieved = item.props;
|
||||||
if (itemRetrieved["type"] == 13) {
|
if (itemRetrieved["type"] == 13 || itemRetrieved["type"] == 21) {
|
||||||
var startIsLeft =
|
var startIsLeft =
|
||||||
itemRetrieved["startPosition"]["x"] -
|
itemRetrieved["startPosition"]["x"] -
|
||||||
itemRetrieved["endPosition"]["x"] <=
|
itemRetrieved["endPosition"]["x"] <=
|
||||||
|
@ -1179,6 +1187,9 @@ function createOrUpdateVisualConsoleItem(
|
||||||
case 20:
|
case 20:
|
||||||
nameType = "Color Cloud";
|
nameType = "Color Cloud";
|
||||||
break;
|
break;
|
||||||
|
case 21:
|
||||||
|
nameType = "Network Link";
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
nameType = "Static graph";
|
nameType = "Static graph";
|
||||||
|
@ -1259,7 +1270,8 @@ function createOrUpdateVisualConsoleItem(
|
||||||
tinyMCE != undefined &&
|
tinyMCE != undefined &&
|
||||||
tinyMCE.editors.length > 0 &&
|
tinyMCE.editors.length > 0 &&
|
||||||
item.itemProps.type != 12 &&
|
item.itemProps.type != 12 &&
|
||||||
item.itemProps.type != 13
|
item.itemProps.type != 13 &&
|
||||||
|
item.itemProps.type != 21
|
||||||
) {
|
) {
|
||||||
// Content tiny.
|
// Content tiny.
|
||||||
var label = tinyMCE.activeEditor.getContent();
|
var label = tinyMCE.activeEditor.getContent();
|
||||||
|
|
|
@ -109,7 +109,7 @@ if ($getVisualConsole === true) {
|
||||||
$ratio
|
$ratio
|
||||||
);
|
);
|
||||||
|
|
||||||
echo '['.implode($vcItems, ',').']';
|
echo '['.implode(',', $vcItems).']';
|
||||||
return;
|
return;
|
||||||
} else if ($getVisualConsoleItem === true
|
} else if ($getVisualConsoleItem === true
|
||||||
|| $updateVisualConsoleItem === true
|
|| $updateVisualConsoleItem === true
|
||||||
|
@ -245,7 +245,9 @@ if ($getVisualConsole === true) {
|
||||||
$item = VisualConsole::getItemFromDB($itemId);
|
$item = VisualConsole::getItemFromDB($itemId);
|
||||||
$data = $item->toArray();
|
$data = $item->toArray();
|
||||||
$data['id_layout'] = $visualConsoleId;
|
$data['id_layout'] = $visualConsoleId;
|
||||||
if ($data['type'] === LINE_ITEM) {
|
if ($data['type'] === LINE_ITEM
|
||||||
|
|| $data['type'] === NETWORK_LINK
|
||||||
|
) {
|
||||||
$data['endX'] = ($data['endX'] + 20);
|
$data['endX'] = ($data['endX'] + 20);
|
||||||
$data['endY'] = ($data['endY'] + 20);
|
$data['endY'] = ($data['endY'] + 20);
|
||||||
$data['startX'] = ($data['startX'] + 20);
|
$data['startX'] = ($data['startX'] + 20);
|
||||||
|
|
|
@ -186,6 +186,7 @@ final class NetworkLink extends Model
|
||||||
* Obtain a vc item data structure from the database using a filter.
|
* Obtain a vc item data structure from the database using a filter.
|
||||||
*
|
*
|
||||||
* @param array $filter Filter of the Visual Console Item.
|
* @param array $filter Filter of the Visual Console Item.
|
||||||
|
* @param float $ratio Adjustment ratio factor.
|
||||||
*
|
*
|
||||||
* @return array The Visual Console line data structure stored into the DB.
|
* @return array The Visual Console line data structure stored into the DB.
|
||||||
* @throws \Exception When the data cannot be retrieved from the DB.
|
* @throws \Exception When the data cannot be retrieved from the DB.
|
||||||
|
|
|
@ -81,7 +81,9 @@ class View extends \HTML
|
||||||
$activetabs = 2;
|
$activetabs = 2;
|
||||||
if ($type === LABEL) {
|
if ($type === LABEL) {
|
||||||
$activetabs = 0;
|
$activetabs = 0;
|
||||||
} else if ($type === LINE_ITEM) {
|
} else if ($type === LINE_ITEM
|
||||||
|
|| $type === NETWORK_LINK
|
||||||
|
) {
|
||||||
$activetabs = 0;
|
$activetabs = 0;
|
||||||
$tabs = [
|
$tabs = [
|
||||||
[
|
[
|
||||||
|
@ -306,7 +308,7 @@ class View extends \HTML
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Only Create, settings default values if not enter tab general.
|
// Only Create, settings default values if not enter tab general.
|
||||||
if ($itemId === 0 && $type != LINE_ITEM) {
|
if ($itemId === 0 && $type != LINE_ITEM && $type != NETWORK_LINK) {
|
||||||
$class = VisualConsole::getItemClass((int) $type);
|
$class = VisualConsole::getItemClass((int) $type);
|
||||||
$data = $class::getDefaultGeneralValues($data);
|
$data = $class::getDefaultGeneralValues($data);
|
||||||
}
|
}
|
||||||
|
@ -491,6 +493,17 @@ class View extends \HTML
|
||||||
$data['isLinkEnabled'] = true;
|
$data['isLinkEnabled'] = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NETWORK_LINK:
|
||||||
|
$data['borderColor'] = \get_parameter('borderColor');
|
||||||
|
$data['borderWidth'] = \get_parameter('borderWidth');
|
||||||
|
$data['isOnTop'] = \get_parameter_switch('isOnTop');
|
||||||
|
// Insert line default position ball end.
|
||||||
|
if ($itemId === 0) {
|
||||||
|
$data['height'] = 100;
|
||||||
|
$data['width'] = 100;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Not posible.
|
// Not posible.
|
||||||
break;
|
break;
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -843,6 +843,7 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
||||||
this.elementRef.classList.remove("is-editing");
|
this.elementRef.classList.remove("is-editing");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prevMeta || prevMeta.isFetching !== this.meta.isFetching) {
|
if (!prevMeta || prevMeta.isFetching !== this.meta.isFetching) {
|
||||||
if (this.meta.isFetching) {
|
if (this.meta.isFetching) {
|
||||||
this.elementRef.classList.add("is-fetching");
|
this.elementRef.classList.add("is-fetching");
|
||||||
|
@ -1003,8 +1004,13 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
||||||
*/
|
*/
|
||||||
protected resizeElement(width: number, height: number): void {
|
protected resizeElement(width: number, height: number): void {
|
||||||
// The most valuable size is the content size.
|
// The most valuable size is the content size.
|
||||||
this.childElementRef.style.width = width > 0 ? `${width}px` : null;
|
if (
|
||||||
this.childElementRef.style.height = height > 0 ? `${height}px` : null;
|
this.props.type != ItemType.LINE_ITEM &&
|
||||||
|
this.props.type != ItemType.NETWORK_LINK
|
||||||
|
) {
|
||||||
|
this.childElementRef.style.width = width > 0 ? `${width}px` : "0";
|
||||||
|
this.childElementRef.style.height = height > 0 ? `${height}px` : "0";
|
||||||
|
}
|
||||||
|
|
||||||
if (this.props.label && this.props.label.length > 0) {
|
if (this.props.label && this.props.label.length > 0) {
|
||||||
// Ugly table to show the label as its legacy counterpart.
|
// Ugly table to show the label as its legacy counterpart.
|
||||||
|
@ -1015,11 +1021,11 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
||||||
switch (this.props.labelPosition) {
|
switch (this.props.labelPosition) {
|
||||||
case "up":
|
case "up":
|
||||||
case "down":
|
case "down":
|
||||||
table.style.width = width > 0 ? `${width}px` : null;
|
table.style.width = width > 0 ? `${width}px` : "0";
|
||||||
break;
|
break;
|
||||||
case "left":
|
case "left":
|
||||||
case "right":
|
case "right":
|
||||||
table.style.height = height > 0 ? `${height}px` : null;
|
table.style.height = height > 0 ? `${height}px` : "0";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1182,7 +1188,7 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.initMovementListener(this.elementRef);
|
this.initMovementListener(this.elementRef);
|
||||||
if (this.props.type !== 13) {
|
if (this.props.type !== ItemType.LINE_ITEM) {
|
||||||
this.initResizementListener(this.elementRef);
|
this.initResizementListener(this.elementRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1198,7 +1204,7 @@ abstract class VisualConsoleItem<Props extends ItemProps> {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.stopMovementListener();
|
this.stopMovementListener();
|
||||||
if (this.props.type !== 13) {
|
if (this.props.type !== ItemType.LINE_ITEM) {
|
||||||
this.stopResizementListener();
|
this.stopResizementListener();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ import {
|
||||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
||||||
import TypedEvent, { Listener, Disposable } from "../lib/TypedEvent";
|
import TypedEvent, { Listener, Disposable } from "../lib/TypedEvent";
|
||||||
|
|
||||||
interface LineProps extends ItemProps {
|
export interface LineProps extends ItemProps {
|
||||||
// Overrided properties.
|
// Overrided properties.
|
||||||
readonly type: ItemType.LINE_ITEM;
|
type: number;
|
||||||
label: null;
|
label: null;
|
||||||
isLinkEnabled: false;
|
isLinkEnabled: false;
|
||||||
parentId: null;
|
parentId: null;
|
||||||
|
@ -20,6 +20,8 @@ interface LineProps extends ItemProps {
|
||||||
endPosition: Position;
|
endPosition: Position;
|
||||||
lineWidth: number;
|
lineWidth: number;
|
||||||
color: string | null;
|
color: string | null;
|
||||||
|
viewportOffsetX: number;
|
||||||
|
viewportOffsetY: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +56,9 @@ export function linePropsDecoder(data: AnyObject): LineProps | never {
|
||||||
y: parseIntOr(data.endY, 0)
|
y: parseIntOr(data.endY, 0)
|
||||||
},
|
},
|
||||||
lineWidth: parseIntOr(data.lineWidth || data.borderWidth, 1),
|
lineWidth: parseIntOr(data.lineWidth || data.borderWidth, 1),
|
||||||
color: notEmptyStringOr(data.borderColor || data.color, null)
|
color: notEmptyStringOr(data.borderColor || data.color, null),
|
||||||
|
viewportOffsetX: 0,
|
||||||
|
viewportOffsetY: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -82,20 +86,20 @@ export interface LineMovedEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Line extends Item<LineProps> {
|
export default class Line extends Item<LineProps> {
|
||||||
private circleRadius = 8;
|
protected circleRadius = 8;
|
||||||
// To control if the line movement is enabled.
|
// To control if the line movement is enabled.
|
||||||
private moveMode: boolean = false;
|
protected moveMode: boolean = false;
|
||||||
// To control if the line is moving.
|
// To control if the line is moving.
|
||||||
private isMoving: boolean = false;
|
protected isMoving: boolean = false;
|
||||||
|
|
||||||
// Event manager for moved events.
|
// Event manager for moved events.
|
||||||
private readonly lineMovedEventManager = new TypedEvent<LineMovedEvent>();
|
protected readonly lineMovedEventManager = new TypedEvent<LineMovedEvent>();
|
||||||
// List of references to clean the event listeners.
|
// List of references to clean the event listeners.
|
||||||
private readonly lineMovedEventDisposables: Disposable[] = [];
|
protected readonly lineMovedEventDisposables: Disposable[] = [];
|
||||||
|
|
||||||
// This function will only run the 2nd arg function after the time
|
// This function will only run the 2nd arg function after the time
|
||||||
// of the first arg have passed after its last execution.
|
// of the first arg have passed after its last execution.
|
||||||
private debouncedStartPositionMovementSave = debounce(
|
protected debouncedStartPositionMovementSave = debounce(
|
||||||
500, // ms.
|
500, // ms.
|
||||||
(x: Position["x"], y: Position["y"]) => {
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
this.isMoving = false;
|
this.isMoving = false;
|
||||||
|
@ -110,13 +114,13 @@ export default class Line extends Item<LineProps> {
|
||||||
);
|
);
|
||||||
// This property will store the function
|
// This property will store the function
|
||||||
// to clean the movement listener.
|
// to clean the movement listener.
|
||||||
private removeStartPositionMovement: Function | null = null;
|
protected removeStartPositionMovement: Function | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the movement funtionality for the start position.
|
* Start the movement funtionality for the start position.
|
||||||
* @param element Element to move inside its container.
|
* @param element Element to move inside its container.
|
||||||
*/
|
*/
|
||||||
private initStartPositionMovementListener(
|
protected initStartPositionMovementListener(
|
||||||
element: HTMLElement,
|
element: HTMLElement,
|
||||||
container: HTMLElement
|
container: HTMLElement
|
||||||
): void {
|
): void {
|
||||||
|
@ -124,8 +128,8 @@ export default class Line extends Item<LineProps> {
|
||||||
element,
|
element,
|
||||||
(x: Position["x"], y: Position["y"]) => {
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
// Calculate the center of the circle.
|
// Calculate the center of the circle.
|
||||||
x += this.circleRadius;
|
x += this.circleRadius - this.props.viewportOffsetX / 2;
|
||||||
y += this.circleRadius;
|
y += this.circleRadius - this.props.viewportOffsetY / 2;
|
||||||
|
|
||||||
const startPosition = { x, y };
|
const startPosition = { x, y };
|
||||||
|
|
||||||
|
@ -153,7 +157,7 @@ export default class Line extends Item<LineProps> {
|
||||||
|
|
||||||
// This function will only run the 2nd arg function after the time
|
// This function will only run the 2nd arg function after the time
|
||||||
// of the first arg have passed after its last execution.
|
// of the first arg have passed after its last execution.
|
||||||
private debouncedEndPositionMovementSave = debounce(
|
protected debouncedEndPositionMovementSave = debounce(
|
||||||
500, // ms.
|
500, // ms.
|
||||||
(x: Position["x"], y: Position["y"]) => {
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
this.isMoving = false;
|
this.isMoving = false;
|
||||||
|
@ -168,13 +172,13 @@ export default class Line extends Item<LineProps> {
|
||||||
);
|
);
|
||||||
// This property will store the function
|
// This property will store the function
|
||||||
// to clean the movement listener.
|
// to clean the movement listener.
|
||||||
private removeEndPositionMovement: Function | null = null;
|
protected removeEndPositionMovement: Function | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End the movement funtionality for the end position.
|
* End the movement funtionality for the end position.
|
||||||
* @param element Element to move inside its container.
|
* @param element Element to move inside its container.
|
||||||
*/
|
*/
|
||||||
private initEndPositionMovementListener(
|
protected initEndPositionMovementListener(
|
||||||
element: HTMLElement,
|
element: HTMLElement,
|
||||||
container: HTMLElement
|
container: HTMLElement
|
||||||
): void {
|
): void {
|
||||||
|
@ -182,8 +186,8 @@ export default class Line extends Item<LineProps> {
|
||||||
element,
|
element,
|
||||||
(x: Position["x"], y: Position["y"]) => {
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
// Calculate the center of the circle.
|
// Calculate the center of the circle.
|
||||||
x += this.circleRadius;
|
x += this.circleRadius - this.props.viewportOffsetX / 2;
|
||||||
y += this.circleRadius;
|
y += this.circleRadius - this.props.viewportOffsetY / 2;
|
||||||
|
|
||||||
this.isMoving = true;
|
this.isMoving = true;
|
||||||
this.props = {
|
this.props = {
|
||||||
|
@ -231,6 +235,11 @@ export default class Line extends Item<LineProps> {
|
||||||
|
|
||||||
this.moveMode = meta.editMode;
|
this.moveMode = meta.editMode;
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
|
super.resizeElement(
|
||||||
|
Math.max(props.width, props.viewportOffsetX),
|
||||||
|
Math.max(props.height, props.viewportOffsetY)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -272,27 +281,33 @@ export default class Line extends Item<LineProps> {
|
||||||
const element: HTMLDivElement = document.createElement("div");
|
const element: HTMLDivElement = document.createElement("div");
|
||||||
element.className = "line";
|
element.className = "line";
|
||||||
|
|
||||||
const {
|
let {
|
||||||
x, // Box x
|
x, // Box x
|
||||||
y, // Box y
|
y, // Box y
|
||||||
width, // Box width
|
width, // Box width
|
||||||
height, // Box height
|
height, // Box height
|
||||||
lineWidth, // Line thickness
|
lineWidth, // Line thickness,
|
||||||
|
viewportOffsetX, // viewport width,
|
||||||
|
viewportOffsetY, // viewport heigth,
|
||||||
startPosition, // Line start position
|
startPosition, // Line start position
|
||||||
endPosition, // Line end position
|
endPosition, // Line end position
|
||||||
color // Line color
|
color // Line color
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const x1 = startPosition.x - x + lineWidth / 2;
|
width = width + viewportOffsetX;
|
||||||
const y1 = startPosition.y - y + lineWidth / 2;
|
height = height + viewportOffsetY;
|
||||||
const x2 = endPosition.x - x + lineWidth / 2;
|
|
||||||
const y2 = endPosition.y - y + lineWidth / 2;
|
const x1 = startPosition.x - x + lineWidth / 2 + viewportOffsetX / 2;
|
||||||
|
const y1 = startPosition.y - y + lineWidth / 2 + viewportOffsetY / 2;
|
||||||
|
const x2 = endPosition.x - x + lineWidth / 2 + viewportOffsetX / 2;
|
||||||
|
const y2 = endPosition.y - y + lineWidth / 2 + viewportOffsetY / 2;
|
||||||
|
|
||||||
// SVG container.
|
// SVG container.
|
||||||
const svg = document.createElementNS(svgNS, "svg");
|
const svg = document.createElementNS(svgNS, "svg");
|
||||||
// Set SVG size.
|
// Set SVG size.
|
||||||
svg.setAttribute("width", `${width + lineWidth}`);
|
svg.setAttribute("width", `${width + lineWidth}`);
|
||||||
svg.setAttribute("height", `${height + lineWidth}`);
|
svg.setAttribute("height", `${height + lineWidth}`);
|
||||||
|
|
||||||
const line = document.createElementNS(svgNS, "line");
|
const line = document.createElementNS(svgNS, "line");
|
||||||
line.setAttribute("x1", `${x1}`);
|
line.setAttribute("x1", `${x1}`);
|
||||||
line.setAttribute("y1", `${y1}`);
|
line.setAttribute("y1", `${y1}`);
|
||||||
|
@ -308,21 +323,26 @@ export default class Line extends Item<LineProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updateDomElement(element: HTMLElement): void {
|
protected updateDomElement(element: HTMLElement): void {
|
||||||
const {
|
let {
|
||||||
x, // Box x
|
x, // Box x
|
||||||
y, // Box y
|
y, // Box y
|
||||||
width, // Box width
|
width, // Box width
|
||||||
height, // Box height
|
height, // Box height
|
||||||
lineWidth, // Line thickness
|
lineWidth, // Line thickness
|
||||||
|
viewportOffsetX, // viewport width,
|
||||||
|
viewportOffsetY, // viewport heigth,
|
||||||
startPosition, // Line start position
|
startPosition, // Line start position
|
||||||
endPosition, // Line end position
|
endPosition, // Line end position
|
||||||
color // Line color
|
color // Line color
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const x1 = startPosition.x - x + lineWidth / 2;
|
width = width + viewportOffsetX;
|
||||||
const y1 = startPosition.y - y + lineWidth / 2;
|
height = height + viewportOffsetY;
|
||||||
const x2 = endPosition.x - x + lineWidth / 2;
|
|
||||||
const y2 = endPosition.y - y + lineWidth / 2;
|
const x1 = startPosition.x - x + lineWidth / 2 + viewportOffsetX / 2;
|
||||||
|
const y1 = startPosition.y - y + lineWidth / 2 + viewportOffsetY / 2;
|
||||||
|
const x2 = endPosition.x - x + lineWidth / 2 + viewportOffsetX / 2;
|
||||||
|
const y2 = endPosition.y - y + lineWidth / 2 + viewportOffsetY / 2;
|
||||||
|
|
||||||
const svgs = element.getElementsByTagName("svg");
|
const svgs = element.getElementsByTagName("svg");
|
||||||
|
|
||||||
|
@ -352,9 +372,6 @@ export default class Line extends Item<LineProps> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.moveMode) {
|
if (this.moveMode) {
|
||||||
const startIsLeft = startPosition.x - endPosition.x <= 0;
|
|
||||||
const startIsTop = startPosition.y - endPosition.y <= 0;
|
|
||||||
|
|
||||||
let startCircle: HTMLElement = document.createElement("div");
|
let startCircle: HTMLElement = document.createElement("div");
|
||||||
let endCircle: HTMLElement = document.createElement("div");
|
let endCircle: HTMLElement = document.createElement("div");
|
||||||
|
|
||||||
|
@ -384,12 +401,8 @@ export default class Line extends Item<LineProps> {
|
||||||
startCircle.style.borderRadius = "50%";
|
startCircle.style.borderRadius = "50%";
|
||||||
startCircle.style.backgroundColor = `${color}`;
|
startCircle.style.backgroundColor = `${color}`;
|
||||||
startCircle.style.position = "absolute";
|
startCircle.style.position = "absolute";
|
||||||
startCircle.style.left = startIsLeft
|
startCircle.style.left = `${x1 - this.circleRadius}px`;
|
||||||
? `-${this.circleRadius}px`
|
startCircle.style.top = `${y1 - this.circleRadius}px`;
|
||||||
: `${width + lineWidth - this.circleRadius}px`;
|
|
||||||
startCircle.style.top = startIsTop
|
|
||||||
? `-${this.circleRadius}px`
|
|
||||||
: `${height + lineWidth - this.circleRadius}px`;
|
|
||||||
|
|
||||||
endCircle.classList.add(
|
endCircle.classList.add(
|
||||||
"visual-console-item-line-circle",
|
"visual-console-item-line-circle",
|
||||||
|
@ -400,12 +413,8 @@ export default class Line extends Item<LineProps> {
|
||||||
endCircle.style.borderRadius = "50%";
|
endCircle.style.borderRadius = "50%";
|
||||||
endCircle.style.backgroundColor = `${color}`;
|
endCircle.style.backgroundColor = `${color}`;
|
||||||
endCircle.style.position = "absolute";
|
endCircle.style.position = "absolute";
|
||||||
endCircle.style.left = startIsLeft
|
endCircle.style.left = `${x2 - this.circleRadius}px`;
|
||||||
? `${width + lineWidth - 8}px`
|
endCircle.style.top = `${y2 - this.circleRadius}px`;
|
||||||
: `-${this.circleRadius}px`;
|
|
||||||
endCircle.style.top = startIsTop
|
|
||||||
? `${height + lineWidth - this.circleRadius}px`
|
|
||||||
: `-${this.circleRadius}px`;
|
|
||||||
|
|
||||||
if (element.parentElement !== null) {
|
if (element.parentElement !== null) {
|
||||||
const circles = element.parentElement.getElementsByClassName(
|
const circles = element.parentElement.getElementsByClassName(
|
||||||
|
|
|
@ -1,25 +1,13 @@
|
||||||
import { AnyObject, Position, Size, ItemMeta } from "../lib/types";
|
import { AnyObject, Position, ItemMeta } from "../lib/types";
|
||||||
import {
|
import { debounce, addMovementListener } from "../lib";
|
||||||
parseIntOr,
|
import { ItemType } from "../Item";
|
||||||
notEmptyStringOr,
|
import Line, { LineProps, linePropsDecoder } from "./Line";
|
||||||
debounce,
|
|
||||||
addMovementListener
|
|
||||||
} from "../lib";
|
|
||||||
import Item, { ItemType, ItemProps, itemBasePropsDecoder } from "../Item";
|
|
||||||
import TypedEvent, { Listener, Disposable } from "../lib/TypedEvent";
|
|
||||||
|
|
||||||
interface NetworkLinkProps extends ItemProps {
|
const svgNS = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
|
export interface NetworkLinkProps extends LineProps {
|
||||||
// Overrided properties.
|
// Overrided properties.
|
||||||
readonly type: ItemType.NETWORK_LINK;
|
type: number;
|
||||||
label: null;
|
|
||||||
isLinkEnabled: false;
|
|
||||||
parentId: null;
|
|
||||||
aclGroupId: null;
|
|
||||||
// Custom properties.
|
|
||||||
startPosition: Position;
|
|
||||||
endPosition: Position;
|
|
||||||
lineWidth: number;
|
|
||||||
color: string | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,186 +22,17 @@ interface NetworkLinkProps extends ItemProps {
|
||||||
export function networkLinkPropsDecoder(
|
export function networkLinkPropsDecoder(
|
||||||
data: AnyObject
|
data: AnyObject
|
||||||
): NetworkLinkProps | never {
|
): NetworkLinkProps | never {
|
||||||
const props: NetworkLinkProps = {
|
|
||||||
...itemBasePropsDecoder({ ...data, width: 1, height: 1 }), // Object spread. It will merge the properties of the two objects.
|
|
||||||
type: ItemType.NETWORK_LINK,
|
|
||||||
label: null,
|
|
||||||
isLinkEnabled: false,
|
|
||||||
parentId: null,
|
|
||||||
aclGroupId: null,
|
|
||||||
// Initialize Position & Size.
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
// Custom properties.
|
|
||||||
startPosition: {
|
|
||||||
x: parseIntOr(data.startX, 0),
|
|
||||||
y: parseIntOr(data.startY, 0)
|
|
||||||
},
|
|
||||||
endPosition: {
|
|
||||||
x: parseIntOr(data.endX, 0),
|
|
||||||
y: parseIntOr(data.endY, 0)
|
|
||||||
},
|
|
||||||
lineWidth: parseIntOr(data.lineWidth || data.borderWidth, 1),
|
|
||||||
color: notEmptyStringOr(data.borderColor || data.color, null)
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to enhance the props with the extracted size and position
|
|
||||||
* of the box cause there are missing at the props update. A better
|
|
||||||
* solution would be overriding the props setter to do it there, but
|
|
||||||
* the language doesn't allow it while targetting ES5.
|
|
||||||
* TODO: We need to figure out a more consistent solution.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...props,
|
...linePropsDecoder(data), // Object spread. It will merge the properties of the two objects.
|
||||||
// Enhance the props extracting the box size and position.
|
type: ItemType.NETWORK_LINK,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
viewportOffsetX: 300,
|
||||||
...NetworkLink.extractBoxSizeAndPosition(
|
viewportOffsetY: 300
|
||||||
props.startPosition,
|
|
||||||
props.endPosition
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const svgNS = "http://www.w3.org/2000/svg";
|
export default class NetworkLink extends Line {
|
||||||
|
private labelStart: string;
|
||||||
export interface NetworkLinkMovedEvent {
|
private labelEnd: string;
|
||||||
item: NetworkLink;
|
|
||||||
startPosition: NetworkLinkProps["startPosition"];
|
|
||||||
endPosition: NetworkLinkProps["endPosition"];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class NetworkLink extends Item<NetworkLinkProps> {
|
|
||||||
private circleRadius = 8;
|
|
||||||
// To control if the line movement is enabled.
|
|
||||||
private moveMode: boolean = false;
|
|
||||||
// To control if the line is moving.
|
|
||||||
private isMoving: boolean = false;
|
|
||||||
|
|
||||||
// Event manager for moved events.
|
|
||||||
private readonly lineMovedEventManager = new TypedEvent<
|
|
||||||
NetworkLinkMovedEvent
|
|
||||||
>();
|
|
||||||
// List of references to clean the event listeners.
|
|
||||||
private readonly lineMovedEventDisposables: Disposable[] = [];
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the movement funtionality for the start position.
|
|
||||||
* @param element Element to move inside its container.
|
|
||||||
*/
|
|
||||||
private initStartPositionMovementListener(
|
|
||||||
element: HTMLElement,
|
|
||||||
container: HTMLElement
|
|
||||||
): void {
|
|
||||||
this.removeStartPositionMovement = addMovementListener(
|
|
||||||
element,
|
|
||||||
(x: Position["x"], y: Position["y"]) => {
|
|
||||||
// Calculate the center of the circle.
|
|
||||||
x += this.circleRadius;
|
|
||||||
y += this.circleRadius;
|
|
||||||
|
|
||||||
const startPosition = { x, y };
|
|
||||||
|
|
||||||
this.isMoving = true;
|
|
||||||
this.props = {
|
|
||||||
...this.props,
|
|
||||||
startPosition
|
|
||||||
};
|
|
||||||
|
|
||||||
// Run the end function.
|
|
||||||
this.debouncedStartPositionMovementSave(x, y);
|
|
||||||
},
|
|
||||||
container
|
|
||||||
);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Stop the movement fun
|
|
||||||
*/
|
|
||||||
private stopStartPositionMovementListener(): void {
|
|
||||||
if (this.removeStartPositionMovement) {
|
|
||||||
this.removeStartPositionMovement();
|
|
||||||
this.removeStartPositionMovement = 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
|
||||||
*/
|
*/
|
||||||
|
@ -224,112 +43,130 @@ export default class NetworkLink extends Item<NetworkLinkProps> {
|
||||||
*/
|
*/
|
||||||
super(
|
super(
|
||||||
{
|
{
|
||||||
...props,
|
...props
|
||||||
...NetworkLink.extractBoxSizeAndPosition(
|
|
||||||
props.startPosition,
|
|
||||||
props.endPosition
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...meta
|
...meta
|
||||||
},
|
}
|
||||||
true
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.moveMode = meta.editMode;
|
const x1 = props.startPosition.x - props.x + props.lineWidth / 2;
|
||||||
this.init();
|
const y1 = props.startPosition.y - props.y + props.lineWidth / 2;
|
||||||
}
|
const x2 = props.endPosition.x - props.x + props.lineWidth / 2;
|
||||||
|
const y2 = props.endPosition.y - props.y + props.lineWidth / 2;
|
||||||
|
|
||||||
/**
|
this.labelStart = `start (${x1},${y1})`;
|
||||||
* Classic and protected version of the setter of the `props` property.
|
this.labelEnd = `end (${x2},${y2})`;
|
||||||
* Useful to override it from children classes.
|
|
||||||
* @param newProps
|
|
||||||
* @override Item.setProps
|
|
||||||
*/
|
|
||||||
public setProps(newProps: NetworkLinkProps) {
|
|
||||||
super.setProps({
|
|
||||||
...newProps,
|
|
||||||
...NetworkLink.extractBoxSizeAndPosition(
|
|
||||||
newProps.startPosition,
|
|
||||||
newProps.endPosition
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
this.render();
|
||||||
* Classic and protected version of the setter of the `meta` property.
|
|
||||||
* Useful to override it from children classes.
|
|
||||||
* @param newMetadata
|
|
||||||
* @override Item.setMeta
|
|
||||||
*/
|
|
||||||
public setMeta(newMetadata: ItemMeta) {
|
|
||||||
this.moveMode = newMetadata.editMode;
|
|
||||||
super.setMeta({
|
|
||||||
...newMetadata,
|
|
||||||
lineMode: true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
* To create the item's DOM representation.
|
|
||||||
* @return Item.
|
|
||||||
*/
|
*/
|
||||||
protected createDomElement(): HTMLElement {
|
protected debouncedStartPositionMovementSave = debounce(
|
||||||
const element: HTMLDivElement = document.createElement("div");
|
500, // ms.
|
||||||
element.className = "line";
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
|
this.isMoving = false;
|
||||||
|
const startPosition = { x, y };
|
||||||
|
|
||||||
const {
|
this.labelStart = "start (" + x + "," + y + ")";
|
||||||
x, // Box x
|
|
||||||
y, // Box y
|
|
||||||
width, // Box width
|
|
||||||
height, // Box height
|
|
||||||
lineWidth, // NetworkLink thickness
|
|
||||||
startPosition, // NetworkLink start position
|
|
||||||
endPosition, // NetworkLink end position
|
|
||||||
color // NetworkLink color
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const x1 = startPosition.x - x + lineWidth / 2;
|
// Emit the movement event.
|
||||||
const y1 = startPosition.y - y + lineWidth / 2;
|
this.lineMovedEventManager.emit({
|
||||||
const x2 = endPosition.x - x + lineWidth / 2;
|
item: this,
|
||||||
const y2 = endPosition.y - y + lineWidth / 2;
|
startPosition,
|
||||||
|
endPosition: this.props.endPosition
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// SVG container.
|
protected debouncedEndPositionMovementSave = debounce(
|
||||||
const svg = document.createElementNS(svgNS, "svg");
|
500, // ms.
|
||||||
// Set SVG size.
|
(x: Position["x"], y: Position["y"]) => {
|
||||||
svg.setAttribute("width", `${width + lineWidth}`);
|
this.isMoving = false;
|
||||||
svg.setAttribute("height", `${height + lineWidth}`);
|
const endPosition = { x, y };
|
||||||
const line = document.createElementNS(svgNS, "line");
|
|
||||||
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}`);
|
|
||||||
|
|
||||||
svg.append(line);
|
this.labelEnd = "end (" + x + "," + y + ")";
|
||||||
element.append(svg);
|
|
||||||
|
|
||||||
return element;
|
// Emit the movement event.
|
||||||
}
|
this.lineMovedEventManager.emit({
|
||||||
|
item: this,
|
||||||
|
endPosition,
|
||||||
|
startPosition: this.props.startPosition
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
protected updateDomElement(element: HTMLElement): void {
|
protected updateDomElement(element: HTMLElement): void {
|
||||||
const {
|
super.updateDomElement(element);
|
||||||
|
let {
|
||||||
x, // Box x
|
x, // Box x
|
||||||
y, // Box y
|
y, // Box y
|
||||||
width, // Box width
|
lineWidth, // Line thickness
|
||||||
height, // Box height
|
viewportOffsetX, // viewport width,
|
||||||
lineWidth, // NetworkLink thickness
|
viewportOffsetY, // viewport heigth,
|
||||||
startPosition, // NetworkLink start position
|
startPosition, // Line start position
|
||||||
endPosition, // NetworkLink end position
|
endPosition, // Line end position
|
||||||
color // NetworkLink color
|
color // Line color
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const x1 = startPosition.x - x + lineWidth / 2;
|
// Font size and text adjustments.
|
||||||
const y1 = startPosition.y - y + lineWidth / 2;
|
const fontsize = 7.4;
|
||||||
const x2 = endPosition.x - x + lineWidth / 2;
|
const adjustment = 50;
|
||||||
const y2 = endPosition.y - y + lineWidth / 2;
|
|
||||||
|
// console.log(`startPosition [${startPosition.x},${startPosition.y}]`);
|
||||||
|
// console.log(`x.y [${x},${y}]`);
|
||||||
|
|
||||||
|
let x1 = startPosition.x - x + lineWidth / 2 + viewportOffsetX / 2;
|
||||||
|
let y1 = startPosition.y - y + lineWidth / 2 + viewportOffsetY / 2;
|
||||||
|
let x2 = endPosition.x - x + lineWidth / 2 + viewportOffsetX / 2;
|
||||||
|
let y2 = endPosition.y - y + lineWidth / 2 + viewportOffsetY / 2;
|
||||||
|
|
||||||
|
// Calculate angle (rotation).
|
||||||
|
let g = (Math.atan((y2 - y1) / (x2 - x1)) * 180) / Math.PI;
|
||||||
|
|
||||||
|
if (Math.abs(g) > 0) {
|
||||||
|
g = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate effective 'text' box sizes.
|
||||||
|
const fontheight = 23;
|
||||||
|
let labelStartWidth = this.labelStart.length * fontsize;
|
||||||
|
let labelEndWidth = this.labelEnd.length * fontsize;
|
||||||
|
let labelStartHeight = fontheight;
|
||||||
|
let labelEndHeight = fontheight;
|
||||||
|
|
||||||
|
if (x1 < x2) {
|
||||||
|
// x1 on left of x2.
|
||||||
|
x1 += adjustment;
|
||||||
|
x2 -= adjustment + labelEndWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x1 > x2) {
|
||||||
|
// x1 on right of x2.
|
||||||
|
x1 -= adjustment + labelStartWidth;
|
||||||
|
x2 += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y1 < y2) {
|
||||||
|
// y1 on y2.
|
||||||
|
y1 += adjustment;
|
||||||
|
y2 -= adjustment + labelEndHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y1 > y2) {
|
||||||
|
// y1 under y2.
|
||||||
|
y1 -= adjustment + labelStartHeight;
|
||||||
|
y2 += adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof color == "undefined") {
|
||||||
|
color = "#000";
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(`to : ${x1},${y1} -------- ${x2}, ${y2}`);
|
||||||
|
// console.log(`inclinacion de ${g}`);
|
||||||
|
|
||||||
const svgs = element.getElementsByTagName("svg");
|
const svgs = element.getElementsByTagName("svg");
|
||||||
|
|
||||||
|
@ -338,193 +175,76 @@ export default class NetworkLink extends Item<NetworkLinkProps> {
|
||||||
|
|
||||||
if (svg != null) {
|
if (svg != null) {
|
||||||
// Set SVG size.
|
// Set SVG size.
|
||||||
svg.setAttribute("width", `${width + lineWidth}`);
|
|
||||||
svg.setAttribute("height", `${height + lineWidth}`);
|
|
||||||
|
|
||||||
const lines = svg.getElementsByTagNameNS(svgNS, "line");
|
const lines = svg.getElementsByTagNameNS(svgNS, "line");
|
||||||
|
let groups = svg.getElementsByTagNameNS(svgNS, "g");
|
||||||
|
while (groups.length > 0) {
|
||||||
|
groups[0].remove();
|
||||||
|
}
|
||||||
|
|
||||||
if (lines.length > 0) {
|
if (lines.length > 0) {
|
||||||
const line = lines.item(0);
|
const line = lines.item(0);
|
||||||
|
|
||||||
if (line != null) {
|
if (line != null) {
|
||||||
line.setAttribute("x1", `${x1}`);
|
// let rect = document.createElementNS(
|
||||||
line.setAttribute("y1", `${y1}`);
|
// "http://www.w3.org/2000/svg",
|
||||||
line.setAttribute("x2", `${x2}`);
|
// "rect"
|
||||||
line.setAttribute("y2", `${y2}`);
|
// );
|
||||||
line.setAttribute("stroke", color || "black");
|
// rect.setAttribute("x", SVGRect.x);
|
||||||
line.setAttribute("stroke-width", `${lineWidth}`);
|
// rect.setAttribute("y", SVGRect.y);
|
||||||
|
// rect.setAttribute("width", SVGRect.width);
|
||||||
|
// rect.setAttribute("height", SVGRect.height);
|
||||||
|
// rect.setAttribute("fill", "yellow");
|
||||||
|
|
||||||
|
let start = document.createElementNS(svgNS, "g");
|
||||||
|
start.setAttribute("x", `${x1}`);
|
||||||
|
start.setAttribute("y", `${y1}`);
|
||||||
|
start.setAttribute("width", `${labelStartWidth + fontsize * 2}`);
|
||||||
|
start.setAttribute("height", `${labelStartHeight}`);
|
||||||
|
start.setAttribute("transform", `rotate(${g} ${x1} ${y1})`);
|
||||||
|
|
||||||
|
let sr = document.createElementNS(svgNS, "rect");
|
||||||
|
sr.setAttribute("x", `${x1}`);
|
||||||
|
sr.setAttribute("y", `${y1}`);
|
||||||
|
sr.setAttribute("width", `${labelStartWidth}`);
|
||||||
|
sr.setAttribute("height", `${labelStartHeight}`);
|
||||||
|
sr.setAttribute("stroke", `${color}`);
|
||||||
|
sr.setAttribute("stroke-width", "2");
|
||||||
|
sr.setAttribute("fill", "#FFF");
|
||||||
|
start.append(sr);
|
||||||
|
|
||||||
|
let st = document.createElementNS(svgNS, "text");
|
||||||
|
st.setAttribute("x", `${x1 + fontsize}`);
|
||||||
|
st.setAttribute("y", `${y1 + (fontheight * 2) / 3}`);
|
||||||
|
st.setAttribute("fill", "#000");
|
||||||
|
st.textContent = this.labelStart;
|
||||||
|
st.setAttribute("transform", `rotate(${g} ${x1} ${y1})`);
|
||||||
|
start.append(st);
|
||||||
|
|
||||||
|
let end = document.createElementNS(svgNS, "g");
|
||||||
|
let er = document.createElementNS(svgNS, "rect");
|
||||||
|
er.setAttribute("x", `${x2}`);
|
||||||
|
er.setAttribute("y", `${y2}`);
|
||||||
|
er.setAttribute("width", `${labelEndWidth + fontsize * 2}`);
|
||||||
|
er.setAttribute("height", `${labelEndHeight}`);
|
||||||
|
er.setAttribute("stroke", `${color}`);
|
||||||
|
er.setAttribute("stroke-width", "2");
|
||||||
|
er.setAttribute("fill", "#FFF");
|
||||||
|
er.setAttribute("transform", `rotate(${g} ${x1} ${y1})`);
|
||||||
|
end.append(er);
|
||||||
|
|
||||||
|
let et = document.createElementNS(svgNS, "text");
|
||||||
|
et.setAttribute("x", `${x2 + fontsize}`);
|
||||||
|
et.setAttribute("y", `${y2 + (fontheight * 2) / 3}`);
|
||||||
|
et.setAttribute("fill", "#000");
|
||||||
|
et.textContent = this.labelEnd;
|
||||||
|
et.setAttribute("transform", `rotate(${g} ${x1} ${y1})`);
|
||||||
|
end.append(et);
|
||||||
|
|
||||||
|
svg.append(start);
|
||||||
|
svg.append(end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.moveMode) {
|
|
||||||
const startIsLeft = startPosition.x - endPosition.x <= 0;
|
|
||||||
const startIsTop = startPosition.y - endPosition.y <= 0;
|
|
||||||
|
|
||||||
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.backgroundColor = `${color}`;
|
|
||||||
startCircle.style.position = "absolute";
|
|
||||||
startCircle.style.left = startIsLeft
|
|
||||||
? `-${this.circleRadius}px`
|
|
||||||
: `${width + lineWidth - this.circleRadius}px`;
|
|
||||||
startCircle.style.top = startIsTop
|
|
||||||
? `-${this.circleRadius}px`
|
|
||||||
: `${height + lineWidth - this.circleRadius}px`;
|
|
||||||
|
|
||||||
endCircle.classList.add(
|
|
||||||
"visual-console-item-line-circle",
|
|
||||||
"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.backgroundColor = `${color}`;
|
|
||||||
endCircle.style.position = "absolute";
|
|
||||||
endCircle.style.left = startIsLeft
|
|
||||||
? `${width + lineWidth - 8}px`
|
|
||||||
: `-${this.circleRadius}px`;
|
|
||||||
endCircle.style.top = startIsTop
|
|
||||||
? `${height + lineWidth - this.circleRadius}px`
|
|
||||||
: `-${this.circleRadius}px`;
|
|
||||||
|
|
||||||
if (element.parentElement !== null) {
|
|
||||||
const circles = element.parentElement.getElementsByClassName(
|
|
||||||
"visual-console-item-line-circle"
|
|
||||||
);
|
|
||||||
while (circles.length > 0) {
|
|
||||||
const circle = circles.item(0);
|
|
||||||
if (circle) circle.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
element.parentElement.appendChild(startCircle);
|
|
||||||
element.parentElement.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.moveMode) {
|
|
||||||
this.stopStartPositionMovementListener();
|
|
||||||
// Remove circles.
|
|
||||||
if (element.parentElement !== null) {
|
|
||||||
const circles = element.parentElement.getElementsByClassName(
|
|
||||||
"visual-console-item-line-circle"
|
|
||||||
);
|
|
||||||
|
|
||||||
while (circles.length > 0) {
|
|
||||||
const circle = circles.item(0);
|
|
||||||
if (circle) circle.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.stopStartPositionMovementListener();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the size and position of the box from
|
|
||||||
* the start and the finish of the line.
|
|
||||||
* @param props Item properties.
|
|
||||||
*/
|
|
||||||
public static extractBoxSizeAndPosition(
|
|
||||||
startPosition: Position,
|
|
||||||
endPosition: Position
|
|
||||||
): Size & Position {
|
|
||||||
return {
|
|
||||||
width: Math.abs(startPosition.x - endPosition.x),
|
|
||||||
height: Math.abs(startPosition.y - endPosition.y),
|
|
||||||
x: Math.min(startPosition.x, endPosition.x),
|
|
||||||
y: Math.min(startPosition.y, endPosition.y)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the position into the properties and move the DOM container.
|
|
||||||
* @param x Horizontal axis position.
|
|
||||||
* @param y Vertical axis position.
|
|
||||||
* @override item function
|
|
||||||
*/
|
|
||||||
public move(x: number, y: number): void {
|
|
||||||
super.moveElement(x, y);
|
|
||||||
const startIsLeft =
|
|
||||||
this.props.startPosition.x - this.props.endPosition.x <= 0;
|
|
||||||
const startIsTop =
|
|
||||||
this.props.startPosition.y - this.props.endPosition.y <= 0;
|
|
||||||
|
|
||||||
const start = {
|
|
||||||
x: startIsLeft ? x : this.props.width + x,
|
|
||||||
y: startIsTop ? y : this.props.height + y
|
|
||||||
};
|
|
||||||
|
|
||||||
const end = {
|
|
||||||
x: startIsLeft ? this.props.width + x : x,
|
|
||||||
y: startIsTop ? this.props.height + y : y
|
|
||||||
};
|
|
||||||
|
|
||||||
this.props = {
|
|
||||||
...this.props,
|
|
||||||
startPosition: start,
|
|
||||||
endPosition: end
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To remove the event listeners and the elements from the DOM.
|
|
||||||
* @override Item.remove
|
|
||||||
*/
|
|
||||||
public remove(): void {
|
|
||||||
// Clear the item's event listeners.
|
|
||||||
this.stopStartPositionMovementListener();
|
|
||||||
// Call the parent's .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 onNetworkLinkMovementFinished(
|
|
||||||
listener: Listener<NetworkLinkMovedEvent>
|
|
||||||
): 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…
Reference in New Issue