From 37c0b2465b01797b48f132a1b89c39ff28470e18 Mon Sep 17 00:00:00 2001 From: Ctank Date: Wed, 14 Aug 2019 17:27:23 +0800 Subject: [PATCH] feat(*): dblclick set title --- src/assets/styles/bpd-core.scss | 1 + src/assets/styles/features/_edit-name.scss | 19 +++ src/core/designer.js | 2 + src/draw/draw.js | 6 + src/draw/drawShape.js | 18 ++- src/draw/shape/Base.js | 4 +- src/draw/shape/EndEvent.js | 14 +- src/draw/shape/ServiceTask.js | 3 + src/draw/shape/StartEvent.js | 14 +- src/draw/shape/TerminateEndEvent.js | 14 +- src/draw/shape/UserTask.js | 18 ++- src/features/edit-name/editName.js | 168 +++++++++++++++++++++ src/features/edit-name/index.js | 3 + src/features/select/select.js | 1 - src/main.js | 3 + static/index.html | 9 +- 16 files changed, 281 insertions(+), 16 deletions(-) create mode 100644 src/assets/styles/features/_edit-name.scss create mode 100644 src/features/edit-name/editName.js create mode 100644 src/features/edit-name/index.js diff --git a/src/assets/styles/bpd-core.scss b/src/assets/styles/bpd-core.scss index 6f29f63..cc1aba5 100644 --- a/src/assets/styles/bpd-core.scss +++ b/src/assets/styles/bpd-core.scss @@ -7,3 +7,4 @@ @import './features/select'; @import './features/snapline'; @import './features/tooltip'; +@import './features/edit-name'; diff --git a/src/assets/styles/features/_edit-name.scss b/src/assets/styles/features/_edit-name.scss new file mode 100644 index 0000000..64d4f1d --- /dev/null +++ b/src/assets/styles/features/_edit-name.scss @@ -0,0 +1,19 @@ +.shape-name-edit { + position: absolute; + overflow: hidden; + background: #ffffff; + border: 1px solid #000000; + border-radius: 2px; + padding: 0px; + cursor: text; + z-index: 10; +} + +.shape-name-temp { + padding: 0px; + border: none; + background: transparent; + opacity: 0; + height: 0px; + overflow: hidden; +} diff --git a/src/core/designer.js b/src/core/designer.js index c7ddf30..b0433f7 100644 --- a/src/core/designer.js +++ b/src/core/designer.js @@ -395,6 +395,7 @@ class Designer { for (let key in data) { switch (key) { // 不处理 + case '$instanceOf': case '$type': case 'flowElements': case 'sourceRef': @@ -422,6 +423,7 @@ class Designer { for (let key in plane) { switch (key) { // 不处理 + case '$instanceOf': case '$type': break // id与数据id对应 diff --git a/src/draw/draw.js b/src/draw/draw.js index ff0d5ce..8092c09 100644 --- a/src/draw/draw.js +++ b/src/draw/draw.js @@ -36,10 +36,16 @@ class Draw extends Operation { this.init() } init() { + // 移动 this.$container .off('mousemove.operate touchstart.operate') .on('mousemove.operate touchstart.operate', this.move.bind(this)) + // 双击 + this.$container.off('dblclick.element').on('dblclick.element', () => { + eventBus.trigger('edit.shape.name') + }) + // 创建图形 eventBus.on('shape.create', this.createShapeData.bind(this)) // 渲染图形 diff --git a/src/draw/drawShape.js b/src/draw/drawShape.js index 885d3fb..ff46599 100644 --- a/src/draw/drawShape.js +++ b/src/draw/drawShape.js @@ -248,15 +248,19 @@ class DrawShape { const scrollTop = $textBox.scrollTop() let top = 0 - if (fontStyle.vAlign === 'middle') { - top = textBlock.y + textBlock.height / 2 - scrollTop / 2 - } else { - if (shape.fontStyle.vAlign === 'bottom') { + let margin = 10 + switch (fontStyle.vAlign) { + case 'middle': + top = textBlock.y + textBlock.height / 2 - scrollTop / 2 + break + case 'bottom': top = textBlock.y + textBlock.height - scrollTop - } else { - top = textBlock.y - } + break + default: + top = textBlock.y += margin + break } + let position = { x: textBlock.x + textBlock.width / 2, y: top + scrollTop / 2 diff --git a/src/draw/shape/Base.js b/src/draw/shape/Base.js index 684177c..0014ae2 100644 --- a/src/draw/shape/Base.js +++ b/src/draw/shape/Base.js @@ -15,13 +15,13 @@ class Base { // 字体样式 this.fontStyle = { fontFamily: 'Arial', - size: 13, + size: 12, color: '50,50,50', bold: false, italic: false, underline: false, textAlign: 'center', - vAlign: 'middle', + vAlign: 'top', orientation: 'vertical' } } diff --git a/src/draw/shape/EndEvent.js b/src/draw/shape/EndEvent.js index c5b0243..f2f8029 100644 --- a/src/draw/shape/EndEvent.js +++ b/src/draw/shape/EndEvent.js @@ -95,8 +95,20 @@ class EndEvent extends Shape { * 获取文本范围 */ getTextBlock() { + const { textStyle } = this.style const { height, width } = this.plane.bounds - return { x: width / 2 - 60, y: height, width: 120, height: 30 } + let textWidth = 120 + let textHeight = 30 + if (textStyle) { + textWidth = textStyle.width || textWidth + textHeight = textStyle.height || textHeight + } + return { + x: width / 2 - textWidth / 2, + y: height, + width: textWidth, + height: textHeight + } } } diff --git a/src/draw/shape/ServiceTask.js b/src/draw/shape/ServiceTask.js index dc45904..b0f9978 100644 --- a/src/draw/shape/ServiceTask.js +++ b/src/draw/shape/ServiceTask.js @@ -24,6 +24,9 @@ class ServiceTask extends Shape { this.groupName = 'Task' + // 字体样式 + this.fontStyle.vAlign = 'middle' + this.actions = this.getPath() } /** diff --git a/src/draw/shape/StartEvent.js b/src/draw/shape/StartEvent.js index b9cd261..b9c3dd7 100644 --- a/src/draw/shape/StartEvent.js +++ b/src/draw/shape/StartEvent.js @@ -92,8 +92,20 @@ class StartEvent extends Shape { * 获取文本范围 */ getTextBlock() { + const { textStyle } = this.style const { height, width } = this.plane.bounds - return { x: width / 2 - 60, y: height, width: 120, height: 30 } + let textWidth = 120 + let textHeight = 30 + if (textStyle) { + textWidth = textStyle.width || textWidth + textHeight = textStyle.height || textHeight + } + return { + x: width / 2 - textWidth / 2, + y: height, + width: textWidth, + height: textHeight + } } } diff --git a/src/draw/shape/TerminateEndEvent.js b/src/draw/shape/TerminateEndEvent.js index c7db195..80f960f 100644 --- a/src/draw/shape/TerminateEndEvent.js +++ b/src/draw/shape/TerminateEndEvent.js @@ -122,8 +122,20 @@ class EndEvent extends Shape { * 获取文本范围 */ getTextBlock() { + const { textStyle } = this.style const { height, width } = this.plane.bounds - return { x: width / 2 - 60, y: height, width: 120, height: 30 } + let textWidth = 120 + let textHeight = 30 + if (textStyle) { + textWidth = textStyle.width || textWidth + textHeight = textStyle.height || textHeight + } + return { + x: width / 2 - textWidth / 2, + y: height, + width: textWidth, + height: textHeight + } } } diff --git a/src/draw/shape/UserTask.js b/src/draw/shape/UserTask.js index 4b8af78..1a52e5a 100644 --- a/src/draw/shape/UserTask.js +++ b/src/draw/shape/UserTask.js @@ -24,6 +24,9 @@ class UserTask extends Shape { this.groupName = 'Task' + // 字体样式 + this.fontStyle.vAlign = 'middle' + this.actions = this.getPath() } /** @@ -85,8 +88,21 @@ class UserTask extends Shape { * 获取文本范围 */ getTextBlock() { + const { textStyle } = this.style const { height, width } = this.plane.bounds - return { x: 10, y: 0, width: width - 20, height: height } + + let textWidth = width - 20 + let textHeight = height + if (textStyle) { + textWidth = textStyle.width || textWidth + textHeight = textStyle.height || textHeight + } + return { + x: width / 2 - textWidth / 2, + y: height / 2 - textHeight / 2, + width: textWidth, + height: textHeight + } } } diff --git a/src/features/edit-name/editName.js b/src/features/edit-name/editName.js new file mode 100644 index 0000000..e179d39 --- /dev/null +++ b/src/features/edit-name/editName.js @@ -0,0 +1,168 @@ +import eventBus from '../../core/eventBus' +import $ from '../../utils/slimJQ' +import { setScale, restoreScale } from '../../utils/utils' + +const DEFAULT_CONFIG = { + // 边框颜色 + borderColor: '#FF884D', + // 修改名称回调 + onEdited: () => {} +} + +class EditName { + constructor($container, config) { + this.$container = $container + + this.config = Object.assign({}, DEFAULT_CONFIG, config) + + this.init() + } + + init() { + // + eventBus.on('edit.shape.name', this.editShapeName.bind(this)) + } + + editShapeName() { + const { $container, config } = this + + const selectIds = eventBus.trigger('shape.select.getIds') || [] + if (selectIds.length === 1) { + const element = eventBus.trigger('element.get', selectIds[0]) + console.log(element) + + const { data, plane, shape } = element + + if (shape.bpmnName === 'SequenceFlow') { + this.editConnectionName(element) + return true + } + + let $edit = $container.find('.shape-name-edit') + if ($edit.length === 0) { + $edit = $("").appendTo( + $container.find('.bpd-designer') + ) + } + + let $temp = $container.find('.shape-name-temp') + if ($temp.length === 0) { + $temp = $("").appendTo( + $container.find('.bpd-designer') + ) + } + + $('.text-box[data-shape=' + data.id + ']').hide() + + const fontStyle = shape.fontStyle + const textBlock = shape.getTextBlock() + const editStyle = { + width: textBlock.width + 'px', + 'border-color': config.borderColor, + 'line-height': Math.round(fontStyle.size * 1.25) + 'px', + 'font-size': fontStyle.size + 'px', + 'font-family': fontStyle.fontFamily, + 'font-weight': fontStyle.bold ? 'bold' : 'normal', + 'font-style': fontStyle.italic ? 'italic' : 'normal', + 'text-align': fontStyle.textAlign, + color: 'rgb(' + fontStyle.color + ')', + 'text-decoration': fontStyle.underline ? 'underline' : 'none' + } + + $edit.css(editStyle).show() + $temp.css(editStyle) + textBlock.x += plane.bounds.x + textBlock.y += plane.bounds.y + $edit.val(data.name) + + $edit + .off() + .on('keyup', () => { + $temp.val($edit.val()) + $temp.scrollTop(99999) + const tempHeight = $temp.scrollTop() + $edit.css({ height: tempHeight }) + + const shapeTextPos = { + x: textBlock.x + textBlock.width / 2, + y: textBlock.y + textBlock.height / 2 + } + let editPosY = 0 + let editPadding = 5 + let editPaddingTop = 0 + let textHeight = textBlock.height + + switch (fontStyle.vAlign) { + case 'middle': + if (tempHeight > textHeight) { + textHeight = tempHeight + editPosY = shapeTextPos.y - textHeight / 2 - editPadding + editPaddingTop = 0 + } else { + editPosY = shapeTextPos.y - textBlock.height / 2 - editPadding + editPaddingTop = (textBlock.height - tempHeight) / 2 + textHeight = textBlock.height - editPaddingTop + } + break + default: + editPosY = shapeTextPos.y - textBlock.height / 2 + editPadding + if (tempHeight > textHeight) { + textHeight = tempHeight + } else { + textHeight = textBlock.height + } + break + } + const editHeight = editPadding * 2 + textHeight + const editPos = { + x: textBlock.x + textBlock.width / 2 - editPadding, + y: editPosY + editHeight / 2 + } + $edit.css({ + width: textBlock.width, + height: textHeight, + 'padding-top': editPaddingTop, + padding: editPadding, + left: setScale(editPos.x) - textBlock.width / 2 - 1, + top: setScale(editPos.y) - editHeight / 2 - 1 + }) + }) + .on('blur', e => { + this.updateShapeName(element) + }) + .on('mousemove', e => { + e.stopPropagation() + }) + .on('mousedown', e => { + e.stopPropagation() + }) + .on('mouseenter', e => { + console.log('mouseenter') + }) + + $edit.trigger('keyup') + } + } + + editConnectionName(element) {} + + updateShapeName(element) { + const { data } = element + const $edit = this.$container.find('.shape-name-edit') + const shapeName = $edit.val() + if ($edit.length && $edit.is(':visible')) { + if (shapeName !== data.name) { + data.name = shapeName + // Model.update(d) + } + // 渲染图形 + eventBus.trigger('shape.render', { + type: element.shape.bpmnName, + element + }) + $edit.remove() + } + } +} + +export default EditName diff --git a/src/features/edit-name/index.js b/src/features/edit-name/index.js new file mode 100644 index 0000000..5f5e781 --- /dev/null +++ b/src/features/edit-name/index.js @@ -0,0 +1,3 @@ +import editName from './editName' + +export default editName diff --git a/src/features/select/select.js b/src/features/select/select.js index 988c18a..4ce5aa0 100644 --- a/src/features/select/select.js +++ b/src/features/select/select.js @@ -5,7 +5,6 @@ import { setScale, restoreScale, mergeArray, - cloneDeep, setExportData } from '../../utils/utils' import DrawUtils from '../../draw/drawUtils' diff --git a/src/main.js b/src/main.js index 198c171..9fc4046 100644 --- a/src/main.js +++ b/src/main.js @@ -14,6 +14,7 @@ import { loadFont, setExportData } from './utils/utils' import BpmnXML from './features/xml' import Background from './features/background' import Direction from './features/direction' +import EditName from './features/edit-name' import Record from './features/record' import ShapeAnchor from './features/anchor' import ShapeSelect from './features/select' @@ -149,6 +150,8 @@ const initFeatures = ($container, options) => { const shapeSelect = new ShapeSelect($container, options.config.select) // 记录 const record = new Record() + // 编辑名称 + const editName = new EditName($container, options.config.editName) // 提示 const tooltip = new Tooltip($container, options.config.tooltip) // 拖动 diff --git a/static/index.html b/static/index.html index 2e4117f..7909429 100644 --- a/static/index.html +++ b/static/index.html @@ -125,7 +125,11 @@ bpmnStyle: { StartEvent: { name: 'xxx', - fillStyle: { color: '158,202,243' } + fillStyle: { color: '158,202,243' }, + textStyle: { width: 60, height: 12 } + }, + EndEvent: { + textStyle: { width: 60, height: 12 } }, UserTask: { content: [ @@ -146,7 +150,8 @@ ] } ], - fillStyle: { color: '158,202,243' } + fillStyle: { color: '158,202,243' }, + textStyle: { width: 60, height: 12 } } }, // 图形样式