diff --git a/public/iconfont.css b/public/iconfont.css index b527e37..bbf1148 100644 --- a/public/iconfont.css +++ b/public/iconfont.css @@ -1,6 +1,6 @@ @font-face { - font-family: "iconfont"; /* Project id 4440655 */ - src: url('iconfont.woff2?t=1735201425292') format('woff2'); + font-family: "iconfont"; /* Project id 4797805 */ + src: url('iconfont.woff2?t=1735470843861') format('woff2'); } .iconfont { @@ -11,164 +11,32 @@ -moz-osx-font-smoothing: grayscale; } -.icon-single-click:before { - content: "\e664"; +.icon-memory-chip:before { + content: "\e600"; } -.icon-wheel-change:before { - content: "\e6ad"; +.icon-wave-square:before { + content: "\ebd0"; } -.icon-double-click:before { - content: "\e6fc"; +.icon-about:before { + content: "\e601"; } -.icon-i18n:before { - content: "\e678"; +.icon-setting:before { + content: "\e657"; } -.icon-gou:before { - content: "\e84b"; +.icon-collections:before { + content: "\e689"; } -.icon-menu:before { - content: "\e607"; +.icon-register:before { + content: "\e611"; } -.icon-clear:before { - content: "\e619"; -} - -.icon-axis:before { - content: "\ed1f"; -} - -.icon-add-line:before { - content: "\e7b0"; -} - -.icon-arrow-to-previous:before { - content: "\e616"; -} - -.icon-arrow-to-next:before { - content: "\e615"; -} - -.icon-beginning:before { - content: "\e60e"; -} - -.icon-ending:before { - content: "\e60f"; -} - -.icon-line-analog:before { - content: "\e662"; -} - -.icon-ladder-analog:before { - content: "\e87b"; -} - -.icon-common-digital:before { - content: "\e606"; -} - -.icon-delete:before { - content: "\e684"; -} - -.icon-empty:before { - content: "\e617"; -} - -.icon-expand:before { - content: "\e658"; -} - -.icon-collapse:before { - content: "\e676"; -} - -.icon-group:before { - content: "\e70c"; -} - -.icon-cancel-group:before { - content: "\e65f"; -} - -.icon-delete-group:before { - content: "\e675"; -} - -.icon-choose:before { - content: "\e63b"; -} - -.icon-thin-arrow-right:before { - content: "\e622"; -} - -.icon-change-color:before { - content: "\e6fb"; -} - -.icon-join-group:before { - content: "\e914"; -} - -.icon-arrow-right:before { - content: "\eb08"; -} - -.icon-arrow-left:before { - content: "\eb09"; -} - -.icon-arrow-down:before { - content: "\eb0a"; -} - -.icon-arrow-up:before { - content: "\eb0b"; -} - -.icon-command:before { - content: "\e604"; -} - -.icon-minus:before { - content: "\e656"; -} - -.icon-equal:before { - content: "\e701"; -} - -.icon-ctrl:before { - content: "\e605"; -} - -.icon-shift:before { - content: "\e626"; -} - -.icon-mouse:before { - content: "\e69e"; -} - -.icon-left-right:before { - content: "\e61c"; -} - -.icon-up-down:before { - content: "\e61d"; -} - -.icon-help:before { - content: "\e87a"; +.icon-brackets:before { + content: "\e613"; } .icon-parameter:before { @@ -203,31 +71,175 @@ content: "\e614"; } -.icon-brackets:before { - content: "\e613"; +.icon-help:before { + content: "\e87a"; } -.icon-register:before { - content: "\e611"; +.icon-ctrl:before { + content: "\e605"; } -.icon-about:before { - content: "\e601"; +.icon-shift:before { + content: "\e626"; } -.icon-setting:before { - content: "\e657"; +.icon-mouse:before { + content: "\e69e"; } -.icon-collections:before { - content: "\e689"; +.icon-left-right:before { + content: "\e61c"; } -.icon-memory-chip:before { - content: "\e600"; +.icon-up-down:before { + content: "\e61d"; } -.icon-wave-square:before { - content: "\ebd0"; +.icon-command:before { + content: "\e604"; +} + +.icon-minus:before { + content: "\e656"; +} + +.icon-equal:before { + content: "\e701"; +} + +.icon-arrow-right:before { + content: "\eb08"; +} + +.icon-arrow-left:before { + content: "\eb09"; +} + +.icon-arrow-down:before { + content: "\eb0a"; +} + +.icon-arrow-up:before { + content: "\eb0b"; +} + +.icon-change-color:before { + content: "\e6fb"; +} + +.icon-join-group:before { + content: "\e914"; +} + +.icon-thin-arrow-right:before { + content: "\e622"; +} + +.icon-choose:before { + content: "\e63b"; +} + +.icon-cancel-group:before { + content: "\e65f"; +} + +.icon-delete-group:before { + content: "\e675"; +} + +.icon-expand:before { + content: "\e658"; +} + +.icon-collapse:before { + content: "\e676"; +} + +.icon-group:before { + content: "\e70c"; +} + +.icon-empty:before { + content: "\e617"; +} + +.icon-delete:before { + content: "\e684"; +} + +.icon-line-analog:before { + content: "\e662"; +} + +.icon-ladder-analog:before { + content: "\e87b"; +} + +.icon-common-digital:before { + content: "\e606"; +} + +.icon-arrow-to-next:before { + content: "\e615"; +} + +.icon-beginning:before { + content: "\e60e"; +} + +.icon-ending:before { + content: "\e60f"; +} + +.icon-arrow-to-previous:before { + content: "\e616"; +} + +.icon-add-line:before { + content: "\e7b0"; +} + +.icon-axis:before { + content: "\ed1f"; +} + +.icon-clear:before { + content: "\e619"; +} + +.icon-menu:before { + content: "\e607"; +} + +.icon-gou:before { + content: "\e84b"; +} + +.icon-i18n:before { + content: "\e678"; +} + +.icon-single-click:before { + content: "\e664"; +} + +.icon-wheel-change:before { + content: "\e6ad"; +} + +.icon-double-click:before { + content: "\e6fc"; +} + +.icon-connection-style-slice:before { + content: "\e608"; +} + +.icon-connection-style-concat:before { + content: "\e6e9"; +} + +.icon-connection-style-connect:before { + content: "\e693"; } diff --git a/public/iconfont.woff2 b/public/iconfont.woff2 index af436bb..eaf6e23 100644 Binary files a/public/iconfont.woff2 and b/public/iconfont.woff2 differ diff --git a/public/netlist.css b/public/netlist.css index 4fa4007..114cf8c 100644 --- a/public/netlist.css +++ b/public/netlist.css @@ -12,6 +12,13 @@ --toolbar-height: 50px; --toolbar-item-height: 32px; + /* 渲染相关的颜色设置 */ + --instance-color: #CB81DA; + --instance-fill-color: rgba(203, 129, 218, 0.1); + --wire-color: var(--foreground); + --port-color: rgb(70, 70, 222); + --port-fill-color: rgba(70, 70, 222, 0.1); + /* css 动画属性 */ --animation-7s: .7s cubic-bezier(0.23,1,0.32,1); --animation-5s: .5s cubic-bezier(0.23,1,0.32,1); diff --git a/scripts/update_icon.py b/scripts/update_icon.py index 8eb9b31..2938152 100644 --- a/scripts/update_icon.py +++ b/scripts/update_icon.py @@ -11,7 +11,7 @@ headers = { 'sec-fetch-mode': 'navigate' } -url = 'https://www.iconfont.cn/api/project/download.zip?spm=a313x.manage_type_myprojects.i1.d7543c303.125e3a81q6VMOU&pid=4440655&ctoken=Ku-GfnHTFQU6ObMjjX4rrwYn' +url = 'https://www.iconfont.cn/api/project/download.zip?spm=a313x.manage_type_myprojects.i1.d7543c303.96213a81OjUDfb&pid=4797805&ctoken=QcRJGHx0m7kL39pW1Slgy_E8' res = r.get(url, headers=headers) if res.status_code: diff --git a/src/components/render/index.vue b/src/components/render/index.vue index 212e407..18dea6d 100644 --- a/src/components/render/index.vue +++ b/src/components/render/index.vue @@ -36,11 +36,17 @@ onMounted(async () => { } .grab { - cursor: grab; + /* TODO: finish */ + /* cursor: grab; */ +} + +.pointer { + cursor: pointer; } .grabbing { - cursor: grabbing; + /* TODO: finish */ + /* cursor: grabbing; */ } .port-caption { diff --git a/src/components/setting/color.js b/src/components/setting/color.js new file mode 100644 index 0000000..4dfdb5a --- /dev/null +++ b/src/components/setting/color.js @@ -0,0 +1,85 @@ +import { reactive } from 'vue'; + +import i18n from '@/i18n'; +import { parseColor } from '@/hook/color'; + +const { t } = i18n.global; + +export const colorManager = reactive({ + currentGerneralIndex: 0, + generals: [ + { + value: 0, + type: 'wire', + label: t('common.line'), + color: 'white', + }, + { + value: 1, + type: 'port', + label: t('common.port'), + color: 'white', + }, + { + value: 2, + type: 'instance', + label: t('common.instance'), + color: 'white', + } + ], + + currentCell: 'binary', + cells: [ + { + value: '', + text: '' + }, + { + + }, + { + + }, + { + + }, + { + + } + ], + + initColor() { + const rootStyles = getComputedStyle(document.documentElement); + for (const item of this.generals) { + const optionName = `--${item.type}-color`; + const colorString = rootStyles.getPropertyValue(optionName); + console.log(optionName, colorString); + item.color = colorString; + } + } +}); + +/** + * @description 通用颜色设置发生变时 + * @param {string} colorString 用户选择的颜色的字符串 + */ +export function onGeneralColorChange(colorString) { + const { r, g, b } = parseColor(colorString); + const index = colorManager.currentGerneralIndex; + const item = colorManager.generals[index]; + const borderColor = `rgb(${r}, ${g}, ${b})`; + const fillColor = `rgba(${r}, ${g}, ${b}, 0.1)`; + const rootStyles = getComputedStyle(document.documentElement); + document.documentElement.style.setProperty(`--${item.type}-color`, borderColor); + document.documentElement.style.setProperty(`--${item.type}-fill-color`, fillColor); +} + +export const predefinedColors = [ + '#ff4500', + '#ff8c00', + '#ffd700', + '#90ee90', + '#00ced1', + '#1e90ff', + '#c71585' +]; \ No newline at end of file diff --git a/src/components/setting/connect-style.js b/src/components/setting/connect-style.js new file mode 100644 index 0000000..8cde538 --- /dev/null +++ b/src/components/setting/connect-style.js @@ -0,0 +1,27 @@ +import { pinkLog } from '@/hook/utils'; +import { reactive } from 'vue'; + +export const connectionStyles = reactive({ + currentStyle: 'connect', + options: [ + { + value: 'slice', + text: '拆分符', + icon: 'iconfont icon-connection-style-slice' + }, + { + value: 'connect', + text: '直连符', + icon: 'iconfont icon-connection-style-connect' + }, + { + value: 'concat', + text: '合并符', + icon: 'iconfont icon-connection-style-concat' + } + ] +}); + +export function onConnectStyleChange(style) { + pinkLog('连接样式修改为: ' + style); +} \ No newline at end of file diff --git a/src/components/setting/index.vue b/src/components/setting/index.vue index e71305e..0594a9d 100644 --- a/src/components/setting/index.vue +++ b/src/components/setting/index.vue @@ -3,10 +3,9 @@

{{ t('general-setting') }}

-
+
-   {{ t('language-setting') }}
@@ -45,15 +44,94 @@
- - {{ t('render-animation') }} - + + {{ t('render-animation') }} +
+
+ +
+

{{ t('appearance-setting') }}

+
+ + {{ t('render-arrow') }} + + +
+
+ +
+ + {{ t('bold-multi-width-wire') }} + + +
+
+ +
+ + {{ t('cross-dot-style') }} + +
+ + + + + {{ option.text }} + + + +
+
+
+ + +
+ + {{ t('setting.general-color-setting') }} + +
+
+ + + +
+
+ +
+
@@ -62,8 +140,11 @@ @@ -215,4 +259,16 @@ const languageSetting = reactive({ color: var(--vscode-foreground) !important; } +.setting-option .icon-i18n { + margin-right: 8px; +} + +.connection-icon { + width: 12px; + margin-right: 8px; + display: flex; + justify-content: center; + font-size: 10px; +} + \ No newline at end of file diff --git a/src/components/setting/language.js b/src/components/setting/language.js new file mode 100644 index 0000000..23f0c17 --- /dev/null +++ b/src/components/setting/language.js @@ -0,0 +1,42 @@ +import { reactive } from 'vue'; + +export const languageSetting = reactive({ + options: [ + { + value: 'en', + text: 'English' + }, + { + value: 'zh', + text: '简体中文' + }, + { + value: 'zhTw', + text: '繁體中文' + }, + { + value: 'ja', + text: '日本語' + }, + { + value: 'ko', + text: '한국어' + }, + { + value: 'de', + text: 'Deutsch' + }, + { + value: 'fr', + text: 'Français' + }, + { + value: 'ru', + text: 'Русский' + }, + { + value: 'ar', + text: 'العربية' + } + ] +}); diff --git a/src/hook/global.js b/src/hook/global.js index e589840..9b26f59 100644 --- a/src/hook/global.js +++ b/src/hook/global.js @@ -8,7 +8,12 @@ export const emitter = mitt(); export const globalSetting = reactive({ language: 'zh', - renderAnimation: true + // 开启渲染动画 + renderAnimation: true, + // 绘制箭头 + renderArrow: false, + // 加粗多位宽的线 + boldMultiWidthWire: true }); export const globalLookup = reactive({ diff --git a/src/hook/render/cell.js b/src/hook/render/cell.js index 0fc9b85..e692531 100644 --- a/src/hook/render/cell.js +++ b/src/hook/render/cell.js @@ -48,28 +48,22 @@ export class CellRender { const id2manager = this.id2manager; const _this = this; - - console.log(data); - - let cellSelections = this.parentSelection.selectAll('svg') .data(data) .enter() .append(data => { - const element = data.element; - console.log(data); - + const element = data.element; element.setAttribute('x', data.x); element.setAttribute('y', data.y); if (globalSetting.renderAnimation) { - element.setAttribute('stroke-opacity', 0); + element.setAttribute('opacity', 0); } return element; }) .each(function (data) { const cellSelection = d3.select(this); const manager = _this.createDataManager(cellSelection, data); - + // TODO: 实现拖拽 // registerDragEvent(manager, rootRender); }); @@ -78,7 +72,7 @@ export class CellRender { cellSelections = cellSelections .transition() .duration(1000) - .attr('stroke-opacity', 1) + .attr('opacity', 1) .attr('class', 'grab'); } else { cellSelections = cellSelections diff --git a/src/hook/render/instantiation.js b/src/hook/render/instantiation.js index af6e1c2..fa76193 100644 --- a/src/hook/render/instantiation.js +++ b/src/hook/render/instantiation.js @@ -2,6 +2,7 @@ import * as d3 from 'd3'; import { NetlistRender } from '.'; import { globalSetting } from '../global'; import { LAYOUT_CONSTANT } from './layout'; +import { svgResource } from '../skin/draw'; export class InstantiationRender { /** @@ -32,52 +33,20 @@ export class InstantiationRender { addAsD3DataItem(node) { const nodeModule = this.rootRender.nameToModule.get(node.renderName); const view = nodeModule.view; + const textPadding = 5; const portnames = []; - let inputCount = 0; - let outputCount = 0; - const instanceWidth = LAYOUT_CONSTANT.INSTANTIATION_WIDTH + 2 * LAYOUT_CONSTANT.PORT_INNER_PADDING; - // 统计出两侧 port 字符串最长的 - let inputPortMaxLength = 0; - let outputPortMaxLength = 0; - - for (const portName of view.nameToPort.keys()) { - const port = view.nameToPort.get(portName); - if (port.direction === 'input') { - inputPortMaxLength = Math.max(portName.length, inputPortMaxLength); - } else { - outputPortMaxLength = Math.max(portName.length, outputPortMaxLength); - } - } - - for (const portName of view.nameToPort.keys()) { - const port = view.nameToPort.get(portName); - if (port.direction === 'input') { - inputCount ++; - const offsetY = inputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN + - (inputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT + - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT; - - portnames.push({ - name: portName, - x: 5, - y: offsetY, - align: 'left' - }); - } else { - outputCount ++; - const offsetY = outputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN + - (outputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT + - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT; - - portnames.push({ - name: portName, - x: instanceWidth - 5, - y: offsetY, - align: 'end' - }); - } + for (const port of node.ports || []) { + const isInput = port.x < LAYOUT_CONSTANT.INSTANTIATION_WIDTH; + const align = isInput ? 'left': 'end'; + const portX = isInput ? port.x + textPadding : port.x - textPadding; + portnames.push({ + name: port.renderName, + x: portX, + y: port.y, + align + }); } this.data.push({ @@ -88,12 +57,11 @@ export class InstantiationRender { name: node.name, width: node.width, height: node.height, - fill: 'var(--main-dark-color)', + fill: 'var(--instance-fill-color)', text: node.renderName, portnames, rx: 3, ry: 3, - expandText: '📌', _self: node }); } @@ -104,6 +72,7 @@ export class InstantiationRender { const id2manager = this.id2manager; const _this = this; + // 外部控制主体的 g let instantiationSelections = this.parentSelection.selectAll('g.instance') .data(data) .enter() @@ -111,74 +80,142 @@ export class InstantiationRender { .attr('class', 'instance') .attr("transform", d => `translate(${d.x}, ${d.y})`); + // 例化模块的方块 let instances = instantiationSelections.append('rect') .attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT) .attr('width', data => data.width) - .attr('height', data => data.height - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT) - .attr('fill', d => { - const children = d._self.children || []; - return children.length > 0 ? 'rgba(203, 129, 218, 0.1)' : d.fill; - }); + .attr('height', data => data.height - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT); + // 说明文字 let texts = instantiationSelections.append('text') .attr('x', 0) .attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT - 8) .attr('dominant-baseline', 'middle') .attr('text-anchor', 'left') - .attr('fill', 'var(--main-dark-color)') - .attr('font-size', '0') - .attr('font-size', '12px') + .attr('fill', 'var(--foreground)') + .attr('font-size', '14px') .attr('class', 'port-caption') - .text(data => data.name + ' ' + data.expandText) + .text(data => data.name) .each(function(data) { const text = d3.select(this); const bbox = text.node().getBBox(); - instantiationSelections.insert('rect', 'text') - .attr('x', -1) - .attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT - bbox.height - 5) - .attr('width', bbox.width + 10) - .attr('height', bbox.height + 5) - .attr('fill', 'var(--main-color)'); + data.textX = (data.width - bbox.width) / 2; }) - .on('click', function(event) { + .attr('x', d => d.textX) + + + // 渲染 portnames + instantiationSelections.each(function(node) { + d3.select(this) + .selectAll('.port-name') + .data(node.portnames) + .enter() + .append('text') + .attr('class', 'port-name') + .attr('x', d => d.x) + .attr('y', d => d.y) + .attr('dominant-baseline', 'middle') + .attr('text-anchor', d => d.align) + .attr('fill', 'var(--foreground)') + .attr('font-size', '11px') + .text(d => d.name); + }); + + + // 增加一个背景方块,防止 svg 点不到 + let bgFullScreenSelections = instantiationSelections.append('rect') + .attr('x', 5) + .attr('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + 5) + .attr('width', 20) + .attr('height', 20) + .attr('opacity', 0) + .attr('class', 'pointer') + .on('click', function(data) { const selection = d3.select(this); const d = selection.datum(); const children = d._self.children || []; - if (children.length > 0) { rootRender.collapseInstance(selection); } else { rootRender.expandInstance(selection); } }); + + + const id2element = new Map(); + // 渲染左上角的放大缩小图标,并注册对应的展开/收起事件 + let fullSreenSelections = instantiationSelections.append(data => { + // 获取全屏图标 + const element = svgResource.get('full-screen'); + element.setAttribute('x', 5); + element.setAttribute('y', LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + 5); + element.setAttribute('width', 20); + element.setAttribute('height', 20); + element.setAttribute('class', 'pointer'); - // 获取 port 相关的信息 - instantiationSelections.each(function(node) { - d3.select(this) // 选择当前节点 - .selectAll('.port-name') // 选择所有端口名称元素 - .data(node.portnames) // 绑定端口名称数据 - .enter() - .append('text') // 创建文本元素 - .attr('class', 'port-name') - .attr('x', d => d.x) // 使用端口的相对 x 坐标 - .attr('y', d => d.y) // 使用端口的相对 y 坐标 - .attr('dominant-baseline', 'middle') // 文本垂直居中 - .attr('text-anchor', d => d.align) - .attr('fill', 'var(--foreground)') // 文本颜色 - .attr('font-size', '10px') // 设置字体大小 - .text(d => d.name); // 设置文本内容 + return element; + }) + .each(function(data) { + const svgElement = d3.select(this); + id2element.set(data.id, svgElement); + }) + .on('mouseenter', function() { + const svgElement = d3.select(this); + svgElement.selectAll("*") + .attr("fill", "var(--instance-color)"); + }) + .on('mouseleave', function() { + const svgElement = d3.select(this); + svgElement.selectAll("*") + .attr("fill", "var(--foreground)"); + }) + .on('click', function(data) { + const selection = d3.select(this); + const d = selection.datum(); + const children = d._self.children || []; + + if (children.length > 0) { + rootRender.collapseInstance(selection); + } else { + rootRender.expandInstance(selection); + } }); + console.log(id2element); + + bgFullScreenSelections + .on('mouseenter', function(_, data) { + const svgElement = id2element.get(data.id); + svgElement.selectAll("*") + .attr("fill", "var(--instance-color)"); + }) + .on('mouseleave', function(_, data) { + const svgElement = id2element.get(data.id); + svgElement.selectAll("*") + .attr("fill", "var(--foreground)"); + }); + if (globalSetting.renderAnimation) { - instances.transition() + instances + .transition() .duration(1000) - .attr('stroke', 'var(--main-color)') - .attr('stroke-width', 2) + .attr('fill', d => { + const children = d._self.children || []; + return children.length > 0 ? 'rgba(203, 129, 218, 0.1)' : d.fill; + }) + .attr('stroke', 'var(--instance-color)') + .attr('stroke-width', 2); + } else { - instances.attr('stroke', 'var(--main-color)') - .attr('stroke-width', 2) + instances + .attr('fill', d => { + const children = d._self.children || []; + return children.length > 0 ? 'rgba(203, 129, 218, 0.1)' : d.fill; + }) + .attr('stroke', 'var(--instance-color)') + .attr('stroke-width', 2) } instantiationSelections diff --git a/src/hook/render/layout.js b/src/hook/render/layout.js index b1a1be9..7b5b1c3 100644 --- a/src/hook/render/layout.js +++ b/src/hook/render/layout.js @@ -32,6 +32,7 @@ export const LAYOUT_CONSTANT = { // 例化模块上部分的空缺区域 INSTANCE_TITLE_HEIGHT: 10, + INSTANCE_TOP_PADDING: 20, // 常数 CONSTANT_WIDTH: 50, @@ -271,7 +272,7 @@ export class Module { inputCount ++; const offsetY = inputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN + (inputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT + - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT; + LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + LAYOUT_CONSTANT.INSTANCE_TOP_PADDING; ports.push({ id: connection.id, @@ -286,7 +287,7 @@ export class Module { outputCount ++; const offsetY = outputCount * LAYOUT_CONSTANT.PORT_TOP_MARGIN + (outputCount - 1) * LAYOUT_CONSTANT.CELL_PORT_HEIGHT + - LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT; + LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + LAYOUT_CONSTANT.INSTANCE_TOP_PADDING; ports.push({ id: connection.id, @@ -306,7 +307,7 @@ export class Module { renderName: cell.type, renderType: 'cell', width: instanceWidth, - height: instanceHeight + LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT, + height: instanceHeight + LAYOUT_CONSTANT.INSTANCE_TITLE_HEIGHT + LAYOUT_CONSTANT.INSTANCE_TOP_PADDING, ports, layoutOptions: { // 强制固定 port 的方向 diff --git a/src/hook/render/port.js b/src/hook/render/port.js index 02bbd88..03ec7d3 100644 --- a/src/hook/render/port.js +++ b/src/hook/render/port.js @@ -36,7 +36,7 @@ export class PortRender { y: node.y, width: node.width, height: node.height, - fill: 'var(--main-dark-color)', + fill: 'var(--port-fill-color)', text: node.renderName, rx: 3, ry: 3 @@ -78,12 +78,12 @@ export class PortRender { if (globalSetting.renderAnimation) { ports.transition() .duration(1000) - .attr('stroke', 'var(--main-color)') + .attr('stroke', 'var(--port-color)') .attr('stroke-width', 2) .attr('rx', d => d.rx) .attr('ry', d => d.ry); } else { - ports.attr('stroke', 'var(--main-color)') + ports.attr('stroke', 'var(--port-color)') .attr('stroke-width', 2) .attr('rx', d => d.rx) .attr('ry', d => d.ry); diff --git a/src/hook/render/wire.js b/src/hook/render/wire.js index aad24cf..ada5cd6 100644 --- a/src/hook/render/wire.js +++ b/src/hook/render/wire.js @@ -38,7 +38,7 @@ export class WireRender { x2: points[i + 1].x, y2: points[i + 1].y, strokeWidth: 2, - color: 'var(--foreground)' + color: 'var(--wire-color)' }); } } diff --git a/src/hook/skin/draw.js b/src/hook/skin/draw.js new file mode 100644 index 0000000..9d89e69 --- /dev/null +++ b/src/hook/skin/draw.js @@ -0,0 +1,38 @@ +// 一些和绘制相关的 svg 资源 +export const DIDE_DRAW_SVG_STRINGS = [ + // 放大 + { + name: 'full-screen', + source: '' + } +]; + +class SvgResource { + constructor() { + /** + * @type {Map} + */ + this.nameToSvgDoc = new Map(); + const parser = new DOMParser(); + + for (const item of DIDE_DRAW_SVG_STRINGS) { + let svgString = item.source; + let name = item.name; + // 填充颜色 + svgString = svgString.replace(/#000000/g, 'var(--foreground)'); + const svgDoc = parser.parseFromString(svgString, 'image/svg+xml'); + this.nameToSvgDoc.set(name, svgDoc); + } + } + + get(svgName) { + const svg = this.nameToSvgDoc.get(svgName); + if (!svg) { + return undefined; + } + const element = svg.documentElement.cloneNode(true); + return element; + } +} + +export const svgResource = new SvgResource(); \ No newline at end of file diff --git a/src/i18n/ar.json b/src/i18n/ar.json index 549915f..98fc39c 100644 --- a/src/i18n/ar.json +++ b/src/i18n/ar.json @@ -3,7 +3,6 @@ "general-setting": "عام", "appearance-setting": "المظهر", "current-version": "الإصدار الحالي", - "copyright": "حقوق النشر مملوكة لفريق مشروع Digital-IDE، نرحب بـ Star.", "confirm": "تأكيد", "cancel": "إلغاء", "tips": "نصائح", @@ -16,5 +15,13 @@ "usermanual.scale-view": "تكبير/تصغير العرض", "usermanual.scale-view-more": "تكبير العرض (مقياس أكبر)", "loading": "جاري التحميل", - "module": "وحدة" + "module": "وحدة", + "render-arrow": "تقديم سهم نقطة الاتصال", + "bold-multi-width-wire": "خطوط اتصال متعددة العرض بخط عريض", + "copyright": "حقوق النشر مملوكة لفريق مشروع Digital-IDE، نرحب بـ Star.", + "cross-dot-style": "نمط التقاطع", + "common.line": "خط", + "common.port": "المنفذ", + "common.instance": "تجهيز الوحدة", + "setting.general-color-setting": "إعدادات الألوان العامة" } \ No newline at end of file diff --git a/src/i18n/de.json b/src/i18n/de.json index ce9b93e..6e61495 100644 --- a/src/i18n/de.json +++ b/src/i18n/de.json @@ -3,7 +3,6 @@ "general-setting": "Allgemein", "appearance-setting": "Aussehen", "current-version": "Aktuelle Version", - "copyright": "Dieses Software gehört dem Digital-IDE Projektteam, willkommen Star.", "confirm": "Bestätigen", "cancel": "Abbrechen", "tips": "Tipps", @@ -16,5 +15,13 @@ "usermanual.scale-view": "Ansicht zoomen", "usermanual.scale-view-more": "Ansicht vergrößern (größerer Maßstab)", "loading": "Laden", - "module": "Modul" + "module": "Modul", + "render-arrow": "Rendern des Verbindungspfeils", + "bold-multi-width-wire": "Fettgedruckte mehrfach breite Verbindungslinien", + "copyright": "Dieses Software gehört dem Digital-IDE Projektteam, willkommen Star.", + "cross-dot-style": "Kreuzungsstil", + "common.line": "Linie", + "common.port": "Port", + "common.instance": "Modul instanziieren", + "setting.general-color-setting": "Allgemeine Farbeinstellungen" } \ No newline at end of file diff --git a/src/i18n/en.json b/src/i18n/en.json index 2f05218..cd60050 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -3,7 +3,6 @@ "general-setting": "General", "appearance-setting": "Appearance", "current-version": "current version", - "copyright": "The copyright of this software belongs to Digital-IDE project team. Welcome to Star.", "confirm": "confirm", "cancel": "cancel", "tips": "Tips", @@ -16,5 +15,13 @@ "usermanual.scale-view": "View zoom", "usermanual.scale-view-more": "View zoom (larger scale)", "loading": "loading", - "module": "Modules" + "module": "Modules", + "render-arrow": "Render connection point arrow", + "bold-multi-width-wire": "Bold multi-width connection lines", + "copyright": "The copyright of this software belongs to Digital-IDE project team. Welcome to Star.", + "cross-dot-style": "Intersection Style", + "common.line": "line", + "common.port": "Port", + "common.instance": "Instantiate module", + "setting.general-color-setting": "General Color Settings" } \ No newline at end of file diff --git a/src/i18n/fr.json b/src/i18n/fr.json index 7c4770e..2715294 100644 --- a/src/i18n/fr.json +++ b/src/i18n/fr.json @@ -3,7 +3,6 @@ "general-setting": "Général", "appearance-setting": "Apparence", "current-version": "Version actuelle", - "copyright": "Les droits d'auteur appartiennent au groupe de projet Digital-IDE, bienvenue Star.", "confirm": "Confirmer", "cancel": "Annuler", "tips": "Conseils", @@ -16,5 +15,13 @@ "usermanual.scale-view": "Zoom de la vue", "usermanual.scale-view-more": "Zoom de la vue (échelle plus grande)", "loading": "Chargement", - "module": "Module" + "module": "Module", + "render-arrow": "Rendu de la flèche du point de connexion", + "bold-multi-width-wire": "Lignes de connexion multi-largeur en gras", + "copyright": "Les droits d'auteur appartiennent au groupe de projet Digital-IDE, bienvenue Star.", + "cross-dot-style": "Style d'intersection", + "common.line": "ligne", + "common.port": "Port", + "common.instance": "Instancier le module", + "setting.general-color-setting": "Paramètres de couleur généraux" } \ No newline at end of file diff --git a/src/i18n/ja.json b/src/i18n/ja.json index de503dd..d003260 100644 --- a/src/i18n/ja.json +++ b/src/i18n/ja.json @@ -3,7 +3,6 @@ "general-setting": "一般", "appearance-setting": "外観", "current-version": "現在のバージョン", - "copyright": "このソフトウェアの著作権は Digital-IDE プロジェクトチームに帰属します。Star を歓迎します。", "confirm": "確認", "cancel": "キャンセル", "tips": "ヒント", @@ -16,5 +15,13 @@ "usermanual.scale-view": "ビューのズーム", "usermanual.scale-view-more": "ビューのズーム(より大きなスケール)", "loading": "読み込み中", - "module": "モジュール" + "module": "モジュール", + "render-arrow": "接続点矢印のレンダリング", + "bold-multi-width-wire": "太字の多幅接続線", + "copyright": "このソフトウェアの著作権は Digital-IDE プロジェクトチームに帰属します。Star を歓迎します。", + "cross-dot-style": "交差点スタイル", + "common.line": "線", + "common.port": "ポート", + "common.instance": "モジュールのインスタンス化", + "setting.general-color-setting": "一般的な色設定" } \ No newline at end of file diff --git a/src/i18n/ko.json b/src/i18n/ko.json index 7b75ff7..863ea35 100644 --- a/src/i18n/ko.json +++ b/src/i18n/ko.json @@ -3,7 +3,6 @@ "general-setting": "일반", "appearance-setting": "외관", "current-version": "현재 버전", - "copyright": "이 소프트웨어의 저작권은 Digital-IDE 프로젝트 팀에 있으며, Star를 환영합니다.", "confirm": "확인", "cancel": "취소", "tips": "팁", @@ -16,5 +15,13 @@ "usermanual.scale-view": "보기 확대/축소", "usermanual.scale-view-more": "보기 확대 (더 큰 스케일)", "loading": "로딩 중", - "module": "모듈" + "module": "모듈", + "render-arrow": "연결점 화살표 렌더링", + "bold-multi-width-wire": "굵은 다중 너비 연결선", + "copyright": "이 소프트웨어의 저작권은 Digital-IDE 프로젝트 팀에 있으며, Star를 환영합니다.", + "cross-dot-style": "교차로 스타일", + "common.line": "선", + "common.port": "포트", + "common.instance": "모듈 인스턴스화", + "setting.general-color-setting": "일반 색상 설정" } \ No newline at end of file diff --git a/src/i18n/ru.json b/src/i18n/ru.json index 7b3d194..a48dd8d 100644 --- a/src/i18n/ru.json +++ b/src/i18n/ru.json @@ -3,7 +3,6 @@ "general-setting": "Общие", "appearance-setting": "Внешний вид", "current-version": "Текущая версия", - "copyright": "Авторские права принадлежат проектной группе Digital-IDE, приветствуем Star.", "confirm": "Подтвердить", "cancel": "Отменить", "tips": "Советы", @@ -16,5 +15,13 @@ "usermanual.scale-view": "Масштабирование вида", "usermanual.scale-view-more": "Масштабирование вида (больший масштаб)", "loading": "Загрузка", - "module": "Модуль" + "module": "Модуль", + "render-arrow": "Рендеринг стрелки точки соединения", + "bold-multi-width-wire": "Жирные многожильные соединительные линии", + "copyright": "Авторские права принадлежат проектной группе Digital-IDE, приветствуем Star.", + "cross-dot-style": "Стиль пересечения", + "common.line": "линия", + "common.port": "Порт", + "common.instance": "Создание экземпляра модуля", + "setting.general-color-setting": "Общие настройки цвета" } \ No newline at end of file diff --git a/src/i18n/zh-cn.json b/src/i18n/zh-cn.json index b3c0173..3cfca2e 100644 --- a/src/i18n/zh-cn.json +++ b/src/i18n/zh-cn.json @@ -3,7 +3,6 @@ "general-setting": "通用", "appearance-setting": "外观", "current-version": "当前版本", - "copyright": "本软件版权归 Digital-IDE 项目组所有,欢迎 Star。", "confirm": "确定", "cancel": "取消", "tips": "提示", @@ -16,5 +15,13 @@ "usermanual.scale-view": "视图缩放", "usermanual.scale-view-more": "视图缩放(尺度更大)", "loading": "加载中", - "module": "模块" + "module": "模块", + "render-arrow": "渲染连接点箭头", + "bold-multi-width-wire": "加粗多位宽连接线", + "copyright": "本软件版权归 Digital-IDE 项目组所有,欢迎 Star。", + "cross-dot-style": "交叉点样式", + "common.line": "线", + "common.port": "端口", + "common.instance": "例化模块", + "setting.general-color-setting": "通用颜色设置" } \ No newline at end of file diff --git a/src/i18n/zh-tw.json b/src/i18n/zh-tw.json index a16cb1f..221574e 100644 --- a/src/i18n/zh-tw.json +++ b/src/i18n/zh-tw.json @@ -3,7 +3,6 @@ "general-setting": "通用", "appearance-setting": "外觀", "current-version": "當前版本", - "copyright": "本軟件版權歸 Digital-IDE 項目組所有,歡迎 Star。", "confirm": "確定", "cancel": "取消", "tips": "提示", @@ -16,5 +15,13 @@ "usermanual.scale-view": "視圖縮放", "usermanual.scale-view-more": "視圖縮放(尺度更大)", "loading": "加載中", - "module": "模塊" + "module": "模塊", + "render-arrow": "渲染連接點箭頭", + "bold-multi-width-wire": "加粗多位寬連接線", + "copyright": "本軟件版權歸 Digital-IDE 項目組所有,歡迎 Star。", + "cross-dot-style": "交叉點樣式", + "common.line": "線", + "common.port": "端口", + "common.instance": "實例化模組", + "setting.general-color-setting": "通用顏色設定" } \ No newline at end of file