Skip to content

Commit

Permalink
feat: basic shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
bubkoo committed Mar 25, 2020
1 parent d753ee5 commit da33dba
Show file tree
Hide file tree
Showing 12 changed files with 428 additions and 0 deletions.
21 changes: 21 additions & 0 deletions packages/x6/src/research/shape/basic/circle.ts
@@ -0,0 +1,21 @@
import { NodeRegistry } from '../../registry'
import { getMarkup, getName, rootAttr, shapeAttr, textAttr } from './util'

export const Circle = NodeRegistry.register(getName('circle'), {
markup: getMarkup('circle'),
size: { width: 60, height: 60 },
attrs: {
...rootAttr,
circle: {
...shapeAttr,
r: 30,
cx: 30,
cy: 30,
},
text: {
...textAttr,
refX: 0.5,
refY: 0.5,
},
},
})
22 changes: 22 additions & 0 deletions packages/x6/src/research/shape/basic/ellipse.ts
@@ -0,0 +1,22 @@
import { NodeRegistry } from '../../registry'
import { getMarkup, getName, rootAttr, shapeAttr, textAttr } from './util'

export const Ellipse = NodeRegistry.register(getName('ellipse'), {
markup: getMarkup('ellipse'),
size: { width: 60, height: 40 },
attrs: {
...rootAttr,
ellipse: {
...shapeAttr,
rx: 30,
ry: 20,
cx: 30,
cy: 20,
},
text: {
...textAttr,
refX: 0.5,
refY: 0.5,
},
},
})
14 changes: 14 additions & 0 deletions packages/x6/src/research/shape/basic/image.ts
@@ -0,0 +1,14 @@
import { NodeRegistry } from '../../registry'
import { getMarkup, getName, rootAttr, textAttr } from './util'

export const Image = NodeRegistry.register(getName('image'), {
markup: getMarkup('image'),
attrs: {
...rootAttr,
text: {
...textAttr,
refX: 0.5,
refDy: 20,
},
},
})
10 changes: 10 additions & 0 deletions packages/x6/src/research/shape/basic/index.ts
@@ -0,0 +1,10 @@
export * from './rect'
export * from './circle'
export * from './ellipse'
export * from './polygon'
export * from './polyline'
export * from './image'
export * from './path'
export * from './rhombus'
export * from './text'
export * from './text-block'
19 changes: 19 additions & 0 deletions packages/x6/src/research/shape/basic/path.ts
@@ -0,0 +1,19 @@
import { NodeRegistry } from '../../registry'
import { getMarkup, getName, rootAttr, shapeAttr, textAttr } from './util'

export const Path = NodeRegistry.register(getName('path'), {
markup: getMarkup('path'),
size: { width: 60, height: 60 },
attrs: {
...rootAttr,
path: {
...shapeAttr,
},
text: {
...textAttr,
ref: 'path',
refX: 0.5,
refDy: 10,
},
},
})
18 changes: 18 additions & 0 deletions packages/x6/src/research/shape/basic/polygon.ts
@@ -0,0 +1,18 @@
import { NodeRegistry } from '../../registry'
import { getMarkup, getName, rootAttr, shapeAttr, textAttr } from './util'

export const Polygon = NodeRegistry.register(getName('polygon'), {
markup: getMarkup('polygon'),
size: { width: 60, height: 40 },
attrs: {
...rootAttr,
polygon: {
...shapeAttr,
},
text: {
...textAttr,
refX: 0.5,
refDy: 20,
},
},
})
18 changes: 18 additions & 0 deletions packages/x6/src/research/shape/basic/polyline.ts
@@ -0,0 +1,18 @@
import { NodeRegistry } from '../../registry'
import { getMarkup, getName, rootAttr, shapeAttr, textAttr } from './util'

export const Polyline = NodeRegistry.register(getName('polyline'), {
markup: getMarkup('polyline'),
size: { width: 60, height: 40 },
attrs: {
...rootAttr,
polyline: {
...shapeAttr,
},
text: {
...textAttr,
refX: 0.5,
refDy: 20,
},
},
})
19 changes: 19 additions & 0 deletions packages/x6/src/research/shape/basic/rect.ts
@@ -0,0 +1,19 @@
import { NodeRegistry } from '../../registry'
import { getMarkup, getName, rootAttr, shapeAttr, textAttr } from './util'

export const Rect = NodeRegistry.register(getName('rect'), {
markup: getMarkup('rect'),
attrs: {
...rootAttr,
rect: {
...shapeAttr,
width: 100,
height: 60,
},
text: {
...textAttr,
refX: 0.5,
refY: 0.5,
},
},
})
17 changes: 17 additions & 0 deletions packages/x6/src/research/shape/basic/rhombus.ts
@@ -0,0 +1,17 @@
import { NodeRegistry } from '../../registry'
import { getName } from './util'
import './path'

export const Rhombus = NodeRegistry.register(getName('rhombus'), {
inherit: getName('path'),
attrs: {
path: {
d: 'M 30 0 L 60 30 30 60 0 30 z',
},
text: {
refY: 0.5,
refDy: null,
yAlignment: 'middle',
},
},
})
204 changes: 204 additions & 0 deletions packages/x6/src/research/shape/basic/text-block.ts
@@ -0,0 +1,204 @@
import { Platform, StringExt, ObjectExt } from '../../../util'
import { Size } from '../../../types'
import { Attr } from '../../attr'
import { Node } from '../../core/node'
import { Store } from '../../core/store'
import { NodeView } from '../../core/node-view'
import { NodeRegistry, ViewRegistry } from '../../registry'
import { getName, rootAttr } from './util'

const contentAction = 'content' as any
const contentSelector = '.text-block-content'
const registryName = getName('text-block')

export class TextBlock extends Node {
public readonly store: Store<TextBlock.Properties>

get content() {
return this.getContent()
}

set content(val: string) {
this.setContent(val)
}

getContent() {
return this.store.get('content', '')
}

setContent(content?: string, options: Node.SetOptions = {}) {
this.store.set('content', content, options)
}

protected setup() {
super.setup()
this.store.on('mutated', metadata => {
const key = metadata.key
if (key === 'content') {
this.updateContent(this.getContent())
} else if (key === 'size') {
this.updateSize(this.getSize())
}
})

this.updateSize(this.getSize())
this.updateContent(this.getContent())
}

protected updateSize(size: Size) {
if (Platform.SUPPORT_FOREIGNOBJECT) {
this.setAttrs({
foreignObject: { ...size },
[contentSelector]: {
style: { ...size },
},
})
}
}

protected updateContent(content?: string) {
if (Platform.SUPPORT_FOREIGNOBJECT) {
this.setAttrs({
[contentSelector]: {
html: content ? StringExt.sanitizeHTML(content) : '',
},
})
} else {
this.setAttrs({
[contentSelector]: {
text: content,
},
})
}
}
}

export namespace TextBlock {
export interface Properties extends Node.Properties {
content?: string
}
}

export class TextBlockView extends NodeView<TextBlock> {
confirmUpdate(flag: number, options: any = {}) {
let ret = super.confirmUpdate(flag, options)
if (this.hasAction(ret, contentAction)) {
this.updateContent()
ret = this.removeAction(ret, contentAction)
}
return ret
}

update(partialAttrs?: Attr.CellAttrs) {
if (Platform.SUPPORT_FOREIGNOBJECT) {
super.update(partialAttrs)
} else {
const node = this.cell
const attrs = { ...(partialAttrs || node.getAttrs()) }
delete attrs[contentSelector]
super.update(attrs)
if (!partialAttrs || ObjectExt.has(partialAttrs, contentSelector)) {
this.updateContent(partialAttrs)
}
}
}

updateContent(partialAttrs?: Attr.CellAttrs) {
if (Platform.SUPPORT_FOREIGNOBJECT) {
super.update(partialAttrs)
} else {
const node = this.cell
const textAttrs = (partialAttrs || node.getAttrs())[contentSelector]

// Break the text to fit the node size taking into
// account the attributes set on the node.
const text = StringExt.breakText(
node.getContent(),
node.getSize(),
textAttrs,
{
svgDocument: this.graph.svg,
},
)

const attrs = {
[contentSelector]: ObjectExt.merge({}, textAttrs, { text }),
}

super.update(attrs)
}
}
}

TextBlock.config({
view: registryName,

markup: [
'<g class="rotatable">',
'<g class="scalable"><rect/></g>',
Platform.SUPPORT_FOREIGNOBJECT
? [
`<foreignObject>`,
`<body xmlns="http://www.w3.org/1999/xhtml">`,
`<div class="${contentSelector.substr(1)}" />`,
`</body>`,
`</foreignObject>`,
].join('')
: `<text class="${contentSelector.substr(1)}"/>`,
'</g>',
].join(''),

attrs: {
...rootAttr,
rect: {
fill: '#ffffff',
stroke: '#000000',
width: 80,
height: 100,
},
text: {
fill: '#000000',
fontSize: 14,
fontFamily: 'Arial, helvetica, sans-serif',
},
body: {
style: {
background: 'transparent',
position: 'static',
margin: 0,
padding: 0,
},
},
foreignObject: {
style: {
overflow: 'hidden',
},
},
[contentSelector]: {
refX: 0.5,
refY: 0.5,
yAlignment: 'middle',
xAlignment: 'middle',
style: {
textAlign: 'center',
verticalAlign: 'middle',
display: 'table-cell',
padding: '0 5px',
margin: 0,
},
},
},
})

TextBlockView.config({
bootstrap: ['render', contentAction],
actions: Platform.SUPPORT_FOREIGNOBJECT
? {}
: {
size: contentAction,
content: contentAction,
},
})

NodeRegistry.register(registryName, TextBlock)
ViewRegistry.register(registryName, TextBlockView)

0 comments on commit da33dba

Please sign in to comment.