Merged PR 216: Deprecate parent from IContainerModel for FindContainerById
This commit is contained in:
parent
d40cd8cf8e
commit
b4eba6bb9b
19 changed files with 97 additions and 109 deletions
|
@ -5,10 +5,6 @@ onmessage = (e) => {
|
||||||
|
|
||||||
const getCircularReplacer = () => {
|
const getCircularReplacer = () => {
|
||||||
return (key, value) => {
|
return (key, value) => {
|
||||||
if (key === 'parent') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key === 'containers') {
|
if (key === 'containers') {
|
||||||
return [...value.entries()]
|
return [...value.entries()]
|
||||||
.map(([Key, Value]) => ({ Key, Value }));
|
.map(([Key, Value]) => ({ Key, Value }));
|
||||||
|
|
|
@ -98,7 +98,6 @@ describe.concurrent('Models test suite', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const mainContainer = new ContainerModel(
|
const mainContainer = new ContainerModel(
|
||||||
null,
|
|
||||||
DEFAULT_MAINCONTAINER_PROPS
|
DEFAULT_MAINCONTAINER_PROPS
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -267,7 +266,6 @@ describe.concurrent('Models test suite', () => {
|
||||||
it('ContainerModel', async() => {
|
it('ContainerModel', async() => {
|
||||||
const model: IContainerModel = {
|
const model: IContainerModel = {
|
||||||
children: [],
|
children: [],
|
||||||
parent: null,
|
|
||||||
properties: containerProperties,
|
properties: containerProperties,
|
||||||
userData: {}
|
userData: {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -78,7 +78,6 @@ export function App(props: IAppProps): JSX.Element {
|
||||||
const appRef = useRef<HTMLDivElement>(null);
|
const appRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const defaultMainContainer = new ContainerModel(
|
const defaultMainContainer = new ContainerModel(
|
||||||
null,
|
|
||||||
DEFAULT_MAINCONTAINER_PROPS
|
DEFAULT_MAINCONTAINER_PROPS
|
||||||
);
|
);
|
||||||
const containers = new Map<string, IContainerModel>();
|
const containers = new Map<string, IContainerModel>();
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { GetAbsolutePosition } from '../../utils/itertools';
|
||||||
import { RemoveMargin } from '../../utils/svg';
|
import { RemoveMargin } from '../../utils/svg';
|
||||||
|
|
||||||
interface ISelectorProps {
|
interface ISelectorProps {
|
||||||
|
containers: Map<string, IContainerModel>
|
||||||
selected?: IContainerModel
|
selected?: IContainerModel
|
||||||
scale?: number
|
scale?: number
|
||||||
}
|
}
|
||||||
|
@ -14,7 +15,7 @@ export function RenderSelector(ctx: CanvasRenderingContext2D, frameCount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const scale = (props.scale ?? 1);
|
const scale = (props.scale ?? 1);
|
||||||
let [x, y] = GetAbsolutePosition(props.selected);
|
let [x, y] = GetAbsolutePosition(props.containers, props.selected);
|
||||||
let [width, height] = [
|
let [width, height] = [
|
||||||
props.selected.properties.width,
|
props.selected.properties.width,
|
||||||
props.selected.properties.height
|
props.selected.properties.height
|
||||||
|
|
|
@ -163,7 +163,6 @@ function AddNewContainerToParent(
|
||||||
|
|
||||||
// Create the container
|
// Create the container
|
||||||
const newContainer = new ContainerModel(
|
const newContainer = new ContainerModel(
|
||||||
parentClone,
|
|
||||||
defaultProperties,
|
defaultProperties,
|
||||||
[],
|
[],
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,9 +57,10 @@ export function DeleteContainer(
|
||||||
throw new Error(`[DeleteContainer] Tried to delete a container that is not present in the main container: ${containerId}`);
|
throw new Error(`[DeleteContainer] Tried to delete a container that is not present in the main container: ${containerId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
if (container === mainContainerClone ||
|
if (container === mainContainerClone ||
|
||||||
container.parent === undefined ||
|
parent === undefined ||
|
||||||
container.parent === null) {
|
parent === null) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'Oops...',
|
title: 'Oops...',
|
||||||
text: 'Deleting the main container is not allowed!',
|
text: 'Deleting the main container is not allowed!',
|
||||||
|
@ -75,10 +76,10 @@ export function DeleteContainer(
|
||||||
const newSymbols = structuredClone(current.symbols);
|
const newSymbols = structuredClone(current.symbols);
|
||||||
UnlinkContainerFromSymbols(containers, newSymbols, container);
|
UnlinkContainerFromSymbols(containers, newSymbols, container);
|
||||||
|
|
||||||
const index = container.parent.children.indexOf(container.properties.id);
|
const index = parent.children.indexOf(container.properties.id);
|
||||||
const success = containers.delete(container.properties.id);
|
const success = containers.delete(container.properties.id);
|
||||||
if (index > -1 && success) {
|
if (index > -1 && success) {
|
||||||
container.parent.children.splice(index, 1);
|
parent.children.splice(index, 1);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('[DeleteContainer] Could not find container among parent\'s children');
|
throw new Error('[DeleteContainer] Could not find container among parent\'s children');
|
||||||
}
|
}
|
||||||
|
@ -90,7 +91,7 @@ export function DeleteContainer(
|
||||||
const selectedContainerId = GetSelectedContainerOnDelete(
|
const selectedContainerId = GetSelectedContainerOnDelete(
|
||||||
containers,
|
containers,
|
||||||
current.selectedContainerId,
|
current.selectedContainerId,
|
||||||
container.parent,
|
parent,
|
||||||
index
|
index
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -202,12 +203,8 @@ export function OnPropertyChange(
|
||||||
*/
|
*/
|
||||||
export function SortChildren(
|
export function SortChildren(
|
||||||
containers: Map<string, IContainerModel>,
|
containers: Map<string, IContainerModel>,
|
||||||
parent: IContainerModel | null | undefined
|
parent: IContainerModel
|
||||||
): void {
|
): void {
|
||||||
if (parent === null || parent === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isHorizontal = parent.properties.orientation === Orientation.Horizontal;
|
const isHorizontal = parent.properties.orientation === Orientation.Horizontal;
|
||||||
const children = parent.children;
|
const children = parent.children;
|
||||||
|
|
||||||
|
@ -293,7 +290,10 @@ function SetContainer(
|
||||||
);
|
);
|
||||||
|
|
||||||
// sort the children list by their position
|
// sort the children list by their position
|
||||||
SortChildren(containers, container.parent);
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
|
if (parent !== null && parent !== undefined) {
|
||||||
|
SortChildren(containers, parent);
|
||||||
|
}
|
||||||
|
|
||||||
// Apply special behaviors: rigid, flex, symbol, anchor
|
// Apply special behaviors: rigid, flex, symbol, anchor
|
||||||
ApplyBehaviors(containers, container, symbols);
|
ApplyBehaviors(containers, container, symbols);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { ISetContainerListRequest } from '../../../Interfaces/ISetContainerListR
|
||||||
import { ISetContainerListResponse } from '../../../Interfaces/ISetContainerListResponse';
|
import { ISetContainerListResponse } from '../../../Interfaces/ISetContainerListResponse';
|
||||||
import { FindContainerById } from '../../../utils/itertools';
|
import { FindContainerById } from '../../../utils/itertools';
|
||||||
import { SetContainerList } from '../../API/api';
|
import { SetContainerList } from '../../API/api';
|
||||||
|
import { GetCurrentHistoryState } from '../Editor';
|
||||||
import { AddContainers } from './AddContainer';
|
import { AddContainers } from './AddContainer';
|
||||||
import { DeleteContainer } from './ContainerOperations';
|
import { DeleteContainer } from './ContainerOperations';
|
||||||
|
|
||||||
|
@ -62,15 +63,16 @@ export function GetAction(
|
||||||
function GetPreviousAndNextSiblings(containers: Map<string, IContainerModel>, container: IContainerModel): { prev: IContainerModel | undefined, next: IContainerModel | undefined } {
|
function GetPreviousAndNextSiblings(containers: Map<string, IContainerModel>, container: IContainerModel): { prev: IContainerModel | undefined, next: IContainerModel | undefined } {
|
||||||
let prev;
|
let prev;
|
||||||
let next;
|
let next;
|
||||||
if (container.parent !== undefined &&
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
container.parent !== null &&
|
if (parent !== undefined &&
|
||||||
container.parent.children.length > 1) {
|
parent !== null &&
|
||||||
const index = container.parent.children.indexOf(container.properties.id);
|
parent.children.length > 1) {
|
||||||
|
const index = parent.children.indexOf(container.properties.id);
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
prev = FindContainerById(containers, container.parent.children[index - 1]);
|
prev = FindContainerById(containers, parent.children[index - 1]);
|
||||||
}
|
}
|
||||||
if (index < container.parent.children.length - 1) {
|
if (index < parent.children.length - 1) {
|
||||||
next = FindContainerById(containers, container.parent.children[index + 1]);
|
next = FindContainerById(containers, parent.children[index + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { prev, next };
|
return { prev, next };
|
||||||
|
@ -86,6 +88,9 @@ function HandleSetContainerList(
|
||||||
setNewHistory: (newHistory: IHistoryState[]) => void
|
setNewHistory: (newHistory: IHistoryState[]) => void
|
||||||
): void {
|
): void {
|
||||||
const addingBehavior = response.AddingBehavior ?? action.AddingBehavior;
|
const addingBehavior = response.AddingBehavior ?? action.AddingBehavior;
|
||||||
|
const current = GetCurrentHistoryState(history, historyCurrentStep);
|
||||||
|
const containers = current.containers;
|
||||||
|
const parent = FindContainerById(containers, selectedContainer.properties.parentId);
|
||||||
switch (addingBehavior) {
|
switch (addingBehavior) {
|
||||||
case AddMethod.Append:
|
case AddMethod.Append:
|
||||||
setNewHistory(
|
setNewHistory(
|
||||||
|
@ -103,6 +108,7 @@ function HandleSetContainerList(
|
||||||
case AddMethod.Replace:
|
case AddMethod.Replace:
|
||||||
setNewHistory(
|
setNewHistory(
|
||||||
HandleReplace(
|
HandleReplace(
|
||||||
|
containers,
|
||||||
selectedContainer,
|
selectedContainer,
|
||||||
response,
|
response,
|
||||||
configuration,
|
configuration,
|
||||||
|
@ -112,7 +118,7 @@ function HandleSetContainerList(
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case AddMethod.ReplaceParent:
|
case AddMethod.ReplaceParent:
|
||||||
if (selectedContainer.parent === undefined || selectedContainer.parent === null) {
|
if (parent === undefined || parent === null) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'Error',
|
title: 'Error',
|
||||||
text: 'The selected container has not parent to replace',
|
text: 'The selected container has not parent to replace',
|
||||||
|
@ -122,7 +128,8 @@ function HandleSetContainerList(
|
||||||
}
|
}
|
||||||
setNewHistory(
|
setNewHistory(
|
||||||
HandleReplace(
|
HandleReplace(
|
||||||
selectedContainer.parent,
|
containers,
|
||||||
|
parent,
|
||||||
response,
|
response,
|
||||||
configuration,
|
configuration,
|
||||||
history,
|
history,
|
||||||
|
@ -134,17 +141,19 @@ function HandleSetContainerList(
|
||||||
}
|
}
|
||||||
|
|
||||||
function HandleReplace(
|
function HandleReplace(
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
selectedContainer: IContainerModel,
|
selectedContainer: IContainerModel,
|
||||||
response: ISetContainerListResponse,
|
response: ISetContainerListResponse,
|
||||||
configuration: IConfiguration,
|
configuration: IConfiguration,
|
||||||
history: IHistoryState[],
|
history: IHistoryState[],
|
||||||
historyCurrentStep: number
|
historyCurrentStep: number
|
||||||
): IHistoryState[] {
|
): IHistoryState[] {
|
||||||
if (selectedContainer.parent === undefined || selectedContainer.parent === null) {
|
const parent = FindContainerById(containers, selectedContainer.properties.parentId);
|
||||||
|
if (parent === undefined || parent === null) {
|
||||||
throw new Error('[ReplaceContainer] Cannot replace a container that does not exists');
|
throw new Error('[ReplaceContainer] Cannot replace a container that does not exists');
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = selectedContainer.parent.children.indexOf(selectedContainer.properties.id);
|
const index = parent.children.indexOf(selectedContainer.properties.id);
|
||||||
|
|
||||||
const newHistoryAfterDelete = DeleteContainer(
|
const newHistoryAfterDelete = DeleteContainer(
|
||||||
selectedContainer.properties.id,
|
selectedContainer.properties.id,
|
||||||
|
|
|
@ -18,12 +18,11 @@ export function ApplyBehaviors(containers: Map<string, IContainerModel>, contain
|
||||||
try {
|
try {
|
||||||
const symbol = symbols.get(container.properties.linkedSymbolId);
|
const symbol = symbols.get(container.properties.linkedSymbolId);
|
||||||
if (container.properties.linkedSymbolId !== '' && symbol !== undefined) {
|
if (container.properties.linkedSymbolId !== '' && symbol !== undefined) {
|
||||||
ApplySymbol(container, symbol);
|
ApplySymbol(containers, container, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container.parent !== undefined && container.parent !== null) {
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
const parent = container.parent;
|
if (parent !== undefined && parent !== null) {
|
||||||
|
|
||||||
if (container.properties.isAnchor) {
|
if (container.properties.isAnchor) {
|
||||||
ApplyAnchor(containers, container, parent);
|
ApplyAnchor(containers, container, parent);
|
||||||
}
|
}
|
||||||
|
@ -69,11 +68,12 @@ export function ApplyBehaviorsOnSiblingsChildren(
|
||||||
containers: Map<string, IContainerModel>,
|
containers: Map<string, IContainerModel>,
|
||||||
newContainer: IContainerModel,
|
newContainer: IContainerModel,
|
||||||
symbols: Map<string, ISymbolModel>): void {
|
symbols: Map<string, ISymbolModel>): void {
|
||||||
if (newContainer.parent === null || newContainer.parent === undefined) {
|
const parent = FindContainerById(containers, newContainer.properties.parentId);
|
||||||
|
if (parent === null || parent === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
newContainer.parent.children
|
parent.children
|
||||||
.forEach((containerId: string) => {
|
.forEach((containerId: string) => {
|
||||||
const container = FindContainerById(containers, containerId);
|
const container = FindContainerById(containers, containerId);
|
||||||
|
|
||||||
|
@ -81,8 +81,9 @@ export function ApplyBehaviorsOnSiblingsChildren(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container.parent !== null) {
|
const containerParent = FindContainerById(containers, container.properties.parentId);
|
||||||
UpdateWarning(containers, container, container.parent);
|
if (containerParent !== null && containerParent !== undefined) {
|
||||||
|
UpdateWarning(containers, container, containerParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container === newContainer) {
|
if (container === newContainer) {
|
||||||
|
@ -102,11 +103,12 @@ export function ApplyBehaviorsOnSiblingsChildren(
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function ApplyBehaviorsOnSiblings(containers: Map<string, IContainerModel>, newContainer: IContainerModel, symbols: Map<string, ISymbolModel>): void {
|
export function ApplyBehaviorsOnSiblings(containers: Map<string, IContainerModel>, newContainer: IContainerModel, symbols: Map<string, ISymbolModel>): void {
|
||||||
if (newContainer.parent === null || newContainer.parent === undefined) {
|
const parent = FindContainerById(containers, newContainer.properties.parentId);
|
||||||
|
if (parent === null || parent === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
newContainer.parent.children
|
parent.children
|
||||||
.forEach((containerId: string) => {
|
.forEach((containerId: string) => {
|
||||||
const container = FindContainerById(containers, containerId);
|
const container = FindContainerById(containers, containerId);
|
||||||
|
|
||||||
|
@ -116,8 +118,9 @@ export function ApplyBehaviorsOnSiblings(containers: Map<string, IContainerModel
|
||||||
|
|
||||||
ApplyBehaviors(containers, container, symbols);
|
ApplyBehaviors(containers, container, symbols);
|
||||||
|
|
||||||
if (container.parent != null) {
|
const containerParent = FindContainerById(containers, container.properties.parentId);
|
||||||
UpdateWarning(containers, container, container.parent);
|
if (containerParent !== null && containerParent !== undefined) {
|
||||||
|
UpdateWarning(containers, container, containerParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container === newContainer) {
|
if (container === newContainer) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { ISizePointer } from '../../../Interfaces/ISizePointer';
|
import { ISizePointer } from '../../../Interfaces/ISizePointer';
|
||||||
import { Orientation } from '../../../Enums/Orientation';
|
import { Orientation } from '../../../Enums/Orientation';
|
||||||
import { ENABLE_HARD_RIGID } from '../../../utils/default';
|
import { ENABLE_HARD_RIGID } from '../../../utils/default';
|
||||||
import { MakeChildrenIterator } from '../../../utils/itertools';
|
import { FindContainerById, MakeChildrenIterator } from '../../../utils/itertools';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Transform the container into a rigid body"
|
* "Transform the container into a rigid body"
|
||||||
|
@ -122,17 +122,18 @@ export function ConstraintBodyInsideUnallocatedWidth(
|
||||||
containers: Map<string, IContainerModel>,
|
containers: Map<string, IContainerModel>,
|
||||||
container: IContainerModel
|
container: IContainerModel
|
||||||
): IContainerModel {
|
): IContainerModel {
|
||||||
if (container.parent === null || container.parent === undefined) {
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
|
if (parent === null || parent === undefined) {
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the available spaces of the parent
|
// Get the available spaces of the parent
|
||||||
const isHorizontal =
|
const isHorizontal =
|
||||||
container.parent.properties.orientation === Orientation.Horizontal;
|
parent.properties.orientation === Orientation.Horizontal;
|
||||||
const children: IContainerModel[] = [...MakeChildrenIterator(containers, container.parent.children)];
|
const children: IContainerModel[] = [...MakeChildrenIterator(containers, parent.children)];
|
||||||
const availableWidths = GetAvailableWidths(
|
const availableWidths = GetAvailableWidths(
|
||||||
0,
|
0,
|
||||||
container.parent.properties.width,
|
parent.properties.width,
|
||||||
children,
|
children,
|
||||||
container,
|
container,
|
||||||
isHorizontal
|
isHorizontal
|
||||||
|
@ -172,7 +173,7 @@ export function ConstraintBodyInsideUnallocatedWidth(
|
||||||
container,
|
container,
|
||||||
0,
|
0,
|
||||||
availableWidthFound.x,
|
availableWidthFound.x,
|
||||||
container.parent.properties.width,
|
parent.properties.width,
|
||||||
availableWidthFound.width
|
availableWidthFound.width
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -203,7 +204,7 @@ export function ConstraintBodyInsideUnallocatedWidth(
|
||||||
availableWidthFound.x,
|
availableWidthFound.x,
|
||||||
0,
|
0,
|
||||||
availableWidthFound.width,
|
availableWidthFound.width,
|
||||||
container.parent.properties.height
|
parent.properties.height
|
||||||
);
|
);
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
import { ApplyParentTransform } from '../../../utils/itertools';
|
import { ApplyParentTransform, FindContainerById } from '../../../utils/itertools';
|
||||||
import { RestoreX, TransformX } from '../../../utils/svg';
|
import { RestoreX, TransformX } from '../../../utils/svg';
|
||||||
|
|
||||||
export function ApplySymbol(container: IContainerModel, symbol: ISymbolModel): IContainerModel {
|
export function ApplySymbol(containers: Map<string, IContainerModel>, container: IContainerModel, symbol: ISymbolModel): IContainerModel {
|
||||||
container.properties.x = TransformX(symbol.x, symbol.width, symbol.config.PositionReference);
|
container.properties.x = TransformX(symbol.x, symbol.width, symbol.config.PositionReference);
|
||||||
container.properties.x = RestoreX(container.properties.x, container.properties.width, container.properties.positionReference);
|
container.properties.x = RestoreX(container.properties.x, container.properties.width, container.properties.positionReference);
|
||||||
const [x] = ApplyParentTransform(container.parent, container.properties.x, 0);
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
|
let x = 0;
|
||||||
|
if (parent !== undefined && parent !== null) {
|
||||||
|
([x] = ApplyParentTransform(containers, parent, container.properties.x, 0));
|
||||||
|
}
|
||||||
container.properties.x = x;
|
container.properties.x = x;
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,8 +87,9 @@ function HandleOnDrop(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetContainer.parent === null ||
|
const parent = FindContainerById(containers, targetContainer.properties.parentId);
|
||||||
targetContainer.parent === undefined) {
|
if (parent === null ||
|
||||||
|
parent === undefined) {
|
||||||
throw new Error('[handleDrop] Tried to drop into a child container without a parent!');
|
throw new Error('[handleDrop] Tried to drop into a child container without a parent!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,11 +98,11 @@ function HandleOnDrop(
|
||||||
|
|
||||||
// locate the hitboxes
|
// locate the hitboxes
|
||||||
if (y < 12) {
|
if (y < 12) {
|
||||||
const index = targetContainer.parent.children.indexOf(targetContainer.properties.id);
|
const index = parent.children.indexOf(targetContainer.properties.id);
|
||||||
addContainer(
|
addContainer(
|
||||||
index,
|
index,
|
||||||
type,
|
type,
|
||||||
targetContainer.parent.properties.id
|
parent.properties.id
|
||||||
);
|
);
|
||||||
} else if (y < 24) {
|
} else if (y < 24) {
|
||||||
addContainer(
|
addContainer(
|
||||||
|
@ -109,11 +110,11 @@ function HandleOnDrop(
|
||||||
type,
|
type,
|
||||||
targetContainer.properties.id);
|
targetContainer.properties.id);
|
||||||
} else {
|
} else {
|
||||||
const index = targetContainer.parent.children.indexOf(targetContainer.properties.id);
|
const index = parent.children.indexOf(targetContainer.properties.id);
|
||||||
addContainer(
|
addContainer(
|
||||||
index + 1,
|
index + 1,
|
||||||
type,
|
type,
|
||||||
targetContainer.parent.properties.id
|
parent.properties.id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ function GetDimensionsNodes(
|
||||||
max = -Infinity;
|
max = -Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
const absoluteX = GetAbsolutePosition(container)[0];
|
const absoluteX = GetAbsolutePosition(containers, container)[0];
|
||||||
const x = TransformX(absoluteX, container.properties.width, container.properties.positionReference);
|
const x = TransformX(absoluteX, container.properties.width, container.properties.positionReference);
|
||||||
lastY = container.properties.y + container.properties.height;
|
lastY = container.properties.y + container.properties.height;
|
||||||
if (x < min) {
|
if (x < min) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { GetAbsolutePosition } from '../../../../utils/itertools';
|
||||||
import { RemoveMargin } from '../../../../utils/svg';
|
import { RemoveMargin } from '../../../../utils/svg';
|
||||||
|
|
||||||
interface ISelectorProps {
|
interface ISelectorProps {
|
||||||
|
containers: Map<string, IContainerModel>
|
||||||
selected?: IContainerModel
|
selected?: IContainerModel
|
||||||
scale?: number
|
scale?: number
|
||||||
}
|
}
|
||||||
|
@ -19,7 +20,7 @@ export function Selector(props: ISelectorProps): JSX.Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
const scale = (props.scale ?? 1);
|
const scale = (props.scale ?? 1);
|
||||||
let [x, y] = GetAbsolutePosition(props.selected);
|
let [x, y] = GetAbsolutePosition(props.containers, props.selected);
|
||||||
let [width, height] = [
|
let [width, height] = [
|
||||||
props.selected.properties.width,
|
props.selected.properties.width,
|
||||||
props.selected.properties.height
|
props.selected.properties.height
|
||||||
|
|
|
@ -98,7 +98,7 @@ export function SVG(props: ISVGProps): JSX.Element {
|
||||||
: null}
|
: null}
|
||||||
<DimensionLayer containers={props.containers} scale={scale} root={props.children} />
|
<DimensionLayer containers={props.containers} scale={scale} root={props.children} />
|
||||||
<SymbolLayer scale={scale} symbols={props.symbols} />
|
<SymbolLayer scale={scale} symbols={props.symbols} />
|
||||||
<Selector scale={scale} selected={props.selected} /> {/* leave this at the end so it can be removed during the svg export */}
|
<Selector containers={props.containers} scale={scale} selected={props.selected} /> {/* leave this at the end so it can be removed during the svg export */}
|
||||||
</svg>
|
</svg>
|
||||||
</ReactSVGPanZoom>
|
</ReactSVGPanZoom>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -147,6 +147,7 @@ export function Viewer({
|
||||||
|
|
||||||
// Draw selector
|
// Draw selector
|
||||||
RenderSelector(ctx, frameCount, {
|
RenderSelector(ctx, frameCount, {
|
||||||
|
containers: current.containers,
|
||||||
scale,
|
scale,
|
||||||
selected: selectedContainer
|
selected: selectedContainer
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,9 +2,6 @@ import { IContainerProperties } from './IContainerProperties';
|
||||||
|
|
||||||
export interface IContainerModel {
|
export interface IContainerModel {
|
||||||
children: string[]
|
children: string[]
|
||||||
// TODO: Remove parent now that accessing the parent by id is faster.
|
|
||||||
// TODO: Use GetContainerById(container.properties.parentId) as the better alternative.
|
|
||||||
parent: IContainerModel | null
|
|
||||||
properties: IContainerProperties
|
properties: IContainerProperties
|
||||||
userData: Record<string, string | number>
|
userData: Record<string, string | number>
|
||||||
}
|
}
|
||||||
|
@ -15,18 +12,13 @@ export interface IContainerModel {
|
||||||
*/
|
*/
|
||||||
export class ContainerModel implements IContainerModel {
|
export class ContainerModel implements IContainerModel {
|
||||||
public children: string[];
|
public children: string[];
|
||||||
// TODO: Remove parent now that accessing the parent by id is faster.
|
|
||||||
// TODO: Use GetContainerById(container.properties.parentId) as the better alternative.
|
|
||||||
public parent: IContainerModel | null;
|
|
||||||
public properties: IContainerProperties;
|
public properties: IContainerProperties;
|
||||||
public userData: Record<string, string | number>;
|
public userData: Record<string, string | number>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
parent: IContainerModel | null,
|
|
||||||
properties: IContainerProperties,
|
properties: IContainerProperties,
|
||||||
children: string[] = [],
|
children: string[] = [],
|
||||||
userData = {}) {
|
userData = {}) {
|
||||||
this.parent = parent;
|
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
this.children = children;
|
this.children = children;
|
||||||
this.userData = userData;
|
this.userData = userData;
|
||||||
|
|
|
@ -121,7 +121,6 @@ export function GetDefaultEditorState(configuration: IConfiguration): IEditorSta
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const mainContainer = new ContainerModel(
|
const mainContainer = new ContainerModel(
|
||||||
null,
|
|
||||||
mainContainerConfig
|
mainContainerConfig
|
||||||
);
|
);
|
||||||
const containers = new Map<string, IContainerModel>();
|
const containers = new Map<string, IContainerModel>();
|
||||||
|
|
|
@ -123,16 +123,16 @@ export function * MakeRecursionDFSIterator(
|
||||||
/**
|
/**
|
||||||
* Returns the depth of the container
|
* Returns the depth of the container
|
||||||
* @returns The depth of the container
|
* @returns The depth of the container
|
||||||
* @deprecated Please avoid using this function inside an iterationl,
|
* @deprecated Please avoid using this function inside an iteration,
|
||||||
* use recursive DFS or iterative BFS to get the depth
|
* use recursive DFS or iterative BFS to get the depth
|
||||||
*/
|
*/
|
||||||
export function GetDepth(parent: IContainerModel): number {
|
export function GetDepth(containers: Map<string, IContainerModel>, parent: IContainerModel): number {
|
||||||
let depth = 0;
|
let depth = 0;
|
||||||
|
|
||||||
let current: IContainerModel | null = parent;
|
let current: IContainerModel | null = parent;
|
||||||
while (current != null) {
|
while (current != null) {
|
||||||
depth++;
|
depth++;
|
||||||
current = current.parent;
|
current = FindContainerById(containers, current.properties.parentId) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return depth;
|
return depth;
|
||||||
|
@ -142,22 +142,31 @@ export function GetDepth(parent: IContainerModel): number {
|
||||||
* Returns the absolute position by iterating to the parent
|
* Returns the absolute position by iterating to the parent
|
||||||
* @returns The absolute position of the container
|
* @returns The absolute position of the container
|
||||||
*/
|
*/
|
||||||
export function GetAbsolutePosition(container: IContainerModel): [number, number] {
|
export function GetAbsolutePosition(containers: Map<string, IContainerModel>, container: IContainerModel): [number, number] {
|
||||||
const x = container.properties.x;
|
const x = container.properties.x;
|
||||||
const y = container.properties.y;
|
const y = container.properties.y;
|
||||||
return CancelParentTransform(container.parent, x, y);
|
const parent = FindContainerById(containers, container.properties.parentId) ?? null;
|
||||||
|
return CancelParentTransform(containers, parent, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GetContainerLinkedList(container: IContainerModel, stop?: IContainerModel): IContainerModel[] {
|
export function GetContainerLinkedList(
|
||||||
const it = MakeContainerLinkedListIterator(container, stop);
|
containers: Map<string, IContainerModel>,
|
||||||
|
container: IContainerModel,
|
||||||
|
stop?: IContainerModel
|
||||||
|
): IContainerModel[] {
|
||||||
|
const it = MakeContainerLinkedListIterator(containers, container, stop);
|
||||||
return [...it];
|
return [...it];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function * MakeContainerLinkedListIterator(container: IContainerModel, stop?: IContainerModel): Generator<IContainerModel, void, unknown> {
|
export function * MakeContainerLinkedListIterator(
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
|
container: IContainerModel,
|
||||||
|
stop?: IContainerModel
|
||||||
|
): Generator<IContainerModel, void, unknown> {
|
||||||
let current: IContainerModel | null = container;
|
let current: IContainerModel | null = container;
|
||||||
while (current !== stop && current != null) {
|
while (current !== stop && current != null) {
|
||||||
yield current;
|
yield current;
|
||||||
current = current.parent;
|
current = FindContainerById(containers, current.properties.parentId) ?? null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,6 +178,7 @@ export function * MakeContainerLinkedListIterator(container: IContainerModel, st
|
||||||
* @returns x and y such that the transformations of the parent are cancelled
|
* @returns x and y such that the transformations of the parent are cancelled
|
||||||
*/
|
*/
|
||||||
export function CancelParentTransform(
|
export function CancelParentTransform(
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
parent: IContainerModel | null,
|
parent: IContainerModel | null,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
|
@ -178,7 +188,7 @@ export function CancelParentTransform(
|
||||||
return [x, y];
|
return [x, y];
|
||||||
}
|
}
|
||||||
|
|
||||||
const it = MakeContainerLinkedListIterator(parent, stop);
|
const it = MakeContainerLinkedListIterator(containers, parent, stop);
|
||||||
for (const current of it) {
|
for (const current of it) {
|
||||||
x += current.properties.x;
|
x += current.properties.x;
|
||||||
y += current.properties.y;
|
y += current.properties.y;
|
||||||
|
@ -195,6 +205,7 @@ export function CancelParentTransform(
|
||||||
* @returns x and y such that the transformations of the parent are applied
|
* @returns x and y such that the transformations of the parent are applied
|
||||||
*/
|
*/
|
||||||
export function ApplyParentTransform(
|
export function ApplyParentTransform(
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
parent: IContainerModel | null,
|
parent: IContainerModel | null,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
|
@ -204,7 +215,7 @@ export function ApplyParentTransform(
|
||||||
return [x, y];
|
return [x, y];
|
||||||
}
|
}
|
||||||
|
|
||||||
const it = MakeContainerLinkedListIterator(parent, stop);
|
const it = MakeContainerLinkedListIterator(containers, parent, stop);
|
||||||
for (const current of it) {
|
for (const current of it) {
|
||||||
x -= current.properties.x;
|
x -= current.properties.x;
|
||||||
y -= current.properties.y;
|
y -= current.properties.y;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { FindContainerById, MakeDFSIterator } from './itertools';
|
|
||||||
import { IEditorState } from '../Interfaces/IEditorState';
|
import { IEditorState } from '../Interfaces/IEditorState';
|
||||||
import { IHistoryState } from '../Interfaces/IHistoryState';
|
import { IHistoryState } from '../Interfaces/IHistoryState';
|
||||||
import { IContainerModel } from '../Interfaces/IContainerModel';
|
import { IContainerModel } from '../Interfaces/IContainerModel';
|
||||||
|
@ -37,36 +36,10 @@ export function ReviveState(state: IHistoryState): void {
|
||||||
|
|
||||||
const containers: Array<{ Key: string, Value: IContainerModel }> = (state.containers) as any;
|
const containers: Array<{ Key: string, Value: IContainerModel }> = (state.containers) as any;
|
||||||
state.containers = new Map(containers.map(({ Key, Value }: {Key: string, Value: IContainerModel}) => [Key, Value]));
|
state.containers = new Map(containers.map(({ Key, Value }: {Key: string, Value: IContainerModel}) => [Key, Value]));
|
||||||
|
|
||||||
const root = FindContainerById(state.containers, state.mainContainer);
|
|
||||||
|
|
||||||
if (root === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove parent and remove this bloc of code
|
|
||||||
// TODO: See IContainerModel.ts for more detail
|
|
||||||
const it = MakeDFSIterator(root, state.containers);
|
|
||||||
for (const container of it) {
|
|
||||||
const parentId = container.properties.parentId;
|
|
||||||
if (parentId === null) {
|
|
||||||
container.parent = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const parent = FindContainerById(state.containers, parentId);
|
|
||||||
if (parent === undefined) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
container.parent = parent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GetCircularReplacer(): (key: any, value: object | Map<string, any> | null) => object | null | undefined {
|
export function GetCircularReplacer(): (key: any, value: object | Map<string, any> | null) => object | null | undefined {
|
||||||
return (key: any, value: object | null) => {
|
return (key: any, value: object | null) => {
|
||||||
if (key === 'parent') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key === 'containers') {
|
if (key === 'containers') {
|
||||||
return [...(value as Map<string, any>).entries()]
|
return [...(value as Map<string, any>).entries()]
|
||||||
.map(([Key, Value]: [string, any]) => ({ Key, Value }));
|
.map(([Key, Value]: [string, any]) => ({ Key, Value }));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue