Add connection stype support

This commit is contained in:
Paulo Veiga 2022-12-22 04:18:10 +00:00
parent c8482e1764
commit fcfdc5b435
41 changed files with 290 additions and 157 deletions

View File

@ -1,6 +1,9 @@
context('Node manager', () => { context('Node manager', () => {
before(() => { before(() => {
cy.visit('/editor.html'); cy.visit('/editor.html');
// Wait for load complate ...
cy.get('[aria-label="vortex-loading"]').should('not.exist');
}); });
it('shortcut add sibling node', () => { it('shortcut add sibling node', () => {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View File

@ -7,20 +7,23 @@ import {
fontSizes, fontSizes,
getNextValue, getNextValue,
} from '../../../components/toolbar/ToolbarValueModelBuilder'; } from '../../../components/toolbar/ToolbarValueModelBuilder';
import { LineType } from '@wisemapping/mindplot/src/components/ConnectionLine';
import { TopicShapeType } from '@wisemapping/mindplot/src/components/model/INodeModel';
class NodePropertyBuilder { class NodePropertyBuilder {
designer: Designer; designer: Designer;
fontSizeModel: NodeProperty<number>; private fontSizeModel: NodeProperty<number>;
selectedTopicColorModel: NodeProperty<string>; private selectedTopicColorModel: NodeProperty<string>;
fontFamilyModel: NodeProperty<string>; private fontFamilyModel: NodeProperty<string>;
fontStyleModel: NodeProperty<string>; private fontStyleModel: NodeProperty<string>;
borderColorModel: NodeProperty<string>; private borderColorModel: NodeProperty<string>;
fontColorModel: NodeProperty<string>; private fontColorModel: NodeProperty<string>;
topicShapeModel: NodeProperty<string>; private topicShapeModel: NodeProperty<TopicShapeType>;
topicIconModel: NodeProperty<string>; private topicIconModel: NodeProperty<string>;
noteModel: NodeProperty<string>; private connetionStyleModel: NodeProperty<LineType>;
linkModel: NodeProperty<string>; private noteModel: NodeProperty<string>;
private linkModel: NodeProperty<string>;
constructor(designer: Designer) { constructor(designer: Designer) {
this.designer = designer; this.designer = designer;
@ -34,7 +37,9 @@ class NodePropertyBuilder {
return this.designer.getModel().selectedTopic()?.getFontSize(); return this.designer.getModel().selectedTopic()?.getFontSize();
} }
private uniqueOrNull(propertyGetter: (Topic: Topic) => string | number | null) { private uniqueOrNull(
propertyGetter: (Topic: Topic) => string | number | null | LineType,
): string {
const nodes = this.designer.getModel().filterSelectedTopics(); const nodes = this.designer.getModel().filterSelectedTopics();
return getTheUniqueValueOrNull(nodes, propertyGetter); return getTheUniqueValueOrNull(nodes, propertyGetter);
} }
@ -190,15 +195,20 @@ class NodePropertyBuilder {
return this.fontStyleModel; return this.fontStyleModel;
} }
/** getConnectionStyleModel(): NodeProperty<LineType> {
* if (!this.connetionStyleModel)
* @returns model to get and set topic shape this.connetionStyleModel = {
*/ getValue: () => this.selectedTopic()?.getConnectionStyle(),
getTopicShapeModel(): NodeProperty<string> { setValue: (value: LineType) => this.designer.changeConnectionStyle(value),
};
return this.connetionStyleModel;
}
getTopicShapeModel(): NodeProperty<TopicShapeType> {
if (!this.topicShapeModel) if (!this.topicShapeModel)
this.topicShapeModel = { this.topicShapeModel = {
getValue: () => this.uniqueOrNull((node) => node.getShapeType()), getValue: () => this.uniqueOrNull((node) => node.getShapeType()) as TopicShapeType,
setValue: (value: string) => this.designer.changeTopicShape(value), setValue: (value: TopicShapeType) => this.designer.changeTopicShape(value),
}; };
return this.topicShapeModel; return this.topicShapeModel;
} }

View File

@ -32,6 +32,10 @@ import CheckBoxOutlineBlankOutlinedIcon from '@mui/icons-material/CheckBoxOutlin
import HorizontalRuleOutlinedIcon from '@mui/icons-material/HorizontalRuleOutlined'; import HorizontalRuleOutlinedIcon from '@mui/icons-material/HorizontalRuleOutlined';
import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline';
import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined'; import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined';
import ShapeLineOutlined from '@mui/icons-material/ShapeLineOutlined';
import PolylineOutlined from '@mui/icons-material/PolylineOutlined';
import GestureOutlined from '@mui/icons-material/GestureOutlined';
import TimelineOutined from '@mui/icons-material/TimelineOutlined';
import Palette from '@mui/icons-material/Square'; import Palette from '@mui/icons-material/Square';
import SquareOutlined from '@mui/icons-material/SquareOutlined'; import SquareOutlined from '@mui/icons-material/SquareOutlined';
@ -45,6 +49,7 @@ import IconPicker from '../action-widget/pane/icon-picker';
import FontFamilySelector from '../action-widget/button/font-family-selector'; import FontFamilySelector from '../action-widget/button/font-family-selector';
import Editor from '../../classes/model/editor'; import Editor from '../../classes/model/editor';
import { IntlShape } from 'react-intl'; import { IntlShape } from 'react-intl';
import { LineType } from '@wisemapping/mindplot/src/components/ConnectionLine';
const keyTooltip = (msg: string, key: string): string => { const keyTooltip = (msg: string, key: string): string => {
const isMac = window.navigator.platform.toUpperCase().indexOf('MAC') >= 0; const isMac = window.navigator.platform.toUpperCase().indexOf('MAC') >= 0;
@ -52,7 +57,7 @@ const keyTooltip = (msg: string, key: string): string => {
}; };
export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionConfig[] { export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionConfig[] {
const toolbarValueModelBuilder = new NodePropertyValueModelBuilder(model.getDesigner()); const valueBulder = new NodePropertyValueModelBuilder(model.getDesigner());
// eslint-disable-next-line react-hooks/rules-of-hooks // eslint-disable-next-line react-hooks/rules-of-hooks
const colorAndShapeToolbarConfiguration: ActionConfig = { const colorAndShapeToolbarConfiguration: ActionConfig = {
icon: <BrushOutlinedIcon />, icon: <BrushOutlinedIcon />,
@ -67,8 +72,8 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
id: 'editor-panel.tooltip-topic-share-rectangle', id: 'editor-panel.tooltip-topic-share-rectangle',
defaultMessage: 'Rectangle shape', defaultMessage: 'Rectangle shape',
}), }),
onClick: () => toolbarValueModelBuilder.getTopicShapeModel().setValue('rectangle'), onClick: () => valueBulder.getTopicShapeModel().setValue('rectangle'),
selected: () => toolbarValueModelBuilder.getTopicShapeModel().getValue() === 'rectangle', selected: () => valueBulder.getTopicShapeModel().getValue() === 'rectangle',
}, },
{ {
icon: <CheckBoxOutlineBlankOutlinedIcon />, icon: <CheckBoxOutlineBlankOutlinedIcon />,
@ -76,9 +81,8 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
id: 'editor-panel.tooltip-topic-share-rounded', id: 'editor-panel.tooltip-topic-share-rounded',
defaultMessage: 'Rounded shape', defaultMessage: 'Rounded shape',
}), }),
onClick: () => toolbarValueModelBuilder.getTopicShapeModel().setValue('rounded rectangle'), onClick: () => valueBulder.getTopicShapeModel().setValue('rounded rectangle'),
selected: () => selected: () => valueBulder.getTopicShapeModel().getValue() === 'rounded rectangle',
toolbarValueModelBuilder.getTopicShapeModel().getValue() === 'rounded rectangle',
}, },
{ {
icon: <HorizontalRuleOutlinedIcon />, icon: <HorizontalRuleOutlinedIcon />,
@ -86,8 +90,8 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
id: 'editor-panel.tooltip-topic-share-line', id: 'editor-panel.tooltip-topic-share-line',
defaultMessage: 'Line shape', defaultMessage: 'Line shape',
}), }),
onClick: () => toolbarValueModelBuilder.getTopicShapeModel().setValue('line'), onClick: () => valueBulder.getTopicShapeModel().setValue('line'),
selected: () => toolbarValueModelBuilder.getTopicShapeModel().getValue() === 'line', selected: () => valueBulder.getTopicShapeModel().getValue() === 'line',
}, },
{ {
icon: <CircleOutlinedIcon />, icon: <CircleOutlinedIcon />,
@ -95,14 +99,14 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
id: 'editor-panel.tooltip-topic-share-ellipse', id: 'editor-panel.tooltip-topic-share-ellipse',
defaultMessage: 'Ellipse shape', defaultMessage: 'Ellipse shape',
}), }),
onClick: () => toolbarValueModelBuilder.getTopicShapeModel().setValue('elipse'), onClick: () => valueBulder.getTopicShapeModel().setValue('elipse'),
selected: () => toolbarValueModelBuilder.getTopicShapeModel().getValue() === 'elipse', selected: () => valueBulder.getTopicShapeModel().getValue() === 'elipse',
}, },
null, null,
{ {
icon: () => ( icon: () => (
<Palette <Palette
htmlColor={toolbarValueModelBuilder.getSelectedTopicColorModel().getValue() as string} htmlColor={valueBulder.getSelectedTopicColorModel().getValue() as string}
></Palette> ></Palette>
), ),
tooltip: intl.formatMessage({ tooltip: intl.formatMessage({
@ -115,7 +119,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
return ( return (
<ColorPicker <ColorPicker
closeModal={closeModal} closeModal={closeModal}
colorModel={toolbarValueModelBuilder.getSelectedTopicColorModel()} colorModel={valueBulder.getSelectedTopicColorModel()}
></ColorPicker> ></ColorPicker>
); );
}, },
@ -124,9 +128,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
}, },
{ {
icon: () => ( icon: () => (
<SquareOutlined <SquareOutlined htmlColor={valueBulder.getColorBorderModel().getValue() as string} />
htmlColor={toolbarValueModelBuilder.getColorBorderModel().getValue() as string}
></SquareOutlined>
), ),
tooltip: intl.formatMessage({ tooltip: intl.formatMessage({
id: 'editor-panel.tooltip-topic-border-color', id: 'editor-panel.tooltip-topic-border-color',
@ -138,7 +140,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
return ( return (
<ColorPicker <ColorPicker
closeModal={closeModal} closeModal={closeModal}
colorModel={toolbarValueModelBuilder.getColorBorderModel()} colorModel={valueBulder.getColorBorderModel()}
></ColorPicker> ></ColorPicker>
); );
}, },
@ -149,6 +151,46 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0, disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
}; };
const connectionStyleConfiguration: ActionConfig = {
icon: <ShapeLineOutlined />,
tooltip: intl.formatMessage({
id: 'editor-panel.tooltip-connection-style',
defaultMessage: 'Connection Style',
}),
options: [
{
icon: <PolylineOutlined />,
tooltip: intl.formatMessage({
id: 'editor-panel.tooltip-connection-style-polyline',
defaultMessage: 'Polyline',
}),
onClick: () => valueBulder.getConnectionStyleModel().setValue(LineType.POLYLINE_MIDDLE),
selected: () =>
valueBulder.getConnectionStyleModel().getValue() === LineType.POLYLINE_MIDDLE,
},
{
icon: <TimelineOutined />,
tooltip: intl.formatMessage({
id: 'editor-panel.tooltip-connection-style-polyline-curved',
defaultMessage: 'Polyline Curved',
}),
onClick: () => valueBulder.getConnectionStyleModel().setValue(LineType.POLYLINE_CURVED),
selected: () =>
valueBulder.getConnectionStyleModel().getValue() === LineType.POLYLINE_CURVED,
},
{
icon: <GestureOutlined />,
tooltip: intl.formatMessage({
id: 'editor-panel.tooltip-connection-style-curved',
defaultMessage: 'Curved',
}),
onClick: () => valueBulder.getConnectionStyleModel().setValue(LineType.SIMPLE_CURVED),
selected: () => valueBulder.getConnectionStyleModel().getValue() === LineType.SIMPLE_CURVED,
},
],
disabled: () => model.getDesignerModel().filterSelectedTopics().length === 0,
};
/** /**
* submenu to manipulate node font * submenu to manipulate node font
*/ */
@ -160,9 +202,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
}), }),
options: [ options: [
{ {
render: () => ( render: () => <FontFamilySelector fontFamilyModel={valueBulder.getFontFamilyModel()} />,
<FontFamilySelector fontFamilyModel={toolbarValueModelBuilder.getFontFamilyModel()} />
),
}, },
null, null,
{ {
@ -171,8 +211,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
id: 'editor-panel.tooltip-topic-font-bigger', id: 'editor-panel.tooltip-topic-font-bigger',
defaultMessage: 'Bigger', defaultMessage: 'Bigger',
}), }),
onClick: () => onClick: () => valueBulder.getFontSizeModel().switchValue(SwitchValueDirection.up),
toolbarValueModelBuilder.getFontSizeModel().switchValue(SwitchValueDirection.up),
}, },
{ {
icon: <TextDecreaseOutlinedIcon></TextDecreaseOutlinedIcon>, icon: <TextDecreaseOutlinedIcon></TextDecreaseOutlinedIcon>,
@ -180,8 +219,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
id: 'editor-panel.tooltip-topic-font-smaller', id: 'editor-panel.tooltip-topic-font-smaller',
defaultMessage: 'Smaller', defaultMessage: 'Smaller',
}), }),
onClick: () => onClick: () => valueBulder.getFontSizeModel().switchValue(SwitchValueDirection.down),
toolbarValueModelBuilder.getFontSizeModel().switchValue(SwitchValueDirection.down),
}, },
null, null,
{ {
@ -193,8 +231,8 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
}), }),
'B', 'B',
), ),
onClick: toolbarValueModelBuilder.fontWeigthModel().switchValue, onClick: valueBulder.fontWeigthModel().switchValue,
selected: () => toolbarValueModelBuilder.fontWeigthModel().getValue() === 'bold', selected: () => valueBulder.fontWeigthModel().getValue() === 'bold',
}, },
{ {
icon: <FormatItalicIcon />, icon: <FormatItalicIcon />,
@ -205,13 +243,11 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
}), }),
'I', 'I',
), ),
onClick: toolbarValueModelBuilder.getFontStyleModel().switchValue, onClick: valueBulder.getFontStyleModel().switchValue,
selected: () => toolbarValueModelBuilder.getFontStyleModel().getValue() === 'italic', selected: () => valueBulder.getFontStyleModel().getValue() === 'italic',
}, },
{ {
icon: () => ( icon: () => <Palette htmlColor={valueBulder.getFontColorModel().getValue() as string} />,
<Palette htmlColor={toolbarValueModelBuilder.getFontColorModel().getValue() as string} />
),
tooltip: intl.formatMessage({ tooltip: intl.formatMessage({
id: 'editor-panel.tooltip-topic-font-color', id: 'editor-panel.tooltip-topic-font-color',
defaultMessage: 'Color', defaultMessage: 'Color',
@ -222,7 +258,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
return ( return (
<ColorPicker <ColorPicker
closeModal={closeModal} closeModal={closeModal}
colorModel={toolbarValueModelBuilder.getFontColorModel()} colorModel={valueBulder.getFontColorModel()}
></ColorPicker> ></ColorPicker>
); );
}, },
@ -261,10 +297,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
options: [ options: [
{ {
render: (closeModal) => ( render: (closeModal) => (
<TopicLink <TopicLink closeModal={closeModal} urlModel={valueBulder.getLinkModel()}></TopicLink>
closeModal={closeModal}
urlModel={toolbarValueModelBuilder.getLinkModel()}
></TopicLink>
), ),
}, },
], ],
@ -285,10 +318,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
{ {
tooltip: 'Node note', tooltip: 'Node note',
render: (closeModal) => ( render: (closeModal) => (
<TopicNote <TopicNote closeModal={closeModal} noteModel={valueBulder.getNoteModel()}></TopicNote>
closeModal={closeModal}
noteModel={toolbarValueModelBuilder.getNoteModel()}
></TopicNote>
), ),
}, },
], ],
@ -312,10 +342,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
defaultMessage: 'Add Icon', defaultMessage: 'Add Icon',
}), }),
render: (closeModal) => ( render: (closeModal) => (
<IconPicker <IconPicker triggerClose={closeModal} iconModel={valueBulder.getTopicIconModel()} />
triggerClose={closeModal}
iconModel={toolbarValueModelBuilder.getTopicIconModel()}
/>
), ),
}, },
], ],
@ -350,6 +377,7 @@ export function buildEditorPanelConfig(model: Editor, intl: IntlShape): ActionCo
editIconConfiguration, editIconConfiguration,
editNoteConfiguration, editNoteConfiguration,
editLinkUrlConfiguration, editLinkUrlConfiguration,
connectionStyleConfiguration,
addRelationConfiguration, addRelationConfiguration,
]; ];
} }

View File

@ -25,10 +25,9 @@ import Workspace from './Workspace';
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
export enum LineType { export enum LineType {
SIMPLE,
POLYLINE,
CURVED,
SIMPLE_CURVED, SIMPLE_CURVED,
POLYLINE_MIDDLE,
POLYLINE_CURVED,
} }
class ConnectionLine { class ConnectionLine {
@ -52,11 +51,18 @@ class ConnectionLine {
const line = this._createLine(type); const line = this._createLine(type);
const strokeColor = ConnectionLine.getStrokeColor(); const strokeColor = ConnectionLine.getStrokeColor();
if (type === LineType.SIMPLE_CURVED) {
line.setStroke(1, 'solid', strokeColor, 1); switch (type) {
line.setFill(strokeColor, 1); case LineType.POLYLINE_MIDDLE:
} else { case LineType.POLYLINE_CURVED:
line.setStroke(2, 'solid', strokeColor, 1); line.setStroke(1, 'solid', strokeColor, 1);
break;
case LineType.SIMPLE_CURVED:
line.setStroke(1, 'solid', strokeColor, 1);
line.setFill(strokeColor, 2);
break;
default:
line.setStroke(2, 'solid', strokeColor, 1);
} }
// Set line styles ... // Set line styles ...
@ -77,19 +83,18 @@ class ConnectionLine {
this._lineType = lineType; this._lineType = lineType;
let line: ConnectionLine; let line: ConnectionLine;
switch (lineType) { switch (lineType) {
case LineType.POLYLINE: case LineType.POLYLINE_MIDDLE:
line = new PolyLine(); line = new PolyLine();
(line as PolyLine).setStyle('MiddleStraight');
break; break;
case LineType.CURVED: case LineType.POLYLINE_CURVED:
line = new CurvedLine(); line = new PolyLine();
(line as PolyLine).setStyle('Curved');
break; break;
case LineType.SIMPLE_CURVED: case LineType.SIMPLE_CURVED:
line = new CurvedLine(); line = new CurvedLine();
(line as CurvedLine).setStyle(CurvedLine.SIMPLE_LINE); (line as CurvedLine).setStyle(CurvedLine.SIMPLE_LINE);
break; break;
case LineType.SIMPLE:
line = new Line();
break;
default: default:
throw new Error(`Unexpected line type. ${lineType}`); throw new Error(`Unexpected line type. ${lineType}`);
} }

View File

@ -56,6 +56,8 @@ import DragTopic from './DragTopic';
import CentralTopic from './CentralTopic'; import CentralTopic from './CentralTopic';
import FeatureType from './model/FeatureType'; import FeatureType from './model/FeatureType';
import WidgetManager from './WidgetManager'; import WidgetManager from './WidgetManager';
import { TopicShapeType } from './model/INodeModel';
import { LineType } from './ConnectionLine';
class Designer extends Events { class Designer extends Events {
private _mindmap: Mindmap; private _mindmap: Mindmap;
@ -480,6 +482,11 @@ class Designer extends Events {
if (backgroundColor) { if (backgroundColor) {
targetModel.setBackgroundColor(backgroundColor); targetModel.setBackgroundColor(backgroundColor);
} }
const connectType = sourceModel.getConnectionStyle();
if ($defined(connectType)) {
targetModel.setConnectionStyle(connectType!);
}
} }
private _createChildModel(topic: Topic, mousePos: Point = null): NodeModel { private _createChildModel(topic: Topic, mousePos: Point = null): NodeModel {
@ -860,7 +867,7 @@ class Designer extends Events {
} }
} }
changeTopicShape(shape: string) { changeTopicShape(shape: TopicShapeType): void {
const validateFunc = (topic: Topic) => const validateFunc = (topic: Topic) =>
!(topic.getType() === 'CentralTopic' && shape === 'line'); !(topic.getType() === 'CentralTopic' && shape === 'line');
@ -871,6 +878,16 @@ class Designer extends Events {
} }
} }
changeConnectionStyle(type: LineType): void {
const validateFunc = (topic: Topic) => !topic.isCentralTopic();
const validateError = 'Central Topic can not be changed to line figure.';
const topicsIds = this.getModel().filterTopicsIds(validateFunc, validateError);
if (topicsIds.length > 0) {
this._actionDispatcher.changeConnectionStyleToTopic(topicsIds, type);
}
}
changeFontWeight(): void { changeFontWeight(): void {
const topicsIds = this.getModel().filterTopicsIds(); const topicsIds = this.getModel().filterTopicsIds();
if (topicsIds.length > 0) { if (topicsIds.length > 0) {

View File

@ -38,6 +38,7 @@ import FeatureType from './model/FeatureType';
import PositionType from './PositionType'; import PositionType from './PositionType';
import { PivotType } from './RelationshipControlPoints'; import { PivotType } from './RelationshipControlPoints';
import { TopicShapeType } from './model/INodeModel'; import { TopicShapeType } from './model/INodeModel';
import { LineType } from './ConnectionLine';
class StandaloneActionDispatcher extends ActionDispatcher { class StandaloneActionDispatcher extends ActionDispatcher {
private _actionRunner: DesignerActionRunner; private _actionRunner: DesignerActionRunner;
@ -136,7 +137,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
const result = topic.getFontFamily(); const result = topic.getFontFamily();
topic.setFontFamily(commandFontFamily, true); topic.setFontFamily(commandFontFamily, true);
topic.adjustShapes(); topic.redraw();
return result; return result;
}; };
@ -201,7 +202,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
const result = topic.getFontSize(); const result = topic.getFontSize();
topic.setFontSize(commandSize, true); topic.setFontSize(commandSize, true);
topic.adjustShapes(); topic.redraw();
return result; return result;
}; };
@ -209,14 +210,13 @@ class StandaloneActionDispatcher extends ActionDispatcher {
this.execute(command); this.execute(command);
} }
/** */ changeShapeTypeToTopic(topicsIds: number[], shapeType: TopicShapeType) {
changeShapeTypeToTopic(topicsIds: number[], shapeType: string) {
$assert(topicsIds, 'topicsIds can not be null'); $assert(topicsIds, 'topicsIds can not be null');
$assert(shapeType, 'shapeType can not be null'); $assert(shapeType, 'shapeType can not be null');
const commandFunc = (topic: Topic, commandShapeType: string) => { const commandFunc = (topic: Topic, commandShapeType: TopicShapeType) => {
const result = topic.getShapeType(); const result = topic.getShapeType();
topic.setShapeType(commandShapeType as TopicShapeType); topic.setShapeType(commandShapeType);
return result; return result;
}; };
@ -224,7 +224,17 @@ class StandaloneActionDispatcher extends ActionDispatcher {
this.execute(command); this.execute(command);
} }
/** */ changeConnectionStyleToTopic(topicsIds: number[], lineType: LineType) {
const commandFunc = (topic: Topic, commandShapeType: LineType) => {
const result = topic.getConnectionStyle();
topic.setConnectionStyle(commandShapeType);
return result;
};
const command = new GenericFunctionCommand(commandFunc, topicsIds, lineType);
this.execute(command);
}
changeFontWeightToTopic(topicsIds: number[]) { changeFontWeightToTopic(topicsIds: number[]) {
$assert(topicsIds, 'topicsIds can not be null'); $assert(topicsIds, 'topicsIds can not be null');
@ -232,8 +242,7 @@ class StandaloneActionDispatcher extends ActionDispatcher {
const result = topic.getFontWeight(); const result = topic.getFontWeight();
const weight = result === 'bold' ? 'normal' : 'bold'; const weight = result === 'bold' ? 'normal' : 'bold';
topic.setFontWeight(weight, true); topic.setFontWeight(weight, true);
topic.redraw();
topic.adjustShapes();
return result; return result;
}; };

View File

@ -23,7 +23,7 @@ import NodeGraph from './NodeGraph';
import TopicConfig from './TopicConfig'; import TopicConfig from './TopicConfig';
import TopicStyle from './TopicStyle'; import TopicStyle from './TopicStyle';
import TopicFeatureFactory from './TopicFeature'; import TopicFeatureFactory from './TopicFeature';
import ConnectionLine from './ConnectionLine'; import ConnectionLine, { LineType } from './ConnectionLine';
import IconGroup from './IconGroup'; import IconGroup from './IconGroup';
import EventBus from './layout/EventBus'; import EventBus from './layout/EventBus';
import ShirinkConnector from './ShrinkConnector'; import ShirinkConnector from './ShrinkConnector';
@ -64,7 +64,7 @@ abstract class Topic extends NodeGraph {
private _connector: ShirinkConnector; private _connector: ShirinkConnector;
private _outgoingLine: Line; private _outgoingLine: ConnectionLine | null;
constructor(model: NodeModel, options) { constructor(model: NodeModel, options) {
super(model, options); super(model, options);
@ -140,7 +140,7 @@ abstract class Topic extends NodeGraph {
// Move iconGroup to front ... // Move iconGroup to front ...
const iconGroup = this.getIconGroup(); const iconGroup = this.getIconGroup();
if ($defined(iconGroup)) { if (iconGroup) {
iconGroup.moveToFront(); iconGroup.moveToFront();
} }
@ -161,6 +161,15 @@ abstract class Topic extends NodeGraph {
return result; return result;
} }
getConnectionStyle(): LineType {
const model = this.getModel();
let result = model.getConnectionStyle();
if (!result) {
result = TopicStyle.defaultConnectionType(this);
}
return result;
}
private _removeInnerShape(): ElementClass { private _removeInnerShape(): ElementClass {
const group = this.get2DElement(); const group = this.get2DElement();
const innerShape = this.getInnerShape(); const innerShape = this.getInnerShape();
@ -192,7 +201,7 @@ abstract class Topic extends NodeGraph {
return this._innerShape; return this._innerShape;
} }
_buildShape(attributes, shapeType: TopicShapeType): ElementClass { protected _buildShape(attributes, shapeType: TopicShapeType): ElementClass {
$assert(attributes, 'attributes can not be null'); $assert(attributes, 'attributes can not be null');
$assert(shapeType, 'shapeType can not be null'); $assert(shapeType, 'shapeType can not be null');
@ -346,7 +355,7 @@ abstract class Topic extends NodeGraph {
featureModel.getType() === TopicFeatureFactory.EmojiIcon.id; featureModel.getType() === TopicFeatureFactory.EmojiIcon.id;
iconGroup.addIcon(result, isIcon && !this.isReadOnly()); iconGroup.addIcon(result, isIcon && !this.isReadOnly());
this.adjustShapes(); this.redraw();
return result; return result;
} }
@ -368,7 +377,7 @@ abstract class Topic extends NodeGraph {
if ($defined(iconGroup)) { if ($defined(iconGroup)) {
iconGroup.removeIconByModel(featureModel); iconGroup.removeIconByModel(featureModel);
} }
this.adjustShapes(); this.redraw();
} }
addRelationship(relationship: Relationship) { addRelationship(relationship: Relationship) {
@ -414,7 +423,7 @@ abstract class Topic extends NodeGraph {
const model = this.getModel(); const model = this.getModel();
model.setFontFamily(value); model.setFontFamily(value);
} }
this.adjustShapes(); this.redraw();
} }
setFontSize(value: number, updateModel?: boolean) { setFontSize(value: number, updateModel?: boolean) {
@ -425,7 +434,7 @@ abstract class Topic extends NodeGraph {
const model = this.getModel(); const model = this.getModel();
model.setFontSize(value); model.setFontSize(value);
} }
this.adjustShapes(); this.redraw();
} }
setFontStyle(value: string, updateModel?: boolean) { setFontStyle(value: string, updateModel?: boolean) {
@ -435,7 +444,7 @@ abstract class Topic extends NodeGraph {
const model = this.getModel(); const model = this.getModel();
model.setFontStyle(value); model.setFontStyle(value);
} }
this.adjustShapes(); this.redraw();
} }
setFontWeight(value: string, updateModel?: boolean) { setFontWeight(value: string, updateModel?: boolean) {
@ -445,7 +454,7 @@ abstract class Topic extends NodeGraph {
const model = this.getModel(); const model = this.getModel();
model.setFontWeight(value); model.setFontWeight(value);
} }
this.adjustShapes(); this.redraw();
} }
getFontWeight() { getFontWeight() {
@ -525,7 +534,7 @@ abstract class Topic extends NodeGraph {
this._setText(text, true); this._setText(text, true);
} }
this.adjustShapes(); this.redraw();
} }
getText(): string { getText(): string {
@ -538,6 +547,13 @@ abstract class Topic extends NodeGraph {
this._setBackgroundColor(color, true); this._setBackgroundColor(color, true);
} }
setConnectionStyle(type: LineType): void {
this.getModel().setConnectionStyle(type);
// Needs to change change all the lines types. Outgoing are part of the children.
this.getChildren().map((topic: Topic) => topic.redraw());
}
private _setBackgroundColor(color: string, updateModel: boolean) { private _setBackgroundColor(color: string, updateModel: boolean) {
const innerShape = this.getInnerShape(); const innerShape = this.getInnerShape();
innerShape.setFill(color); innerShape.setFill(color);
@ -857,7 +873,7 @@ abstract class Topic extends NodeGraph {
private _updateConnectionLines(): void { private _updateConnectionLines(): void {
// Update this to parent line ... // Update this to parent line ...
const outgoingLine = this.getOutgoingLine(); const outgoingLine = this.getOutgoingLine();
if ($defined(outgoingLine)) { if (outgoingLine) {
outgoingLine.redraw(); outgoingLine.redraw();
} }
@ -880,13 +896,13 @@ abstract class Topic extends NodeGraph {
} }
setVisibility(value: boolean, fade = 0): void { setVisibility(value: boolean, fade = 0): void {
this._setTopicVisibility(value, fade); this.setTopicVisibility(value, fade);
// Hide all children... // Hide all children...
this._setChildrenVisibility(value, fade); this._setChildrenVisibility(value, fade);
// If there there are connection to the node, topic must be hidden. // If there there are connection to the node, topic must be hidden.
this._setRelationshipLinesVisibility(value, fade); this.setRelationshipLinesVisibility(value, fade);
// If it's connected, the connection must be rendered. // If it's connected, the connection must be rendered.
const outgoingLine = this.getOutgoingLine(); const outgoingLine = this.getOutgoingLine();
@ -895,8 +911,7 @@ abstract class Topic extends NodeGraph {
} }
} }
/** */ protected moveToBack(): void {
moveToBack(): void {
// Update relationship lines // Update relationship lines
this._relationships.forEach((r) => r.moveToBack()); this._relationships.forEach((r) => r.moveToBack());
@ -908,8 +923,7 @@ abstract class Topic extends NodeGraph {
this.get2DElement().moveToBack(); this.get2DElement().moveToBack();
} }
/** */ protected moveToFront(): void {
moveToFront(): void {
this.get2DElement().moveToFront(); this.get2DElement().moveToFront();
const connector = this.getShrinkConnector(); const connector = this.getShrinkConnector();
if (connector) { if (connector) {
@ -919,13 +933,12 @@ abstract class Topic extends NodeGraph {
this._relationships.forEach((r) => r.moveToFront()); this._relationships.forEach((r) => r.moveToFront());
} }
/** */
isVisible(): boolean { isVisible(): boolean {
const elem = this.get2DElement(); const elem = this.get2DElement();
return elem.isVisible(); return elem.isVisible();
} }
private _setRelationshipLinesVisibility(value: boolean, fade = 0): void { private setRelationshipLinesVisibility(value: boolean, fade = 0): void {
this._relationships.forEach((relationship) => { this._relationships.forEach((relationship) => {
const sourceTopic = relationship.getSourceTopic(); const sourceTopic = relationship.getSourceTopic();
const targetTopic = relationship.getTargetTopic(); const targetTopic = relationship.getTargetTopic();
@ -941,7 +954,7 @@ abstract class Topic extends NodeGraph {
}); });
} }
private _setTopicVisibility(value: boolean, fade = 0) { private setTopicVisibility(value: boolean, fade = 0) {
const elem = this.get2DElement(); const elem = this.get2DElement();
elem.setVisibility(value, fade); elem.setVisibility(value, fade);
@ -960,7 +973,6 @@ abstract class Topic extends NodeGraph {
textShape.setVisibility(this.getShapeType() !== 'image' ? value : false, fade); textShape.setVisibility(this.getShapeType() !== 'image' ? value : false, fade);
} }
/** */
setOpacity(opacity: number): void { setOpacity(opacity: number): void {
const elem = this.get2DElement(); const elem = this.get2DElement();
elem.setOpacity(opacity); elem.setOpacity(opacity);
@ -1088,7 +1100,6 @@ abstract class Topic extends NodeGraph {
model.setOrder(value); model.setOrder(value);
} }
/** */
connectTo(targetTopic: Topic, workspace: Workspace) { connectTo(targetTopic: Topic, workspace: Workspace) {
$assert(!this._outgoingLine, 'Could not connect an already connected node'); $assert(!this._outgoingLine, 'Could not connect an already connected node');
$assert(targetTopic !== this, 'Circular connection are not allowed'); $assert(targetTopic !== this, 'Circular connection are not allowed');
@ -1105,7 +1116,7 @@ abstract class Topic extends NodeGraph {
childModel.connectTo(targetModel); childModel.connectTo(targetModel);
// Create a connection line ... // Create a connection line ...
const outgoingLine = new ConnectionLine(this, targetTopic); const outgoingLine = this.createConnectionLine(targetTopic);
outgoingLine.setVisibility(false); outgoingLine.setVisibility(false);
this._outgoingLine = outgoingLine; this._outgoingLine = outgoingLine;
@ -1144,7 +1155,13 @@ abstract class Topic extends NodeGraph {
} }
} }
abstract updateTopicShape(targetTopic: Topic); private createConnectionLine(targetTopic: Topic): ConnectionLine {
const type: LineType = targetTopic.getConnectionStyle();
console.log(`redraw ...: ${type}`);
return new ConnectionLine(this, targetTopic, type);
}
abstract updateTopicShape(targetTopic: Topic): void;
append(child: Topic): void { append(child: Topic): void {
const children = this.getChildren(); const children = this.getChildren();
@ -1195,7 +1212,7 @@ abstract class Topic extends NodeGraph {
} }
} }
this._isInWorkspace = true; this._isInWorkspace = true;
this.adjustShapes(); this.redraw();
} }
/** */ /** */
@ -1220,7 +1237,29 @@ abstract class Topic extends NodeGraph {
return result; return result;
} }
adjustShapes(): void { private redrawConnection(): boolean {
let result = false;
if (this._isInWorkspace) {
// Adjust connection line if there is a change in the parent...
const connStyleChanged =
this._outgoingLine?.getLineType() !== this.getParent()?.getConnectionStyle();
if (this._outgoingLine && connStyleChanged) {
// Todo: Review static reference ...
const workspace = designer.getWorkSpace();
this._outgoingLine.removeFromWorkspace(workspace);
const targetTopic = this.getOutgoingConnectedTopic()!;
this._outgoingLine = this.createConnectionLine(targetTopic);
this._outgoingLine.setVisibility(this.isVisible());
workspace.append(this._outgoingLine);
result = true;
}
}
return result;
}
redraw(): void {
if (this._isInWorkspace) { if (this._isInWorkspace) {
const textShape = this.getTextShape(); const textShape = this.getTextShape();
if (this.getShapeType() !== 'image') { if (this.getShapeType() !== 'image') {
@ -1241,13 +1280,9 @@ abstract class Topic extends NodeGraph {
const iconGroupWith = iconGroup.getSize().width; const iconGroupWith = iconGroup.getSize().width;
const topicWith = iconGroupWith + 2 * textIconSpacing + textWidth + padding * 2; const topicWith = iconGroupWith + 2 * textIconSpacing + textWidth + padding * 2;
this.setSize( // Update connections ...
{ const changed = this.redrawConnection();
width: topicWith, this.setSize({ width: topicWith, height: topicHeight }, changed);
height: topicHeight,
},
false,
);
// Adjust all topic elements positions ... // Adjust all topic elements positions ...
const yPosition = Math.round((topicHeight - textHeight) / 2); const yPosition = Math.round((topicHeight - textHeight) / 2);

View File

@ -16,20 +16,23 @@
* limitations under the License. * limitations under the License.
*/ */
import { $assert } from '@wisemapping/core-js'; import { $assert } from '@wisemapping/core-js';
import { LineType } from './ConnectionLine';
import { $msg } from './Messages'; import { $msg } from './Messages';
import { TopicShapeType } from './model/INodeModel'; import { TopicShapeType } from './model/INodeModel';
import Topic from './Topic'; import Topic from './Topic';
type FontStlye = {
font: string;
size: number;
style: string;
weight: string;
color: string;
};
type TopicStyleType = { type TopicStyleType = {
borderColor: string; borderColor: string;
backgroundColor: string; backgroundColor: string;
fontStyle: { connectionStyle: LineType;
font: string; fontStyle: FontStlye;
size: number;
style: string;
weight: string;
color: string;
};
msgKey: string; msgKey: string;
shapeType: TopicShapeType; shapeType: TopicShapeType;
}; };
@ -45,6 +48,7 @@ const TopicDefaultStyles = {
weight: 'bold', weight: 'bold',
color: '#ffffff', color: '#ffffff',
}, },
connectionStyle: LineType.SIMPLE_CURVED,
msgKey: 'CENTRAL_TOPIC', msgKey: 'CENTRAL_TOPIC',
shapeType: 'rounded rectangle' as TopicShapeType, shapeType: 'rounded rectangle' as TopicShapeType,
}, },
@ -58,6 +62,7 @@ const TopicDefaultStyles = {
weight: 'normal', weight: 'normal',
color: 'rgb(82,92,97)', color: 'rgb(82,92,97)',
}, },
connectionStyle: LineType.SIMPLE_CURVED,
msgKey: 'MAIN_TOPIC', msgKey: 'MAIN_TOPIC',
shapeType: 'line' as TopicShapeType, shapeType: 'line' as TopicShapeType,
}, },
@ -71,6 +76,7 @@ const TopicDefaultStyles = {
weight: 'normal', weight: 'normal',
color: 'rgb(82,92,97)', color: 'rgb(82,92,97)',
}, },
connectionStyle: LineType.SIMPLE_CURVED,
msgKey: 'SUB_TOPIC', msgKey: 'SUB_TOPIC',
shapeType: 'line' as TopicShapeType, shapeType: 'line' as TopicShapeType,
}, },
@ -86,6 +92,7 @@ const TopicDefaultStyles = {
color: 'rgb(82,92,97)', color: 'rgb(82,92,97)',
}, },
msgKey: 'ISOLATED_TOPIC', msgKey: 'ISOLATED_TOPIC',
connectionStyle: LineType.SIMPLE_CURVED,
shapeType: 'line' as TopicShapeType, shapeType: 'line' as TopicShapeType,
}, },
}; };
@ -112,30 +119,34 @@ class TopicStyle {
return result; return result;
} }
static defaultText(topic: Topic) { static defaultText(topic: Topic): string {
const { msgKey } = this._getStyles(topic); const { msgKey } = this._getStyles(topic);
return $msg(msgKey); return $msg(msgKey);
} }
static defaultFontStyle(topic: Topic) { static defaultFontStyle(topic: Topic): FontStlye {
return this._getStyles(topic).fontStyle; return this._getStyles(topic).fontStyle;
} }
static defaultBackgroundColor(topic: Topic) { static defaultBackgroundColor(topic: Topic): string {
return this._getStyles(topic).backgroundColor; return this._getStyles(topic).backgroundColor;
} }
static defaultBorderColor(topic: Topic) { static defaultBorderColor(topic: Topic): string {
return this._getStyles(topic).borderColor; return this._getStyles(topic).borderColor;
} }
static getInnerPadding(topic: Topic) { static getInnerPadding(topic: Topic): number {
return Math.round(topic.getTextShape().getFontHeight() * 0.5); return Math.round(topic.getTextShape().getFontHeight() * 0.5);
} }
static defaultShapeType(topic: Topic) { static defaultShapeType(topic: Topic): TopicShapeType {
return this._getStyles(topic).shapeType; return this._getStyles(topic).shapeType;
} }
static defaultConnectionType(topic: Topic): LineType {
return this._getStyles(topic).connectionStyle;
}
} }
export default TopicStyle; export default TopicStyle;

View File

@ -17,6 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { $assert, $defined } from '@wisemapping/core-js'; import { $assert, $defined } from '@wisemapping/core-js';
import { LineType } from '../ConnectionLine';
import PositionType from '../PositionType'; import PositionType from '../PositionType';
import FeatureModel from './FeatureModel'; import FeatureModel from './FeatureModel';
import Mindmap from './Mindmap'; import Mindmap from './Mindmap';
@ -132,12 +133,10 @@ abstract class INodeModel {
mindmap.disconnect(this); mindmap.disconnect(this);
} }
/** */
getShapeType(): TopicShapeType { getShapeType(): TopicShapeType {
return this.getProperty('shapeType') as TopicShapeType; return this.getProperty('shapeType') as TopicShapeType;
} }
/** */
setShapeType(type: string) { setShapeType(type: string) {
this.putProperty('shapeType', type); this.putProperty('shapeType', type);
} }
@ -162,7 +161,6 @@ abstract class INodeModel {
return this.getProperty('fontFamily') as string; return this.getProperty('fontFamily') as string;
} }
/** */
setFontStyle(fontStyle: string) { setFontStyle(fontStyle: string) {
this.putProperty('fontStyle', fontStyle); this.putProperty('fontStyle', fontStyle);
} }
@ -179,7 +177,7 @@ abstract class INodeModel {
return this.getProperty('fontWeight'); return this.getProperty('fontWeight');
} }
setFontColor(color: string) { setFontColor(color: string): void {
this.putProperty('fontColor', color); this.putProperty('fontColor', color);
} }
@ -187,7 +185,7 @@ abstract class INodeModel {
return this.getProperty('fontColor') as string; return this.getProperty('fontColor') as string;
} }
setFontSize(size: number) { setFontSize(size: number): void {
this.putProperty('fontSize', size); this.putProperty('fontSize', size);
} }
@ -219,10 +217,18 @@ abstract class INodeModel {
/** /**
* @return {Boolean} true if the children nodes are hidden by the shrink option * @return {Boolean} true if the children nodes are hidden by the shrink option
*/ */
setChildrenShrunken(value: boolean) { setChildrenShrunken(value: boolean): void {
this.putProperty('shrunken', value); this.putProperty('shrunken', value);
} }
setConnectionStyle(type: LineType): void {
this.putProperty('connectionStyle', type);
}
getConnectionStyle(): LineType | null {
return this.getProperty('connectionStyle') as LineType;
}
isNodeModel(): boolean { isNodeModel(): boolean {
return true; return true;
} }
@ -234,7 +240,7 @@ abstract class INodeModel {
return this.getParent() != null; return this.getParent() != null;
} }
abstract append(node): void; abstract append(node: INodeModel): void;
/** /**
* lets the mindmap handle the connect node operation * lets the mindmap handle the connect node operation

View File

@ -28,7 +28,7 @@ class RelationshipModel {
private _targetTopicId: number; private _targetTopicId: number;
private _lineType: number; private _lineType: LineType;
private _srcCtrlPoint: Point; private _srcCtrlPoint: Point;
@ -67,11 +67,11 @@ class RelationshipModel {
return this._id; return this._id;
} }
getLineType(): number { getLineType(): LineType {
return this._lineType; return this._lineType;
} }
setLineType(lineType: number) { setLineType(lineType: LineType) {
this._lineType = lineType; this._lineType = lineType;
} }

View File

@ -18,13 +18,13 @@
import { $assert, $defined, createDocument } from '@wisemapping/core-js'; import { $assert, $defined, createDocument } from '@wisemapping/core-js';
import { Point } from '@wisemapping/web2d'; import { Point } from '@wisemapping/web2d';
import Mindmap from '../model/Mindmap'; import Mindmap from '../model/Mindmap';
import { LineType } from '../ConnectionLine';
import FeatureModelFactory from '../model/FeatureModelFactory'; import FeatureModelFactory from '../model/FeatureModelFactory';
import NodeModel from '../model/NodeModel'; import NodeModel from '../model/NodeModel';
import RelationshipModel from '../model/RelationshipModel'; import RelationshipModel from '../model/RelationshipModel';
import XMLMindmapSerializer from './XMLMindmapSerializer'; import XMLMindmapSerializer from './XMLMindmapSerializer';
import FeatureType from '../model/FeatureType'; import FeatureType from '../model/FeatureType';
import emojiToIconMap from './iconToEmoji.json'; import emojiToIconMap from './iconToEmoji.json';
import { LineType } from '../ConnectionLine';
class XMLSerializerTango implements XMLMindmapSerializer { class XMLSerializerTango implements XMLMindmapSerializer {
private static MAP_ROOT_NODE = 'map'; private static MAP_ROOT_NODE = 'map';
@ -152,6 +152,11 @@ class XMLSerializerTango implements XMLMindmapSerializer {
parentTopic.setAttribute('brColor', brColor); parentTopic.setAttribute('brColor', brColor);
} }
const connectionStyle = topic.getConnectionStyle();
if ($defined(connectionStyle)) {
parentTopic.setAttribute('connStyle', `${connectionStyle}`);
}
const metadata = topic.getMetadata(); const metadata = topic.getMetadata();
if ($defined(metadata)) { if ($defined(metadata)) {
parentTopic.setAttribute('metadata', metadata); parentTopic.setAttribute('metadata', metadata);
@ -206,18 +211,13 @@ class XMLSerializerTango implements XMLMindmapSerializer {
const lineType = relationship.getLineType(); const lineType = relationship.getLineType();
result.setAttribute('lineType', lineType.toString()); result.setAttribute('lineType', lineType.toString());
if (lineType === LineType.CURVED || lineType === LineType.SIMPLE_CURVED) { if ($defined(relationship.getSrcCtrlPoint())) {
if ($defined(relationship.getSrcCtrlPoint())) { const srcPoint = relationship.getSrcCtrlPoint();
const srcPoint = relationship.getSrcCtrlPoint(); result.setAttribute('srcCtrlPoint', `${Math.round(srcPoint.x)},${Math.round(srcPoint.y)}`);
result.setAttribute('srcCtrlPoint', `${Math.round(srcPoint.x)},${Math.round(srcPoint.y)}`); }
} if ($defined(relationship.getDestCtrlPoint())) {
if ($defined(relationship.getDestCtrlPoint())) { const destPoint = relationship.getDestCtrlPoint();
const destPoint = relationship.getDestCtrlPoint(); result.setAttribute('destCtrlPoint', `${Math.round(destPoint.x)},${Math.round(destPoint.y)}`);
result.setAttribute(
'destCtrlPoint',
`${Math.round(destPoint.x)},${Math.round(destPoint.y)}`,
);
}
} }
result.setAttribute('endArrow', String(relationship.getEndArrow())); result.setAttribute('endArrow', String(relationship.getEndArrow()));
result.setAttribute('startArrow', String(relationship.getStartArrow())); result.setAttribute('startArrow', String(relationship.getStartArrow()));
@ -345,6 +345,12 @@ class XMLSerializerTango implements XMLMindmapSerializer {
topic.setBackgroundColor(bgColor); topic.setBackgroundColor(bgColor);
} }
const connStyle = domElem.getAttribute('connStyle');
if ($defined(connStyle) && connStyle) {
const lineType = Number.parseInt(connStyle, 10) as LineType;
topic.setConnectionStyle(lineType);
}
const borderColor = domElem.getAttribute('brColor'); const borderColor = domElem.getAttribute('brColor');
if (borderColor) { if (borderColor) {
topic.setBorderColor(borderColor); topic.setBorderColor(borderColor);

View File

@ -99,7 +99,7 @@ class PolyLinePeer extends ElementPeer {
if (y2 < y1) { if (y2 < y1) {
signy = -1; signy = -1;
} }
const path = `${x1}, ${y1} ${middlex - 10 * signx}, ${y1} ${middlex}, ${y1 + 10 * signy const path = `${x1}, ${y1} ${(middlex - 10 * signx).toFixed(0)}, ${y1} ${(middlex).toFixed(0)}, ${y1 + 10 * signy
} ${middlex}, ${y2 - 10 * signy} ${middlex + 10 * signx}, ${y2} ${x2}, ${y2}`; } ${middlex}, ${y2 - 10 * signy} ${middlex + 10 * signx}, ${y2} ${x2}, ${y2}`;
this._native.setAttribute('points', path); this._native.setAttribute('points', path);
} }
@ -112,7 +112,7 @@ class PolyLinePeer extends ElementPeer {
const y2 = this._y2; const y2 = this._y2;
if ($defined(x1) && $defined(x2) && $defined(y1) && $defined(y2)) { if ($defined(x1) && $defined(x2) && $defined(y1) && $defined(y2)) {
const diff = x2 - x1; const diff = x2 - x1;
const middlex = diff / 2 + x1; const middlex = (diff * 0.75 + x1).toFixed(0);
const path = `${x1}, ${y1} ${middlex}, ${y1} ${middlex}, ${y1} ${middlex}, ${y2} ${middlex}, ${y2} ${x2}, ${y2}`; const path = `${x1}, ${y1} ${middlex}, ${y1} ${middlex}, ${y1} ${middlex}, ${y2} ${middlex}, ${y2} ${x2}, ${y2}`;
this._native.setAttribute('points', path); this._native.setAttribute('points', path);
} }

View File

@ -4,6 +4,9 @@ context('Editor Page', () => {
}); });
it('page loaded', () => { it('page loaded', () => {
// Wait for load complate ...
cy.get('[aria-label="vortex-loading"]').should('not.exist');
cy.matchImageSnapshot('editor-page'); cy.matchImageSnapshot('editor-page');
}); });
}); });

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB