Introduce Theme framework.
@ -48,7 +48,7 @@ describe('Topic Shape Suite', () => {
|
|||||||
.invoke('attr', 'rx')
|
.invoke('attr', 'rx')
|
||||||
.then(parseInt)
|
.then(parseInt)
|
||||||
.should('be.a', 'number')
|
.should('be.a', 'number')
|
||||||
.should('be.lt', 5);
|
.should('be.lte', 8);
|
||||||
|
|
||||||
cy.focusTopicByText('Mind Mapping');
|
cy.focusTopicByText('Mind Mapping');
|
||||||
cy.matchImageSnapshot('changeToRoundedRectangle');
|
cy.matchImageSnapshot('changeToRoundedRectangle');
|
||||||
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 129 KiB |
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 205 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 109 KiB |
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 153 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 144 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 184 KiB |
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
@ -96,10 +96,7 @@ class ConnectionLine {
|
|||||||
|
|
||||||
private updateColor(): string {
|
private updateColor(): string {
|
||||||
// In case that the main topic has changed the color, overwrite the main topic definiton.
|
// In case that the main topic has changed the color, overwrite the main topic definiton.
|
||||||
let color = this._targetTopic.getConnectionColor();
|
const color = this._sourceTopic.getConnectionColor();
|
||||||
if (this._targetTopic.isCentralTopic()) {
|
|
||||||
color = this._sourceTopic.getModel().getConnectionColor() || color;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._color = color;
|
this._color = color;
|
||||||
switch (this._type) {
|
switch (this._type) {
|
||||||
|
@ -523,8 +523,6 @@ class Designer extends Events {
|
|||||||
const { position } = result;
|
const { position } = result;
|
||||||
childModel.setPosition(position.x, position.y);
|
childModel.setPosition(position.x, position.y);
|
||||||
|
|
||||||
childModel.copy(parentModel);
|
|
||||||
|
|
||||||
return childModel;
|
return childModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,7 +552,7 @@ class Designer extends Events {
|
|||||||
// Hack: if parent is central topic, add node below not on opposite side.
|
// Hack: if parent is central topic, add node below not on opposite side.
|
||||||
// This should be done in the layout
|
// This should be done in the layout
|
||||||
if (parentTopic.getType() === 'CentralTopic') {
|
if (parentTopic.getType() === 'CentralTopic') {
|
||||||
siblingModel.setOrder(topic.getOrder() + 2);
|
siblingModel.setOrder(topic.getOrder()! + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentTopicId = parentTopic.getId();
|
const parentTopicId = parentTopic.getId();
|
||||||
@ -575,10 +573,9 @@ class Designer extends Events {
|
|||||||
result = mindmap.createNode();
|
result = mindmap.createNode();
|
||||||
|
|
||||||
// Create a new node ...
|
// Create a new node ...
|
||||||
const order = topic.getOrder() + 1;
|
const order = topic.getOrder()! + 1;
|
||||||
result.setOrder(order);
|
result.setOrder(order);
|
||||||
result.setPosition(10, 10); // Set a dummy position ...
|
result.setPosition(10, 10); // Set a dummy position ...
|
||||||
result.copy(model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -671,7 +668,7 @@ class Designer extends Events {
|
|||||||
nodeModelToTopic(nodeModel: NodeModel): Topic {
|
nodeModelToTopic(nodeModel: NodeModel): Topic {
|
||||||
$assert(nodeModel, 'Node model can not be null');
|
$assert(nodeModel, 'Node model can not be null');
|
||||||
let children = nodeModel.getChildren().slice();
|
let children = nodeModel.getChildren().slice();
|
||||||
children = children.sort((a, b) => a.getOrder() - b.getOrder());
|
children = children.sort((a, b) => a.getOrder()! - b.getOrder()!);
|
||||||
|
|
||||||
const result = this._buildNodeGraph(nodeModel, this.isReadOnly());
|
const result = this._buildNodeGraph(nodeModel, this.isReadOnly());
|
||||||
result.setVisibility(false);
|
result.setVisibility(false);
|
||||||
|
@ -26,7 +26,8 @@ import PositionType from './PositionType';
|
|||||||
|
|
||||||
class MainTopic extends Topic {
|
class MainTopic extends Topic {
|
||||||
buildDragShape(): ElementClass<ElementPeer> {
|
buildDragShape(): ElementClass<ElementPeer> {
|
||||||
const innerShape = this._buildShape(this.getShapeType());
|
const shapeType = this.getShapeType();
|
||||||
|
const innerShape = this._buildShape(shapeType);
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
innerShape.setSize(size.width, size.height);
|
innerShape.setSize(size.width, size.height);
|
||||||
innerShape.setPosition(0, 0);
|
innerShape.setPosition(0, 0);
|
||||||
@ -50,27 +51,21 @@ class MainTopic extends Topic {
|
|||||||
const group = new Group(groupAttributes);
|
const group = new Group(groupAttributes);
|
||||||
group.append(innerShape);
|
group.append(innerShape);
|
||||||
|
|
||||||
// Add Text ...
|
const textShape = this._buildTextShape(true);
|
||||||
if (this.getShapeType() !== 'image') {
|
const text = this.getText();
|
||||||
const textShape = this._buildTextShape(true);
|
textShape.setText(text);
|
||||||
const text = this.getText();
|
textShape.setOpacity(0.5);
|
||||||
textShape.setText(text);
|
|
||||||
textShape.setOpacity(0.5);
|
|
||||||
|
|
||||||
// Copy text position of the topic element ...
|
// Copy text position of the topic element ...
|
||||||
const textPosition = this.getOrBuildTextShape().getPosition();
|
const textPosition = this.getOrBuildTextShape().getPosition();
|
||||||
textShape.setPosition(textPosition.x, textPosition.y);
|
textShape.setPosition(textPosition.x, textPosition.y);
|
||||||
|
|
||||||
group.append(textShape);
|
group.append(textShape);
|
||||||
}
|
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTopicShape(targetTopic: Topic) {
|
updateTopicShape(_targetTopic: Topic) {
|
||||||
if (!targetTopic.isCentralTopic()) {
|
this.redrawShapeType();
|
||||||
// Get the real shape type ...
|
|
||||||
this.redrawShapeType();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect(workspace: Canvas) {
|
disconnect(workspace: Canvas) {
|
||||||
|
@ -27,7 +27,7 @@ import { $notify } from './widget/ToolbarNotifier';
|
|||||||
import { $msg } from './Messages';
|
import { $msg } from './Messages';
|
||||||
import DesignerKeyboard from './DesignerKeyboard';
|
import DesignerKeyboard from './DesignerKeyboard';
|
||||||
import LocalStorageManager from './LocalStorageManager';
|
import LocalStorageManager from './LocalStorageManager';
|
||||||
import TopicStyle from './TopicStyle';
|
import ThemeFactory from './theme/ThemeFactory';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebComponent implementation for minplot designer.
|
* WebComponent implementation for minplot designer.
|
||||||
@ -54,7 +54,9 @@ class MindplotWebComponent extends HTMLElement {
|
|||||||
const wrapper = document.createElement('div');
|
const wrapper = document.createElement('div');
|
||||||
wrapper.setAttribute('class', 'wise-editor');
|
wrapper.setAttribute('class', 'wise-editor');
|
||||||
wrapper.setAttribute('id', 'mindplot-canvas');
|
wrapper.setAttribute('id', 'mindplot-canvas');
|
||||||
wrapper.setAttribute('style', TopicStyle.defaultCanvasCssStyle());
|
|
||||||
|
const theme = ThemeFactory.createById('classic');
|
||||||
|
wrapper.setAttribute('style', theme.getCanvasCssStyle());
|
||||||
|
|
||||||
this._shadowRoot.appendChild(wrapper);
|
this._shadowRoot.appendChild(wrapper);
|
||||||
this._isLoaded = false;
|
this._isLoaded = false;
|
||||||
|
@ -21,7 +21,7 @@ import { Ellipse, Group } from '@wisemapping/web2d';
|
|||||||
import TopicConfig from './TopicConfig';
|
import TopicConfig from './TopicConfig';
|
||||||
import ActionDispatcher from './ActionDispatcher';
|
import ActionDispatcher from './ActionDispatcher';
|
||||||
import Topic from './Topic';
|
import Topic from './Topic';
|
||||||
import ColorUtil from './render/ColorUtil';
|
import ColorUtil from './theme/ColorUtil';
|
||||||
|
|
||||||
class ShirinkConnector {
|
class ShirinkConnector {
|
||||||
private _isShrink: boolean;
|
private _isShrink: boolean;
|
||||||
|
@ -20,7 +20,6 @@ import { $assert, $defined } from '@wisemapping/core-js';
|
|||||||
import { Rect, Text, Group, ElementClass, ElementPeer } from '@wisemapping/web2d';
|
import { Rect, Text, Group, ElementClass, ElementPeer } from '@wisemapping/web2d';
|
||||||
|
|
||||||
import NodeGraph, { NodeOption } from './NodeGraph';
|
import NodeGraph, { NodeOption } from './NodeGraph';
|
||||||
import TopicStyle from './TopicStyle';
|
|
||||||
import TopicFeatureFactory from './TopicFeature';
|
import TopicFeatureFactory from './TopicFeature';
|
||||||
import ConnectionLine, { LineType } from './ConnectionLine';
|
import ConnectionLine, { LineType } from './ConnectionLine';
|
||||||
import IconGroup from './IconGroup';
|
import IconGroup from './IconGroup';
|
||||||
@ -40,11 +39,11 @@ import SizeType from './SizeType';
|
|||||||
import FeatureModel from './model/FeatureModel';
|
import FeatureModel from './model/FeatureModel';
|
||||||
import PositionType from './PositionType';
|
import PositionType from './PositionType';
|
||||||
import LineTopicShape from './widget/LineTopicShape';
|
import LineTopicShape from './widget/LineTopicShape';
|
||||||
import ColorUtil from './render/ColorUtil';
|
|
||||||
import Icon from './Icon';
|
import Icon from './Icon';
|
||||||
import { FontStyleType } from './FontStyleType';
|
import { FontStyleType } from './FontStyleType';
|
||||||
import { FontWeightType } from './FontWeightType';
|
import { FontWeightType } from './FontWeightType';
|
||||||
import DragTopic from './DragTopic';
|
import DragTopic from './DragTopic';
|
||||||
|
import ThemeFactory from './theme/ThemeFactory';
|
||||||
|
|
||||||
const ICON_SCALING_FACTOR = 1.3;
|
const ICON_SCALING_FACTOR = 1.3;
|
||||||
|
|
||||||
@ -119,83 +118,51 @@ abstract class Topic extends NodeGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected redrawShapeType() {
|
protected redrawShapeType() {
|
||||||
const oldInnerShape = this.getInnerShape();
|
this._removeInnerShape();
|
||||||
if (oldInnerShape) {
|
|
||||||
this._removeInnerShape();
|
|
||||||
|
|
||||||
// Create a new one ...
|
// Create a new one ...
|
||||||
const innerShape = this.getInnerShape();
|
const innerShape = this.getInnerShape();
|
||||||
|
|
||||||
// Update figure size ...
|
// Update figure size ...
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
this.setSize(size, true);
|
this.setSize(size, true);
|
||||||
|
|
||||||
const group = this.get2DElement();
|
const group = this.get2DElement();
|
||||||
group.append(innerShape);
|
group.append(innerShape);
|
||||||
|
|
||||||
// Move text to the front ...
|
// Move text to the front ...
|
||||||
const text = this.getOrBuildTextShape();
|
const text = this.getOrBuildTextShape();
|
||||||
text.moveToFront();
|
text.moveToFront();
|
||||||
|
|
||||||
// Move iconGroup to front ...
|
// Move iconGroup to front ...
|
||||||
const iconGroup = this.getIconGroup();
|
const iconGroup = this.getIconGroup();
|
||||||
if (iconGroup) {
|
if (iconGroup) {
|
||||||
iconGroup.moveToFront();
|
iconGroup.moveToFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move connector to front
|
// Move connector to front
|
||||||
const connector = this.getShrinkConnector();
|
const connector = this.getShrinkConnector();
|
||||||
if (connector) {
|
if (connector) {
|
||||||
connector.moveToFront();
|
connector.moveToFront();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getShapeType(): TopicShapeType {
|
getShapeType(): TopicShapeType {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getShapeType();
|
const theme = ThemeFactory.create(model);
|
||||||
if (!result) {
|
return theme.getShapeType(this);
|
||||||
result = TopicStyle.defaultShapeType(this);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getConnectionStyle(): LineType {
|
getConnectionStyle(): LineType {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result: LineType | undefined = model.getConnectionStyle();
|
const theme = ThemeFactory.create(model);
|
||||||
|
return theme.getConnectionType(this);
|
||||||
// Style is infered looking recursivelly on the parent nodes.
|
|
||||||
if (result === undefined) {
|
|
||||||
const parent = this.getParent();
|
|
||||||
if (parent) {
|
|
||||||
result = parent.getConnectionStyle();
|
|
||||||
} else {
|
|
||||||
result = TopicStyle.defaultConnectionType(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getConnectionColor(): string {
|
getConnectionColor(): string {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result: string | undefined = model.getConnectionColor();
|
const theme = ThemeFactory.create(model);
|
||||||
|
return theme.getConnectionColor(this);
|
||||||
// Style is infered looking recursivelly on the parent nodes.
|
|
||||||
if (!result) {
|
|
||||||
const parent = this.getParent();
|
|
||||||
if (parent && parent.isCentralTopic()) {
|
|
||||||
// This means that this is central main node, in this case, I will overwrite with the main color if it was defined.
|
|
||||||
result = this.getModel().getConnectionColor() || parent.getModel().getConnectionColor();
|
|
||||||
} else {
|
|
||||||
result = parent?.getConnectionColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
result = TopicStyle.defaultConnectionColor(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _removeInnerShape(): ElementClass<ElementPeer> {
|
private _removeInnerShape(): ElementClass<ElementPeer> {
|
||||||
@ -232,7 +199,7 @@ abstract class Topic extends NodeGraph {
|
|||||||
result = new Rect(0.9, { strokeWidth: 2 });
|
result = new Rect(0.9, { strokeWidth: 2 });
|
||||||
break;
|
break;
|
||||||
case 'rounded rectangle':
|
case 'rounded rectangle':
|
||||||
result = new Rect(0.3, { strokeWidth: 2 });
|
result = new Rect(0.6, { strokeWidth: 2 });
|
||||||
break;
|
break;
|
||||||
case 'line':
|
case 'line':
|
||||||
result = new LineTopicShape(this, { strokeWidth: 2 });
|
result = new LineTopicShape(this, { strokeWidth: 2 });
|
||||||
@ -300,14 +267,16 @@ abstract class Topic extends NodeGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _buildIconGroup(): IconGroup {
|
private _buildIconGroup(): IconGroup {
|
||||||
|
const model = this.getModel();
|
||||||
|
const theme = ThemeFactory.create(model);
|
||||||
|
|
||||||
const textHeight = this.getOrBuildTextShape().getFontHeight();
|
const textHeight = this.getOrBuildTextShape().getFontHeight();
|
||||||
const iconSize = textHeight * ICON_SCALING_FACTOR;
|
const iconSize = textHeight * ICON_SCALING_FACTOR;
|
||||||
const result = new IconGroup(this.getId(), iconSize);
|
const result = new IconGroup(this.getId(), iconSize);
|
||||||
const padding = TopicStyle.getInnerPadding(this);
|
const padding = theme.getInnerPadding(this);
|
||||||
result.setPosition(padding, padding);
|
result.setPosition(padding, padding);
|
||||||
|
|
||||||
// Load topic features ...
|
// Load topic features ...
|
||||||
const model = this.getModel();
|
|
||||||
const featuresModel = model.getFeatures();
|
const featuresModel = model.getFeatures();
|
||||||
|
|
||||||
featuresModel.forEach((f) => {
|
featuresModel.forEach((f) => {
|
||||||
@ -397,78 +366,58 @@ abstract class Topic extends NodeGraph {
|
|||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
model.setFontFamily(value);
|
model.setFontFamily(value);
|
||||||
|
|
||||||
this.redraw();
|
this.redraw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFontSize(value: number): void {
|
setFontSize(value: number): void {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
model.setFontSize(value);
|
model.setFontSize(value);
|
||||||
|
|
||||||
this.redraw();
|
this.redraw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFontStyle(value: FontStyleType): void {
|
setFontStyle(value: FontStyleType): void {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
model.setFontStyle(value);
|
model.setFontStyle(value);
|
||||||
|
|
||||||
this.redraw();
|
this.redraw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setFontWeight(value: FontWeightType): void {
|
setFontWeight(value: FontWeightType): void {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
model.setFontWeight(value);
|
model.setFontWeight(value);
|
||||||
|
|
||||||
this.redraw();
|
this.redraw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
getFontWeight(): FontWeightType {
|
getFontWeight(): FontWeightType {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getFontWeight();
|
const theme = ThemeFactory.create(model);
|
||||||
if (!result) {
|
return theme.getFontWeight(this);
|
||||||
const font = TopicStyle.defaultFontStyle(this);
|
|
||||||
result = font.weight;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFontFamily(): string {
|
getFontFamily(): string {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getFontFamily();
|
const theme = ThemeFactory.create(model);
|
||||||
if (!result) {
|
return theme.getFontFamily(this);
|
||||||
const font = TopicStyle.defaultFontStyle(this);
|
|
||||||
result = font.font;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFontColor(): string {
|
getFontColor(): string {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getFontColor();
|
const theme = ThemeFactory.create(model);
|
||||||
if (!result) {
|
return theme.getFontColor(this);
|
||||||
const font = TopicStyle.defaultFontStyle(this);
|
|
||||||
result = font.color;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFontStyle(): string {
|
getFontStyle(): FontStyleType {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getFontStyle();
|
const theme = ThemeFactory.create(model);
|
||||||
if (!result) {
|
return theme.getFontStyle(this);
|
||||||
const font = TopicStyle.defaultFontStyle(this);
|
|
||||||
result = font.style;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFontSize(): number {
|
getFontSize(): number {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getFontSize();
|
const theme = ThemeFactory.create(model);
|
||||||
if (!result) {
|
return theme.getFontSize(this);
|
||||||
const font = TopicStyle.defaultFontStyle(this);
|
|
||||||
result = font.size;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setFontColor(value: string | undefined) {
|
setFontColor(value: string | undefined) {
|
||||||
@ -485,20 +434,22 @@ abstract class Topic extends NodeGraph {
|
|||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
model.setText(modelText);
|
model.setText(modelText);
|
||||||
|
|
||||||
this.redraw();
|
this.redraw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
getText(): string {
|
getText(): string {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
|
const theme = ThemeFactory.create(model);
|
||||||
|
|
||||||
const text = model.getText();
|
const text = model.getText();
|
||||||
return text || TopicStyle.defaultText(this);
|
return text || theme.getText(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
setBackgroundColor(color: string | undefined): void {
|
setBackgroundColor(color: string | undefined): void {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
model.setBackgroundColor(color);
|
model.setBackgroundColor(color);
|
||||||
|
|
||||||
this.redraw();
|
this.redraw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setConnectionStyle(type: LineType): void {
|
setConnectionStyle(type: LineType): void {
|
||||||
@ -517,19 +468,8 @@ abstract class Topic extends NodeGraph {
|
|||||||
|
|
||||||
getBackgroundColor(): string {
|
getBackgroundColor(): string {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getBackgroundColor();
|
const theme = ThemeFactory.create(model);
|
||||||
if (!result && !this.isCentralTopic()) {
|
return theme.getBackgroundColor(this);
|
||||||
// Be sure that not overwride default background color ...
|
|
||||||
const borderColor = model.getBorderColor();
|
|
||||||
if (borderColor) {
|
|
||||||
result = ColorUtil.lightenColor(borderColor, 40);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
result = TopicStyle.defaultBackgroundColor(this);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setBorderColor(color: string | undefined): void {
|
setBorderColor(color: string | undefined): void {
|
||||||
@ -541,25 +481,8 @@ abstract class Topic extends NodeGraph {
|
|||||||
|
|
||||||
getBorderColor(): string {
|
getBorderColor(): string {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
let result = model.getBorderColor();
|
const theme = ThemeFactory.create(model);
|
||||||
|
return theme.getBorderColor(this);
|
||||||
// If the the style is a line, the color is alward the connection one.
|
|
||||||
if (this.getShapeType() === 'line') {
|
|
||||||
result = this.getConnectionColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result === undefined) {
|
|
||||||
const parent = this.getParent();
|
|
||||||
if (parent) {
|
|
||||||
result = parent.getBorderColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If border color has not been defined, use the connection color for the border ...
|
|
||||||
if (!result) {
|
|
||||||
result = this.getConnectionColor();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_buildTopicShape(): void {
|
_buildTopicShape(): void {
|
||||||
@ -638,11 +561,12 @@ abstract class Topic extends NodeGraph {
|
|||||||
|
|
||||||
setOnFocus(focus: boolean) {
|
setOnFocus(focus: boolean) {
|
||||||
if (this.isOnFocus() !== focus) {
|
if (this.isOnFocus() !== focus) {
|
||||||
|
const theme = ThemeFactory.create(this.getModel());
|
||||||
this._onFocus = focus;
|
this._onFocus = focus;
|
||||||
const outerShape = this.getOuterShape();
|
const outerShape = this.getOuterShape();
|
||||||
|
|
||||||
const fillColor = TopicStyle.defaultOuterBackgroundColor(this, focus);
|
const fillColor = theme.getOuterBackgroundColor(this, focus);
|
||||||
const borderColor = TopicStyle.defaultOuterBorderColor(this);
|
const borderColor = theme.getOuterBorderColor(this);
|
||||||
|
|
||||||
outerShape.setFill(fillColor);
|
outerShape.setFill(fillColor);
|
||||||
outerShape.setStroke(1, 'solid', borderColor);
|
outerShape.setStroke(1, 'solid', borderColor);
|
||||||
@ -1051,7 +975,7 @@ abstract class Topic extends NodeGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrder(): number {
|
getOrder(): number | undefined {
|
||||||
const model = this.getModel();
|
const model = this.getModel();
|
||||||
return model.getOrder();
|
return model.getOrder();
|
||||||
}
|
}
|
||||||
@ -1184,6 +1108,7 @@ abstract class Topic extends NodeGraph {
|
|||||||
// Has the style change ?
|
// Has the style change ?
|
||||||
const connStyleChanged =
|
const connStyleChanged =
|
||||||
this._outgoingLine.getLineType() !== this.getParent()!.getConnectionStyle();
|
this._outgoingLine.getLineType() !== this.getParent()!.getConnectionStyle();
|
||||||
|
|
||||||
if (connStyleChanged) {
|
if (connStyleChanged) {
|
||||||
// Todo: Review static reference ...
|
// Todo: Review static reference ...
|
||||||
const workspace = designer.getWorkSpace();
|
const workspace = designer.getWorkSpace();
|
||||||
@ -1197,13 +1122,8 @@ abstract class Topic extends NodeGraph {
|
|||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has the color changed ?
|
this._outgoingLine.redraw();
|
||||||
const color = this._outgoingLine.getStrokeColor();
|
result = true;
|
||||||
const connColorChanged = color !== this.getParent()!.getConnectionColor();
|
|
||||||
if (connColorChanged) {
|
|
||||||
this._outgoingLine.redraw();
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -1211,6 +1131,7 @@ abstract class Topic extends NodeGraph {
|
|||||||
|
|
||||||
redraw(redrawChildren = false): void {
|
redraw(redrawChildren = false): void {
|
||||||
if (this._isInWorkspace) {
|
if (this._isInWorkspace) {
|
||||||
|
const theme = ThemeFactory.create(this.getModel());
|
||||||
const textShape = this.getOrBuildTextShape();
|
const textShape = this.getOrBuildTextShape();
|
||||||
// Update font ...
|
// Update font ...
|
||||||
const fontColor = this.getFontColor();
|
const fontColor = this.getFontColor();
|
||||||
@ -1233,8 +1154,8 @@ abstract class Topic extends NodeGraph {
|
|||||||
|
|
||||||
// Update outer shape style ...
|
// Update outer shape style ...
|
||||||
const outerShape = this.getOuterShape();
|
const outerShape = this.getOuterShape();
|
||||||
const outerFillColor = TopicStyle.defaultOuterBackgroundColor(this, this.isOnFocus());
|
const outerFillColor = theme.getOuterBackgroundColor(this, this.isOnFocus());
|
||||||
const outerBorderColor = TopicStyle.defaultOuterBorderColor(this);
|
const outerBorderColor = theme.getOuterBorderColor(this);
|
||||||
|
|
||||||
outerShape.setFill(outerFillColor);
|
outerShape.setFill(outerFillColor);
|
||||||
outerShape.setStroke(1, 'solid', outerBorderColor);
|
outerShape.setStroke(1, 'solid', outerBorderColor);
|
||||||
@ -1242,7 +1163,7 @@ abstract class Topic extends NodeGraph {
|
|||||||
// Calculate topic size and adjust elements ...
|
// Calculate topic size and adjust elements ...
|
||||||
const textWidth = textShape.getShapeWidth();
|
const textWidth = textShape.getShapeWidth();
|
||||||
const textHeight = textShape.getShapeHeight();
|
const textHeight = textShape.getShapeHeight();
|
||||||
const padding = TopicStyle.getInnerPadding(this);
|
const padding = theme.getInnerPadding(this);
|
||||||
|
|
||||||
// Adjust icons group based on the font size ...
|
// Adjust icons group based on the font size ...
|
||||||
const iconGroup = this.getOrBuildIconGroup();
|
const iconGroup = this.getOrBuildIconGroup();
|
||||||
|
@ -1,205 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright [2011] [wisemapping]
|
|
||||||
*
|
|
||||||
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
|
||||||
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
|
||||||
* "powered by wisemapping" text requirement on every single page;
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the license at
|
|
||||||
*
|
|
||||||
* http://www.wisemapping.org/license
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
import { $assert } from '@wisemapping/core-js';
|
|
||||||
import { LineType } from './ConnectionLine';
|
|
||||||
import { FontStyleType } from './FontStyleType';
|
|
||||||
import { FontWeightType } from './FontWeightType';
|
|
||||||
import { $msg } from './Messages';
|
|
||||||
import { TopicShapeType } from './model/INodeModel';
|
|
||||||
import ColorUtil from './render/ColorUtil';
|
|
||||||
import Topic from './Topic';
|
|
||||||
|
|
||||||
type FontStyle = {
|
|
||||||
font: string;
|
|
||||||
size: number;
|
|
||||||
style: FontStyleType;
|
|
||||||
weight: FontWeightType;
|
|
||||||
color: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type TopicStyleType = {
|
|
||||||
borderColor: string;
|
|
||||||
backgroundColor: string;
|
|
||||||
connectionStyle: LineType;
|
|
||||||
connectionColor: string;
|
|
||||||
fontStyle: FontStyle;
|
|
||||||
msgKey: string;
|
|
||||||
shapeType: TopicShapeType;
|
|
||||||
};
|
|
||||||
|
|
||||||
const TopicDefaultStyles = {
|
|
||||||
CENTRAL_TOPIC: {
|
|
||||||
borderColor: '#3971B1',
|
|
||||||
backgroundColor: '#509DC0',
|
|
||||||
fontStyle: {
|
|
||||||
font: 'Verdana',
|
|
||||||
size: 10,
|
|
||||||
style: 'normal' as FontStyleType,
|
|
||||||
weight: 'bold' as FontWeightType,
|
|
||||||
color: '#ffffff',
|
|
||||||
},
|
|
||||||
connectionStyle: LineType.THICK_CURVED,
|
|
||||||
connectionColor: '#345780',
|
|
||||||
msgKey: 'CENTRAL_TOPIC',
|
|
||||||
shapeType: 'rounded rectangle' as TopicShapeType,
|
|
||||||
},
|
|
||||||
MAIN_TOPIC: {
|
|
||||||
borderColor: '#023BB9',
|
|
||||||
backgroundColor: '#E0E5EF',
|
|
||||||
fontStyle: {
|
|
||||||
font: 'Verdana',
|
|
||||||
size: 8,
|
|
||||||
style: 'normal' as FontStyleType,
|
|
||||||
weight: 'normal' as FontWeightType,
|
|
||||||
color: '#525C61',
|
|
||||||
},
|
|
||||||
connectionStyle: LineType.ARC,
|
|
||||||
connectionColor: '#345780',
|
|
||||||
msgKey: 'MAIN_TOPIC',
|
|
||||||
shapeType: 'line' as TopicShapeType,
|
|
||||||
},
|
|
||||||
SUB_TOPIC: {
|
|
||||||
borderColor: '#96e3ff',
|
|
||||||
backgroundColor: '#96e3ff',
|
|
||||||
fontStyle: {
|
|
||||||
font: 'Verdana',
|
|
||||||
size: 8,
|
|
||||||
style: 'normal' as FontStyleType,
|
|
||||||
weight: 'normal' as FontWeightType,
|
|
||||||
color: '#525C61',
|
|
||||||
},
|
|
||||||
connectionStyle: LineType.ARC,
|
|
||||||
connectionColor: '#345780',
|
|
||||||
msgKey: 'SUB_TOPIC',
|
|
||||||
shapeType: 'line' as TopicShapeType,
|
|
||||||
},
|
|
||||||
|
|
||||||
ISOLATED_TOPIC: {
|
|
||||||
borderColor: '#023BB9',
|
|
||||||
backgroundColor: '#96e3ff',
|
|
||||||
fontStyle: {
|
|
||||||
font: 'Verdana',
|
|
||||||
size: 8,
|
|
||||||
style: 'normal' as FontStyleType,
|
|
||||||
weight: 'normal' as FontWeightType,
|
|
||||||
color: '#525C61',
|
|
||||||
},
|
|
||||||
msgKey: 'ISOLATED_TOPIC',
|
|
||||||
connectionStyle: LineType.THICK_CURVED,
|
|
||||||
connectionColor: '#345780',
|
|
||||||
shapeType: 'line' as TopicShapeType,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
class TopicStyle {
|
|
||||||
static _getStyles(topic: Topic): TopicStyleType {
|
|
||||||
$assert(topic, 'topic can not be null');
|
|
||||||
|
|
||||||
let result: TopicStyleType;
|
|
||||||
if (topic.isCentralTopic()) {
|
|
||||||
result = TopicDefaultStyles.CENTRAL_TOPIC;
|
|
||||||
} else {
|
|
||||||
const targetTopic = topic.getOutgoingConnectedTopic();
|
|
||||||
if (targetTopic) {
|
|
||||||
if (targetTopic.isCentralTopic()) {
|
|
||||||
result = TopicDefaultStyles.MAIN_TOPIC;
|
|
||||||
} else {
|
|
||||||
result = TopicDefaultStyles.SUB_TOPIC;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result = TopicDefaultStyles.ISOLATED_TOPIC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultText(topic: Topic): string {
|
|
||||||
const { msgKey } = this._getStyles(topic);
|
|
||||||
return $msg(msgKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultFontStyle(topic: Topic): FontStyle {
|
|
||||||
return this._getStyles(topic).fontStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultCanvasCssStyle(): string {
|
|
||||||
return `position: relative;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
opacity: 1;
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
background-image: linear-gradient(#ebe9e7 1px, transparent 1px),
|
|
||||||
linear-gradient(to right, #ebe9e7 1px, #f2f2f2 1px);
|
|
||||||
background-size: 50px 50px;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultOuterBorderColor(topic: Topic): string {
|
|
||||||
let result: string;
|
|
||||||
if (topic.getShapeType() === 'line') {
|
|
||||||
result = '#F4B82D';
|
|
||||||
} else {
|
|
||||||
const innerBorderColor = topic.getBorderColor();
|
|
||||||
result = ColorUtil.lightenColor(innerBorderColor, 70);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultOuterBackgroundColor(topic: Topic, onFocus: boolean): string {
|
|
||||||
let result: string;
|
|
||||||
if (topic.getShapeType() === 'line') {
|
|
||||||
result = onFocus ? '#F4B82D' : '#FCEBC0';
|
|
||||||
} else {
|
|
||||||
const innerBgColor = topic.getBackgroundColor();
|
|
||||||
result = ColorUtil.lightenColor(innerBgColor, 70);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultBackgroundColor(topic: Topic): string {
|
|
||||||
return this._getStyles(topic).backgroundColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultBorderColor(topic: Topic): string {
|
|
||||||
return this._getStyles(topic).borderColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getInnerPadding(topic: Topic): number {
|
|
||||||
return topic.getOrBuildTextShape().getFontHeight() * 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultShapeType(topic: Topic): TopicShapeType {
|
|
||||||
return this._getStyles(topic).shapeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultConnectionType(topic: Topic): LineType {
|
|
||||||
return this._getStyles(topic).connectionStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static defaultConnectionColor(topic: Topic): string {
|
|
||||||
return this._getStyles(topic).connectionColor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TopicStyle;
|
|
@ -15,6 +15,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import { $defined } from '@wisemapping/core-js';
|
||||||
import Command from '../Command';
|
import Command from '../Command';
|
||||||
import CommandContext from '../CommandContext';
|
import CommandContext from '../CommandContext';
|
||||||
import PositionType from '../PositionType';
|
import PositionType from '../PositionType';
|
||||||
@ -27,7 +28,7 @@ class DragTopicCommand extends Command {
|
|||||||
|
|
||||||
private _position: PositionType;
|
private _position: PositionType;
|
||||||
|
|
||||||
private _order: number;
|
private _order: number | undefined;
|
||||||
|
|
||||||
constructor(topicId: number, position: PositionType, order: number, parentTopic: Topic) {
|
constructor(topicId: number, position: PositionType, order: number, parentTopic: Topic) {
|
||||||
super();
|
super();
|
||||||
@ -55,8 +56,8 @@ class DragTopicCommand extends Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set topic order ...
|
// Set topic order ...
|
||||||
if (this._order != null) {
|
if ($defined(this._order)) {
|
||||||
topic.setOrder(this._order);
|
topic.setOrder(this._order!);
|
||||||
} else if (this._position != null) {
|
} else if (this._position != null) {
|
||||||
commandContext.moveTopic(topic, this._position);
|
commandContext.moveTopic(topic, this._position);
|
||||||
} else {
|
} else {
|
||||||
|
@ -124,7 +124,8 @@ export default class FreemindImporter extends Importer {
|
|||||||
relationship.setSrcCtrlPoint({ x, y: coords.y });
|
relationship.setSrcCtrlPoint({ x, y: coords.y });
|
||||||
|
|
||||||
// Fix coord
|
// Fix coord
|
||||||
if (srcTopic.getOrder() && srcTopic.getOrder() % 2 !== 0) {
|
const order = srcTopic.getOrder();
|
||||||
|
if (order !== undefined && order % 2 !== 0) {
|
||||||
const y = coords.y * -1;
|
const y = coords.y * -1;
|
||||||
relationship.setSrcCtrlPoint({ x: coords.x, y });
|
relationship.setSrcCtrlPoint({ x: coords.x, y });
|
||||||
}
|
}
|
||||||
@ -140,7 +141,8 @@ export default class FreemindImporter extends Importer {
|
|||||||
relationship.setDestCtrlPoint({ x, y: coords.y });
|
relationship.setDestCtrlPoint({ x, y: coords.y });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destNode.getOrder() && destNode.getOrder() % 2 !== 0) {
|
const order = destNode.getOrder();
|
||||||
|
if (order !== undefined && order % 2 !== 0) {
|
||||||
const y = coords.y * -1;
|
const y = coords.y * -1;
|
||||||
relationship.setDestCtrlPoint({ x: coords.x, y });
|
relationship.setDestCtrlPoint({ x: coords.x, y });
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ abstract class ChildrenSorterStrategy {
|
|||||||
|
|
||||||
abstract computeOffsets(treeSet: RootedTreeSet, node: Node): Map<number, PositionType>;
|
abstract computeOffsets(treeSet: RootedTreeSet, node: Node): Map<number, PositionType>;
|
||||||
|
|
||||||
abstract insert(treeSet: RootedTreeSet, parent: Node, child: Node, order: number): void;
|
abstract insert(treeSet: RootedTreeSet, parent: Node, child: Node, order?: number): void;
|
||||||
|
|
||||||
abstract detach(treeSet: RootedTreeSet, node: Node): void;
|
abstract detach(treeSet: RootedTreeSet, node: Node): void;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class EventBusDispatcher {
|
|||||||
this._layoutManager!.connectNode(
|
this._layoutManager!.connectNode(
|
||||||
args.parentNode.getId(),
|
args.parentNode.getId(),
|
||||||
args.childNode.getId(),
|
args.childNode.getId(),
|
||||||
args.childNode.getOrder(),
|
args.childNode.getOrder()!, // @todo: This can be a issue ...
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ class OriginalLayout {
|
|||||||
const parentX = parentPosition.x;
|
const parentX = parentPosition.x;
|
||||||
const parentY = parentPosition.y;
|
const parentY = parentPosition.y;
|
||||||
|
|
||||||
|
console.log(`${parent?.getId()}:${offset.x}`);
|
||||||
const newPos = {
|
const newPos = {
|
||||||
x: parentX + offset.x,
|
x: parentX + offset.x,
|
||||||
y: parentY + offset.y + this.calculateAlignOffset(node, child, heightById),
|
y: parentY + offset.y + this.calculateAlignOffset(node, child, heightById),
|
||||||
@ -174,6 +175,9 @@ class OriginalLayout {
|
|||||||
private fixOverlapping(node: Node, heightById: Map<number, number>): void {
|
private fixOverlapping(node: Node, heightById: Map<number, number>): void {
|
||||||
const children = this._treeSet.getChildren(node);
|
const children = this._treeSet.getChildren(node);
|
||||||
|
|
||||||
|
if (node.isFree()) {
|
||||||
|
this._shiftBranches(node, heightById);
|
||||||
|
}
|
||||||
children.forEach((child) => {
|
children.forEach((child) => {
|
||||||
this.fixOverlapping(child, heightById);
|
this.fixOverlapping(child, heightById);
|
||||||
});
|
});
|
||||||
|
@ -137,7 +137,8 @@ abstract class INodeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getShapeType(): TopicShapeType {
|
getShapeType(): TopicShapeType {
|
||||||
return this.getProperty('shapeType') as TopicShapeType;
|
const result = this.getProperty('shapeType') as TopicShapeType;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
setShapeType(type: TopicShapeType | undefined) {
|
setShapeType(type: TopicShapeType | undefined) {
|
||||||
@ -152,7 +153,7 @@ abstract class INodeModel {
|
|||||||
this.putProperty('order', value);
|
this.putProperty('order', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrder(): number {
|
getOrder(): number | undefined {
|
||||||
return this.getProperty('order') as number;
|
return this.getProperty('order') as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import INodeModel, { NodeModelType } from './INodeModel';
|
|||||||
import NodeModel from './NodeModel';
|
import NodeModel from './NodeModel';
|
||||||
import RelationshipModel from './RelationshipModel';
|
import RelationshipModel from './RelationshipModel';
|
||||||
import ModelCodeName from '../persistence/ModelCodeName';
|
import ModelCodeName from '../persistence/ModelCodeName';
|
||||||
|
import ThemeType from './ThemeType';
|
||||||
|
|
||||||
class Mindmap extends IMindmap {
|
class Mindmap extends IMindmap {
|
||||||
private _description: string;
|
private _description: string;
|
||||||
@ -33,6 +34,8 @@ class Mindmap extends IMindmap {
|
|||||||
|
|
||||||
private _relationships: Array<RelationshipModel>;
|
private _relationships: Array<RelationshipModel>;
|
||||||
|
|
||||||
|
private _theme: ThemeType | undefined;
|
||||||
|
|
||||||
constructor(id?: string, version: string = ModelCodeName.TANGO) {
|
constructor(id?: string, version: string = ModelCodeName.TANGO) {
|
||||||
super();
|
super();
|
||||||
this._branches = [];
|
this._branches = [];
|
||||||
@ -42,6 +45,10 @@ class Mindmap extends IMindmap {
|
|||||||
this._id = id;
|
this._id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTheme(): ThemeType {
|
||||||
|
return this._theme ? this._theme : 'classic';
|
||||||
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
return this._description;
|
return this._description;
|
||||||
|
@ -132,46 +132,6 @@ class NodeModel extends INodeModel {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(value: NodeModel) {
|
|
||||||
// I don't copy the font size if the target is the source is the central topic.
|
|
||||||
if (value.getType() !== 'CentralTopic') {
|
|
||||||
const fontSize = value.getFontSize();
|
|
||||||
if (fontSize) {
|
|
||||||
this.setFontSize(fontSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fontFamily = value.getFontFamily();
|
|
||||||
if (fontFamily) {
|
|
||||||
this.setFontFamily(fontFamily);
|
|
||||||
}
|
|
||||||
|
|
||||||
const fontColor = value.getFontColor();
|
|
||||||
if (fontColor) {
|
|
||||||
this.setFontColor(fontColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
const fontWeight = value.getFontWeight();
|
|
||||||
if (fontWeight) {
|
|
||||||
this.setFontWeight(fontWeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
const fontStyle = value.getFontStyle();
|
|
||||||
if (fontStyle) {
|
|
||||||
this.setFontStyle(fontStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
const shape = value.getShapeType();
|
|
||||||
if (shape) {
|
|
||||||
this.setShapeType(shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
const backgroundColor = value.getBackgroundColor();
|
|
||||||
if (backgroundColor) {
|
|
||||||
this.setBackgroundColor(backgroundColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deepCopy(): NodeModel {
|
deepCopy(): NodeModel {
|
||||||
const result = new NodeModel(this.getType(), this._mindmap);
|
const result = new NodeModel(this.getType(), this._mindmap);
|
||||||
result._children = this._children.map((node) => {
|
result._children = this._children.map((node) => {
|
||||||
|
20
packages/mindplot/src/components/model/ThemeType.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright [2021] [wisemapping]
|
||||||
|
*
|
||||||
|
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||||
|
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||||
|
* "powered by wisemapping" text requirement on every single page;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the license at
|
||||||
|
*
|
||||||
|
* http://www.wisemapping.org/license
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
type ThemeType = 'classic' | 'prism';
|
||||||
|
|
||||||
|
export default ThemeType;
|
@ -59,8 +59,8 @@ class Pela2TangoMigrator implements XMLMindmapSerializer {
|
|||||||
} else {
|
} else {
|
||||||
rightNodes.push(child);
|
rightNodes.push(child);
|
||||||
}
|
}
|
||||||
rightNodes.sort((a, b) => a.getOrder() - b.getOrder());
|
rightNodes.sort((a, b) => a.getOrder()! - b.getOrder()!);
|
||||||
leftNodes.sort((a, b) => a.getOrder() - b.getOrder());
|
leftNodes.sort((a, b) => a.getOrder()! - b.getOrder()!);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < rightNodes.length; i++) {
|
for (let i = 0; i < rightNodes.length; i++) {
|
||||||
|
@ -60,7 +60,9 @@ class XMLSerializerBeta implements XMLMindmapSerializer {
|
|||||||
parentTopic.setAttribute('position', `${pos.x},${pos.y}`);
|
parentTopic.setAttribute('position', `${pos.x},${pos.y}`);
|
||||||
} else {
|
} else {
|
||||||
const order = topic.getOrder();
|
const order = topic.getOrder();
|
||||||
parentTopic.setAttribute('order', order.toString());
|
if (order !== undefined) {
|
||||||
|
parentTopic.setAttribute('order', order.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,7 +452,7 @@ class XMLSerializerTango implements XMLMindmapSerializer {
|
|||||||
if (topic.getType() !== 'CentralTopic') {
|
if (topic.getType() !== 'CentralTopic') {
|
||||||
topic
|
topic
|
||||||
.getChildren()
|
.getChildren()
|
||||||
.sort((a, b) => a.getOrder() - b.getOrder())
|
.sort((a, b) => a.getOrder()! - b.getOrder()!)
|
||||||
.forEach((child, index) => {
|
.forEach((child, index) => {
|
||||||
if (child.getOrder() !== index) {
|
if (child.getOrder() !== index) {
|
||||||
child.setOrder(index);
|
child.setOrder(index);
|
||||||
|
124
packages/mindplot/src/components/theme/ClassicTheme.ts
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright [2011] [wisemapping]
|
||||||
|
*
|
||||||
|
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||||
|
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||||
|
* "powered by wisemapping" text requirement on every single page;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the license at
|
||||||
|
*
|
||||||
|
* http://www.wisemapping.org/license
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { LineType } from '../ConnectionLine';
|
||||||
|
import { FontStyleType } from '../FontStyleType';
|
||||||
|
import { FontWeightType } from '../FontWeightType';
|
||||||
|
import { TopicShapeType } from '../model/INodeModel';
|
||||||
|
import DefaultTheme, { TopicStyleType } from './DefaultTheme';
|
||||||
|
import { TopicType } from './Theme';
|
||||||
|
|
||||||
|
const defaultStyles = new Map<TopicType, TopicStyleType>([
|
||||||
|
[
|
||||||
|
'CentralTopic',
|
||||||
|
{
|
||||||
|
msgKey: 'CENTRAL_TOPIC',
|
||||||
|
borderColor: '#3971B1',
|
||||||
|
backgroundColor: '#509DC0',
|
||||||
|
fontFamily: 'Verdana',
|
||||||
|
fontSize: 10,
|
||||||
|
fontStyle: 'normal' as FontStyleType,
|
||||||
|
fontWeight: 'bold' as FontWeightType,
|
||||||
|
fontColor: '#ffffff',
|
||||||
|
connectionStyle: LineType.THICK_CURVED,
|
||||||
|
connectionColor: '#345780',
|
||||||
|
shapeType: 'rounded rectangle' as TopicShapeType,
|
||||||
|
outerBackgroundColor: '#F4B82D',
|
||||||
|
outerBorderColor: '#F4B82D',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'MainTopic',
|
||||||
|
{
|
||||||
|
msgKey: 'MAIN_TOPIC',
|
||||||
|
borderColor: '#023BB9',
|
||||||
|
backgroundColor: '#E0E5EF',
|
||||||
|
fontFamily: 'Verdana',
|
||||||
|
fontSize: 9,
|
||||||
|
fontStyle: 'normal' as FontStyleType,
|
||||||
|
fontWeight: 'normal' as FontWeightType,
|
||||||
|
fontColor: '#525C61',
|
||||||
|
connectionStyle: LineType.THICK_CURVED,
|
||||||
|
connectionColor: '#345780',
|
||||||
|
shapeType: 'line' as TopicShapeType,
|
||||||
|
outerBackgroundColor: '#F4B82D',
|
||||||
|
outerBorderColor: '#F4B82D',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'SubTopic',
|
||||||
|
{
|
||||||
|
msgKey: 'SUB_TOPIC',
|
||||||
|
borderColor: '#96e3ff',
|
||||||
|
backgroundColor: '#96e3ff',
|
||||||
|
fontFamily: 'Verdana',
|
||||||
|
fontSize: 8,
|
||||||
|
fontStyle: 'normal' as FontStyleType,
|
||||||
|
fontWeight: 'normal' as FontWeightType,
|
||||||
|
fontColor: '#525C61',
|
||||||
|
connectionStyle: LineType.THICK_CURVED,
|
||||||
|
connectionColor: '#345780',
|
||||||
|
shapeType: 'line' as TopicShapeType,
|
||||||
|
outerBackgroundColor: '#F4B82D',
|
||||||
|
outerBorderColor: '#F4B82D',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'IsolatedTopic',
|
||||||
|
{
|
||||||
|
msgKey: 'ISOLATED_TOPIC',
|
||||||
|
borderColor: '#023BB9',
|
||||||
|
backgroundColor: '#96e3ff',
|
||||||
|
fontFamily: 'Verdana',
|
||||||
|
fontSize: 8,
|
||||||
|
fontStyle: 'normal' as FontStyleType,
|
||||||
|
fontWeight: 'normal' as FontWeightType,
|
||||||
|
fontColor: '#525C61',
|
||||||
|
connectionStyle: LineType.THICK_CURVED,
|
||||||
|
connectionColor: '#345780',
|
||||||
|
shapeType: 'line' as TopicShapeType,
|
||||||
|
outerBackgroundColor: '#F4B82D',
|
||||||
|
outerBorderColor: '#F4B82D',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
class ClassicTheme extends DefaultTheme {
|
||||||
|
constructor() {
|
||||||
|
super(defaultStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCanvasCssStyle(): string {
|
||||||
|
return `position: relative;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 1;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
background-image: linear-gradient(#ebe9e7 1px, transparent 1px),
|
||||||
|
linear-gradient(to right, #ebe9e7 1px, #f2f2f2 1px);
|
||||||
|
background-size: 50px 50px;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ClassicTheme;
|
247
packages/mindplot/src/components/theme/DefaultTheme.ts
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Copyright [2021] [wisemapping]
|
||||||
|
*
|
||||||
|
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||||
|
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||||
|
* "powered by wisemapping" text requirement on every single page;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the license at
|
||||||
|
*
|
||||||
|
* http://www.wisemapping.org/license
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { LineType } from '../ConnectionLine';
|
||||||
|
import { FontStyleType } from '../FontStyleType';
|
||||||
|
import { FontWeightType } from '../FontWeightType';
|
||||||
|
import { TopicShapeType } from '../model/INodeModel';
|
||||||
|
import NodeModel from '../model/NodeModel';
|
||||||
|
import ColorUtil from './ColorUtil';
|
||||||
|
import Topic from '../Topic';
|
||||||
|
import Theme, { TopicType } from './Theme';
|
||||||
|
import { $msg } from '../Messages';
|
||||||
|
|
||||||
|
export type TopicStyleType = {
|
||||||
|
borderColor: string | string[];
|
||||||
|
backgroundColor: string | string[];
|
||||||
|
connectionColor: string | string[];
|
||||||
|
connectionStyle: LineType;
|
||||||
|
fontFamily: string;
|
||||||
|
fontSize: number;
|
||||||
|
fontStyle: FontStyleType;
|
||||||
|
fontWeight: FontWeightType;
|
||||||
|
fontColor: string;
|
||||||
|
msgKey: string;
|
||||||
|
shapeType: TopicShapeType;
|
||||||
|
outerBackgroundColor: string;
|
||||||
|
outerBorderColor: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StyleType = string | string[] | number | undefined | LineType;
|
||||||
|
|
||||||
|
const keyToModel = new Map<keyof TopicStyleType, (model: NodeModel) => StyleType>([
|
||||||
|
['borderColor', (m: NodeModel) => m.getBorderColor()],
|
||||||
|
['backgroundColor', (m: NodeModel) => m.getBackgroundColor()],
|
||||||
|
['shapeType', (m: NodeModel) => m.getShapeType()],
|
||||||
|
['connectionStyle', (m: NodeModel) => m.getConnectionStyle()],
|
||||||
|
['connectionColor', (m: NodeModel) => m.getConnectionColor()],
|
||||||
|
['fontFamily', (m: NodeModel) => m.getFontFamily()],
|
||||||
|
['fontColor', (m: NodeModel) => m.getFontColor()],
|
||||||
|
['fontWeight', (m: NodeModel) => m.getFontWeight()],
|
||||||
|
['fontSize', (m: NodeModel) => m.getFontSize()],
|
||||||
|
['fontStyle', (m: NodeModel) => m.getFontStyle()],
|
||||||
|
]);
|
||||||
|
|
||||||
|
abstract class DefaultTheme implements Theme {
|
||||||
|
private _style: Map<TopicType, TopicStyleType>;
|
||||||
|
|
||||||
|
constructor(style: Map<TopicType, TopicStyleType>) {
|
||||||
|
this._style = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract getCanvasCssStyle(): string;
|
||||||
|
|
||||||
|
protected resolve(key: keyof TopicStyleType, topic: Topic, resolveDefault = true): StyleType {
|
||||||
|
// Search parent value ...
|
||||||
|
const recurviveModelStrategy = (value: keyof TopicStyleType, t: Topic): StyleType => {
|
||||||
|
const model = t.getModel();
|
||||||
|
let result: StyleType = keyToModel.get(key)!(model);
|
||||||
|
|
||||||
|
const parent = t.getParent();
|
||||||
|
if (!result && parent) {
|
||||||
|
result = recurviveModelStrategy(value, parent);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Can be found in the model or parent ?
|
||||||
|
let result = recurviveModelStrategy(key, topic);
|
||||||
|
if (!result && resolveDefault) {
|
||||||
|
result = this.getStyles(topic)[key];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getStyles(topic: Topic): TopicStyleType {
|
||||||
|
let result: TopicStyleType;
|
||||||
|
if (topic.isCentralTopic()) {
|
||||||
|
result = this._style.get('CentralTopic')!;
|
||||||
|
} else {
|
||||||
|
const targetTopic = topic.getOutgoingConnectedTopic();
|
||||||
|
if (targetTopic) {
|
||||||
|
if (targetTopic.isCentralTopic()) {
|
||||||
|
result = this._style.get('MainTopic')!;
|
||||||
|
} else {
|
||||||
|
result = this._style.get('SubTopic')!;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = this._style.get('IsolatedTopic')!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBackgroundColor(topic: Topic): string {
|
||||||
|
const model = topic.getModel();
|
||||||
|
let result = model.getBackgroundColor();
|
||||||
|
if (!result && !topic.isCentralTopic()) {
|
||||||
|
// Be sure that not overwride default background color ...
|
||||||
|
const borderColor = model.getBorderColor();
|
||||||
|
if (borderColor) {
|
||||||
|
result = ColorUtil.lightenColor(borderColor, 40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
let colors: string[] = [];
|
||||||
|
colors = colors.concat(this.resolve('backgroundColor', topic) as string[] | string);
|
||||||
|
|
||||||
|
// if the element is an array, use topic order to decide color ..
|
||||||
|
let order = topic.getOrder();
|
||||||
|
order = order || 0;
|
||||||
|
|
||||||
|
const index = order % colors.length;
|
||||||
|
result = colors[index];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getShapeType(topic: Topic): TopicShapeType {
|
||||||
|
const result = this.resolve('shapeType', topic) as TopicShapeType;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getConnectionType(topic: Topic): LineType {
|
||||||
|
return this.resolve('connectionStyle', topic) as LineType;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFontFamily(topic: Topic): string {
|
||||||
|
return this.resolve('fontFamily', topic) as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFontSize(topic: Topic): number {
|
||||||
|
return this.resolve('fontSize', topic) as number;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFontStyle(topic: Topic): FontStyleType {
|
||||||
|
return this.resolve('fontStyle', topic) as FontStyleType;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFontWeight(topic: Topic): FontWeightType {
|
||||||
|
return this.resolve('fontWeight', topic) as FontWeightType;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFontColor(topic: Topic): string {
|
||||||
|
return this.resolve('fontColor', topic) as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBorderColor(topic: Topic): string {
|
||||||
|
const model = topic.getModel();
|
||||||
|
let result = model.getBorderColor();
|
||||||
|
|
||||||
|
// If the the style is a line, the color is alward the connection one.
|
||||||
|
if (topic.getShapeType() === 'line') {
|
||||||
|
result = topic.getConnectionColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result === undefined) {
|
||||||
|
const parent = topic.getParent();
|
||||||
|
if (parent) {
|
||||||
|
result = parent.getBorderColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If border color has not been defined, use the connection color for the border ...
|
||||||
|
if (!result) {
|
||||||
|
result = topic.getConnectionColor();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getOuterBorderColor(topic: Topic): string {
|
||||||
|
let result: string;
|
||||||
|
if (topic.getShapeType() === 'line') {
|
||||||
|
result = this.getStyles(topic).outerBorderColor;
|
||||||
|
} else {
|
||||||
|
const innerBorderColor = topic.getBorderColor();
|
||||||
|
result = ColorUtil.lightenColor(innerBorderColor, 70);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getOuterBackgroundColor(topic: Topic, onFocus: boolean): string {
|
||||||
|
let result: string;
|
||||||
|
if (topic.getShapeType() === 'line') {
|
||||||
|
const color = this.getStyles(topic).outerBackgroundColor;
|
||||||
|
result = onFocus ? color : ColorUtil.lightenColor(color, 30);
|
||||||
|
} else {
|
||||||
|
const innerBgColor = topic.getBackgroundColor();
|
||||||
|
result = ColorUtil.lightenColor(innerBgColor, 70);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInnerPadding(topic: Topic): number {
|
||||||
|
return topic.getOrBuildTextShape().getFontHeight() * 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
getText(topic: Topic): string {
|
||||||
|
const { msgKey } = this.getStyles(topic);
|
||||||
|
return $msg(msgKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
getConnectionColor(topic: Topic): string {
|
||||||
|
const model = topic.getModel();
|
||||||
|
let result: string | undefined = model.getConnectionColor();
|
||||||
|
|
||||||
|
// Style is infered looking recursivelly on the parent nodes.
|
||||||
|
if (!result) {
|
||||||
|
const parent = topic.getParent();
|
||||||
|
if (parent && parent.isCentralTopic()) {
|
||||||
|
// This means that this is central main node, in this case, I will overwrite with the main color if it was defined.
|
||||||
|
result = topic.getModel().getConnectionColor() || parent.getModel().getConnectionColor();
|
||||||
|
} else {
|
||||||
|
result = parent?.getConnectionColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
let colors: string[] = [];
|
||||||
|
colors = colors.concat(this.resolve('connectionColor', topic) as string[] | string);
|
||||||
|
|
||||||
|
// if the element is an array, use topic order to decide color ..
|
||||||
|
let order = topic.getOrder();
|
||||||
|
order = order || 0;
|
||||||
|
|
||||||
|
const index = order % colors.length;
|
||||||
|
result = colors[index];
|
||||||
|
}
|
||||||
|
return result!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default DefaultTheme;
|
201
packages/mindplot/src/components/theme/PrismTheme.ts
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright [2011] [wisemapping]
|
||||||
|
*
|
||||||
|
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||||
|
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||||
|
* "powered by wisemapping" text requirement on every single page;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the license at
|
||||||
|
*
|
||||||
|
* http://www.wisemapping.org/license
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
import { LineType } from '../ConnectionLine';
|
||||||
|
import { FontStyleType } from '../FontStyleType';
|
||||||
|
import { FontWeightType } from '../FontWeightType';
|
||||||
|
import { TopicShapeType } from '../model/INodeModel';
|
||||||
|
import Topic from '../Topic';
|
||||||
|
import DefaultTheme, { TopicStyleType } from './DefaultTheme';
|
||||||
|
import { TopicType } from './Theme';
|
||||||
|
|
||||||
|
const defaultStyles = new Map<TopicType, TopicStyleType>([
|
||||||
|
[
|
||||||
|
'CentralTopic',
|
||||||
|
{
|
||||||
|
msgKey: 'CENTRAL_TOPIC',
|
||||||
|
borderColor: '#FFFFFF',
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
fontFamily: 'Verdana',
|
||||||
|
fontSize: 10,
|
||||||
|
fontStyle: 'normal' as FontStyleType,
|
||||||
|
fontWeight: 'bold' as FontWeightType,
|
||||||
|
fontColor: '#000000',
|
||||||
|
connectionStyle: LineType.ARC,
|
||||||
|
connectionColor: '#345780',
|
||||||
|
shapeType: 'rounded rectangle' as TopicShapeType,
|
||||||
|
outerBackgroundColor: '#F4B82D',
|
||||||
|
outerBorderColor: '#F4B82D',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'MainTopic',
|
||||||
|
{
|
||||||
|
msgKey: 'MAIN_TOPIC',
|
||||||
|
borderColor: [
|
||||||
|
'#9B7BEB',
|
||||||
|
'#E5628C',
|
||||||
|
'#EB5130',
|
||||||
|
'#F3AE3D',
|
||||||
|
'#F8D651',
|
||||||
|
'#A5D945',
|
||||||
|
'#6BC953',
|
||||||
|
'#6AD6D7',
|
||||||
|
'#4CA6F7',
|
||||||
|
'#4B6FF6',
|
||||||
|
],
|
||||||
|
backgroundColor: [
|
||||||
|
'#9B7BEB',
|
||||||
|
'#E5628C',
|
||||||
|
'#EB5130',
|
||||||
|
'#F3AE3D',
|
||||||
|
'#F8D651',
|
||||||
|
'#A5D945',
|
||||||
|
'#6BC953',
|
||||||
|
'#6AD6D7',
|
||||||
|
'#4CA6F7',
|
||||||
|
'#4B6FF6',
|
||||||
|
],
|
||||||
|
connectionColor: [
|
||||||
|
'#9B7BEB',
|
||||||
|
'#E5628C',
|
||||||
|
'#EB5130',
|
||||||
|
'#F3AE3D',
|
||||||
|
'#F8D651',
|
||||||
|
'#A5D945',
|
||||||
|
'#6BC953',
|
||||||
|
'#6AD6D7',
|
||||||
|
'#4CA6F7',
|
||||||
|
'#4B6FF6',
|
||||||
|
],
|
||||||
|
fontFamily: 'Verdana',
|
||||||
|
fontSize: 9,
|
||||||
|
fontStyle: 'normal' as FontStyleType,
|
||||||
|
fontWeight: 'normal' as FontWeightType,
|
||||||
|
fontColor: '#000000',
|
||||||
|
connectionStyle: LineType.ARC,
|
||||||
|
shapeType: 'rounded rectangle' as TopicShapeType,
|
||||||
|
outerBackgroundColor: '#F4B82D',
|
||||||
|
outerBorderColor: '#F4B82D',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'SubTopic',
|
||||||
|
{
|
||||||
|
msgKey: 'SUB_TOPIC',
|
||||||
|
borderColor: '#96e3ff',
|
||||||
|
backgroundColor: '#96e3ff',
|
||||||
|
fontFamily: 'Verdana',
|
||||||
|
fontSize: 8,
|
||||||
|
fontStyle: 'normal' as FontStyleType,
|
||||||
|
fontWeight: 'normal' as FontWeightType,
|
||||||
|
fontColor: '#000000',
|
||||||
|
connectionStyle: LineType.THICK_CURVED,
|
||||||
|
connectionColor: '#345780',
|
||||||
|
shapeType: 'line' as TopicShapeType,
|
||||||
|
outerBackgroundColor: '#F4B82D',
|
||||||
|
outerBorderColor: '#F4B82D',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'IsolatedTopic',
|
||||||
|
{
|
||||||
|
msgKey: 'ISOLATED_TOPIC',
|
||||||
|
borderColor: '#023BB9',
|
||||||
|
backgroundColor: '#96e3ff',
|
||||||
|
fontFamily: 'Verdana',
|
||||||
|
fontSize: 8,
|
||||||
|
fontStyle: 'normal' as FontStyleType,
|
||||||
|
fontWeight: 'normal' as FontWeightType,
|
||||||
|
fontColor: '#000000',
|
||||||
|
connectionStyle: LineType.THICK_CURVED,
|
||||||
|
connectionColor: '#345780',
|
||||||
|
shapeType: 'line' as TopicShapeType,
|
||||||
|
outerBackgroundColor: '#F4B82D',
|
||||||
|
outerBorderColor: '#F4B82D',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
class PrismTheme extends DefaultTheme {
|
||||||
|
constructor() {
|
||||||
|
super(defaultStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCanvasCssStyle(): string {
|
||||||
|
return `position: relative;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 1;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
background-image: linear-gradient(#ebe9e7 1px, transparent 1px),
|
||||||
|
linear-gradient(to right, #ebe9e7 1px, #f2f2f2 1px);
|
||||||
|
background-size: 50px 50px;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;`;
|
||||||
|
}
|
||||||
|
|
||||||
|
getConnectionColor(topic: Topic): string {
|
||||||
|
const model = topic.getModel();
|
||||||
|
let result: string | undefined = model.getConnectionColor();
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
let colors: string[] = [];
|
||||||
|
colors = colors.concat(this.resolve('connectionColor', topic) as string[] | string);
|
||||||
|
|
||||||
|
// if the element is an array, use topic order to decide color ..
|
||||||
|
let order = topic.getOrder();
|
||||||
|
order = order || 0;
|
||||||
|
|
||||||
|
const index = order % colors.length;
|
||||||
|
result = colors[index];
|
||||||
|
}
|
||||||
|
return result!;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBorderColor(topic: Topic): string {
|
||||||
|
const model = topic.getModel();
|
||||||
|
let result = model.getBorderColor();
|
||||||
|
|
||||||
|
// If the the style is a line, the color is alward the connection one.
|
||||||
|
|
||||||
|
// If border color has not been defined, use the connection color for the border ...
|
||||||
|
if (!result) {
|
||||||
|
if (topic.getShapeType() === 'line') {
|
||||||
|
result = 'none';
|
||||||
|
} else {
|
||||||
|
let colors: string[] = [];
|
||||||
|
colors = colors.concat(this.resolve('borderColor', topic) as string[] | string);
|
||||||
|
|
||||||
|
// if the element is an array, use topic order to decide color ..
|
||||||
|
let order = topic.getOrder();
|
||||||
|
order = order || 0;
|
||||||
|
|
||||||
|
const index = order % colors.length;
|
||||||
|
result = colors[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PrismTheme;
|
57
packages/mindplot/src/components/theme/Theme.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright [2021] [wisemapping]
|
||||||
|
*
|
||||||
|
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
|
||||||
|
* It is basically the Apache License, Version 2.0 (the "License") plus the
|
||||||
|
* "powered by wisemapping" text requirement on every single page;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the license at
|
||||||
|
*
|
||||||
|
* http://www.wisemapping.org/license
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { LineType } from '../ConnectionLine';
|
||||||
|
import { FontStyleType } from '../FontStyleType';
|
||||||
|
import { FontWeightType } from '../FontWeightType';
|
||||||
|
import { TopicShapeType } from '../model/INodeModel';
|
||||||
|
import Topic from '../Topic';
|
||||||
|
|
||||||
|
export type TopicType = 'CentralTopic' | 'MainTopic' | 'SubTopic' | 'IsolatedTopic';
|
||||||
|
interface Theme {
|
||||||
|
getText(topic: Topic): string;
|
||||||
|
|
||||||
|
getFontFamily(topic: Topic): string;
|
||||||
|
|
||||||
|
getFontSize(topic: Topic): number;
|
||||||
|
|
||||||
|
getFontStyle(topic: Topic): FontStyleType;
|
||||||
|
|
||||||
|
getFontWeight(topic: Topic): FontWeightType;
|
||||||
|
|
||||||
|
getFontColor(topic: Topic): string;
|
||||||
|
|
||||||
|
getCanvasCssStyle(): string;
|
||||||
|
|
||||||
|
getOuterBorderColor(topic: Topic): string;
|
||||||
|
|
||||||
|
getOuterBackgroundColor(topic: Topic, onFocus: boolean): string;
|
||||||
|
|
||||||
|
getBackgroundColor(topic: Topic): string;
|
||||||
|
|
||||||
|
getBorderColor(topic: Topic): string;
|
||||||
|
|
||||||
|
getInnerPadding(topic: Topic): number;
|
||||||
|
|
||||||
|
getShapeType(topic: Topic): TopicShapeType;
|
||||||
|
|
||||||
|
getConnectionType(topic: Topic): LineType;
|
||||||
|
|
||||||
|
getConnectionColor(topic: Topic): string;
|
||||||
|
}
|
||||||
|
export default Theme;
|
36
packages/mindplot/src/components/theme/ThemeFactory.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import NodeModel from '../model/NodeModel';
|
||||||
|
import ClassicTheme from './ClassicTheme';
|
||||||
|
import PrismTheme from './PrismTheme';
|
||||||
|
import Theme from './Theme';
|
||||||
|
|
||||||
|
type ThemeId = 'prism' | 'classic';
|
||||||
|
|
||||||
|
class ThemeFactory {
|
||||||
|
private static prismTheme = new PrismTheme();
|
||||||
|
|
||||||
|
private static classicTheme = new ClassicTheme();
|
||||||
|
|
||||||
|
static createById(id: ThemeId): Theme {
|
||||||
|
let result: Theme;
|
||||||
|
switch (id) {
|
||||||
|
case 'classic':
|
||||||
|
result = ThemeFactory.classicTheme;
|
||||||
|
break;
|
||||||
|
case 'prism':
|
||||||
|
result = ThemeFactory.prismTheme;
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
const exhaustiveCheck: never = id;
|
||||||
|
throw new Error(exhaustiveCheck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static create(model: NodeModel): Theme {
|
||||||
|
const mindmap = model.getMindmap();
|
||||||
|
const theme = mindmap.getTheme();
|
||||||
|
return ThemeFactory.createById(theme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default ThemeFactory;
|
@ -35,7 +35,7 @@ class ArcLine extends ArcLine2d {
|
|||||||
let xOffset = x;
|
let xOffset = x;
|
||||||
if (this._targetTopic.isCentralTopic()) {
|
if (this._targetTopic.isCentralTopic()) {
|
||||||
const sourceX = this._sourceTopic.getPosition().x;
|
const sourceX = this._sourceTopic.getPosition().x;
|
||||||
xOffset = Math.sign(sourceX) * (this._targetTopic.getSize().width / 3);
|
xOffset = Math.sign(sourceX) * 10;
|
||||||
} else {
|
} else {
|
||||||
xOffset = x + 3 * Math.sign(x);
|
xOffset = x + 3 * Math.sign(x);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ class LineTopicShape extends StraightLine {
|
|||||||
private _size: SizeType | null;
|
private _size: SizeType | null;
|
||||||
|
|
||||||
constructor(topic: Topic, attributes?: StyleAttributes) {
|
constructor(topic: Topic, attributes?: StyleAttributes) {
|
||||||
const stokeColor = topic.getConnectionColor();
|
const stokeColor = topic.getBorderColor();
|
||||||
super({ ...attributes, strokeColor: stokeColor });
|
super({ ...attributes, strokeColor: stokeColor });
|
||||||
this._size = null;
|
this._size = null;
|
||||||
}
|
}
|
||||||
|