diff --git a/example/config/webpack.config.js b/example/config/webpack.config.js
index 7a76d05a46..9a2e4c989a 100644
--- a/example/config/webpack.config.js
+++ b/example/config/webpack.config.js
@@ -11,6 +11,7 @@ const gitRevisionPlugin = new GitRevisionPlugin({
commithashCommand: `rev-list v${config.version}..HEAD --count`
})
const buildNumber = gitRevisionPlugin.commithash()
+
module.exports = override(
addBundleVisualizer({}, true),
addWebpackModuleRule({
diff --git a/example/yarn.lock b/example/yarn.lock
index 6556559a25..772da76a87 100644
--- a/example/yarn.lock
+++ b/example/yarn.lock
@@ -4176,6 +4176,11 @@ electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.585:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.588.tgz#c6515571737bfb42678115a5eaa818384593a9a5"
integrity sha512-0zr+ZfytnLeJZxGgmEpPTcItu5Mm4A5zHPZXLfHcGp0mdsk95rmD7ePNewYtK1yIdLbk8Z1U2oTRRfOtR4gbYg==
+element-closest-polyfill@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/element-closest-polyfill/-/element-closest-polyfill-1.0.2.tgz#272c217d60effe76a0509a911cde5fcdd78da5a6"
+ integrity sha512-+3cNhtv8YIyk/oDSlBv+zqUjQFcF9puLp4TFIk2w0Gqd6IL2uZnnu0jvDdOaI7dsK1bIA9gG69KIvkEyUFVGRg==
+
elliptic@^6.5.3:
version "6.5.3"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
diff --git a/src/icons/files/shape-line.svg b/src/icons/files/shape-line.svg
new file mode 100644
index 0000000000..bdb5d677aa
--- /dev/null
+++ b/src/icons/files/shape-line.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/icons/files/shape-polyline.svg b/src/icons/files/shape-polyline.svg
new file mode 100644
index 0000000000..858acdef95
--- /dev/null
+++ b/src/icons/files/shape-polyline.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/icons/index.tsx b/src/icons/index.tsx
index 769abaadc4..a701faf02e 100644
--- a/src/icons/index.tsx
+++ b/src/icons/index.tsx
@@ -84,6 +84,8 @@ import ZoomInIcon from './files/zoom-in.svg'
import ZoomOutIcon from './files/zoom-out.svg'
import ShapeCircleIcon from './files/shape-circle.svg'
import ShapeRectangleIcon from './files/shape-rectangle.svg'
+import ShapePolylineIcon from './files/shape-polyline.svg'
+import ShapeLineIcon from './files/shape-line.svg'
const icons = {
about: AboutIcon,
@@ -156,7 +158,9 @@ const icons = {
'zoom-in': ZoomInIcon,
'zoom-out': ZoomOutIcon,
'shape-circle': ShapeCircleIcon,
- 'shape-rectangle': ShapeRectangleIcon
+ 'shape-rectangle': ShapeRectangleIcon,
+ 'shape-polyline': ShapePolylineIcon,
+ 'shape-line': ShapeLineIcon
}
function emptyIcon() {
diff --git a/src/script/chem/struct/index.js b/src/script/chem/struct/index.js
index 426c2d56cf..5d50ab7bbd 100644
--- a/src/script/chem/struct/index.js
+++ b/src/script/chem/struct/index.js
@@ -457,10 +457,9 @@ Struct.prototype.rxnArrowSetPos = function (id, pp) {
item.pp = pp
}
-Struct.prototype.simpleObjectSetPos = function (id, p0, p1) {
+Struct.prototype.simpleObjectSetPos = function (id, pos) {
const item = this.simpleObjects.get(id)
- item.p0 = p0
- item.p1 = p1
+ item.pos = pos
}
/**
@@ -781,14 +780,14 @@ Struct.prototype.findLoops = function () {
const bondsToMark = new Pile()
/*
- Starting from each half-bond not known to be in a loop yet,
- follow the 'next' links until the initial half-bond is reached or
- the length of the sequence exceeds the number of half-bonds available.
- In a planar graph, as long as every bond is a part of some "loop" -
- either an outer or an inner one - every iteration either yields a loop
- or doesn't start at all. Thus this has linear complexity in the number
- of bonds for planar graphs.
- */
+ Starting from each half-bond not known to be in a loop yet,
+ follow the 'next' links until the initial half-bond is reached or
+ the length of the sequence exceeds the number of half-bonds available.
+ In a planar graph, as long as every bond is a part of some "loop" -
+ either an outer or an inner one - every iteration either yields a loop
+ or doesn't start at all. Thus this has linear complexity in the number
+ of bonds for planar graphs.
+ */
let hbIdNext, c, loop, loopId
this.halfBonds.forEach((hb, hbId) => {
@@ -1045,8 +1044,12 @@ RxnPlus.prototype.clone = function () {
function SimpleObject(params) {
params = params || {}
- this.p0 = params.p0 ? new Vec2(params.p0) : new Vec2()
- this.p1 = params.p1 ? new Vec2(params.p1) : new Vec2()
+ this.pos = []
+
+ if (params.pos)
+ for (let i = 0; i < params.pos.length; i++)
+ this.pos[i] = params.pos[i] ? new Vec2(params.pos[i]) : new Vec2()
+
this.mode = params.mode
}
@@ -1057,10 +1060,10 @@ SimpleObject.prototype.clone = function () {
SimpleObject.prototype.center = function () {
switch (this.mode) {
case 'rectangle': {
- return Vec2.centre(this.p0, this.p1)
+ return Vec2.centre(this.pos[0], this.pos[1])
}
default:
- return this.p0
+ return this.pos[0]
}
}
diff --git a/src/script/editor/actions/paste.js b/src/script/editor/actions/paste.js
index b502198f1d..1a88ab4ce5 100644
--- a/src/script/editor/actions/paste.js
+++ b/src/script/editor/actions/paste.js
@@ -110,8 +110,7 @@ export function fromPaste(restruct, pstruct, point, angle = 0) {
pstruct.simpleObjects.forEach(simpleObject => {
action.addOp(
new op.SimpleObjectAdd(
- simpleObject.p0.add(offset),
- simpleObject.p1.add(offset),
+ simpleObject.pos.map(p => p.add(offset)),
simpleObject.mode
).perform(restruct)
)
diff --git a/src/script/editor/actions/simpleobject.js b/src/script/editor/actions/simpleobject.js
index eaf0f4b8dc..f6e6c6f54e 100644
--- a/src/script/editor/actions/simpleobject.js
+++ b/src/script/editor/actions/simpleobject.js
@@ -22,9 +22,9 @@ export function fromSimpleObjectDeletion(restruct, id) {
return action.perform(restruct)
}
-export function fromSimpleObjectAddition(restruct, p0, p1, mode) {
+export function fromSimpleObjectAddition(restruct, pos, mode) {
var action = new Action()
- action.addOp(new op.SimpleObjectAdd(p0, p1, mode))
+ action.addOp(new op.SimpleObjectAdd(pos, mode))
return action.perform(restruct)
}
diff --git a/src/script/editor/operations/op.js b/src/script/editor/operations/op.js
index 6105850db8..498ba93de0 100644
--- a/src/script/editor/operations/op.js
+++ b/src/script/editor/operations/op.js
@@ -934,8 +934,9 @@ function RestoreDescriptorsPosition(history) {
}
RestoreDescriptorsPosition.prototype = new Base()
-function SimpleObjectAdd(p0, p1, mode) {
- this.data = { id: null, p0, p1, mode }
+function SimpleObjectAdd(pos, mode) {
+ this.data = { id: null, pos, mode }
+
let performed = false
this.execute = function (restruct) {
const struct = restruct.molecule
@@ -953,8 +954,7 @@ function SimpleObjectAdd(p0, p1, mode) {
struct.simpleObjectSetPos(
this.data.id,
- new Vec2(this.data.p0),
- new Vec2(this.data.p1)
+ this.data.pos.map(p => new Vec2(p))
)
invalidateItem(restruct, 'simpleObjects', this.data.id, 1)
@@ -969,14 +969,13 @@ function SimpleObjectAdd(p0, p1, mode) {
SimpleObjectAdd.prototype = new Base()
function SimpleObjectDelete(id) {
- this.data = { id, p0: null, p1: null, item: null }
+ this.data = { id, pos: null, item: null }
let performed = false
this.execute = function (restruct) {
const struct = restruct.molecule
if (!performed) {
const item = struct.simpleObjects.get(this.data.id)
- this.data.p0 = item.p0
- this.data.p1 = item.p1
+ this.data.pos = item.pos
this.data.mode = item.mode
}
@@ -1004,8 +1003,7 @@ function SimpleObjectMove(id, d, noinvalidate) {
const id = this.data.id
const d = this.data.d
const item = struct.simpleObjects.get(id)
- item.p0.add_(d)
- item.p1.add_(d)
+ item.pos.forEach(p => p.add_(d))
restruct.simpleObjects
.get(id)
.visel.translate(scale.obj2scaled(d, restruct.render.options))
@@ -1029,7 +1027,9 @@ function SimpleObjectResize(id, d, noinvalidate) {
const id = this.data.id
const d = this.data.d
const item = struct.simpleObjects.get(id)
- item.p1.add_(d)
+
+ //JA: TODO
+ if (d) item.pos[1].add_(d)
restruct.simpleObjects
.get(id)
.visel.translate(scale.obj2scaled(d, restruct.render.options))
diff --git a/src/script/editor/shared/closest.js b/src/script/editor/shared/closest.js
index cad1798e3b..53628c4560 100644
--- a/src/script/editor/shared/closest.js
+++ b/src/script/editor/shared/closest.js
@@ -36,8 +36,7 @@ function findClosestSimpleObject(restruct, pos) {
let ret = null
restruct.simpleObjects.forEach((simpleObject, id) => {
- const p = simpleObject.item.center()
- const dist = Math.max(Math.abs(pos.x - p.x), Math.abs(pos.y - p.y))
+ const dist = simpleObject.calcDistance(pos)
if (dist < 0.3 && (!ret || dist < minDist)) {
minDist = dist
diff --git a/src/script/editor/tool/helper/locate.js b/src/script/editor/tool/helper/locate.js
index d64b891b5d..4c4a16e76b 100644
--- a/src/script/editor/tool/helper/locate.js
+++ b/src/script/editor/tool/helper/locate.js
@@ -72,10 +72,10 @@ function getElementsInRectangle(restruct, p0, p1) {
restruct.simpleObjects.forEach((item, id) => {
if (
- item.item.p0.x > x0 &&
- item.item.p0.x < x1 &&
- item.item.p0.y > y0 &&
- item.item.p0.y < y1
+ item.item.pos[0].x > x0 &&
+ item.item.pos[0].x < x1 &&
+ item.item.pos[0].y > y0 &&
+ item.item.pos[0].y < y1
)
simpleObjectsList.push(id)
})
@@ -144,7 +144,7 @@ function getElementsInPolygon(restruct, rr) {
})
restruct.simpleObjects.forEach((item, id) => {
- if (isPointInPolygon(r, item.item.p0)) simpleObjectsList.push(id)
+ if (isPointInPolygon(r, item.item.pos[0])) simpleObjectsList.push(id)
})
const enhancedFlagList = []
diff --git a/src/script/editor/tool/simpleobject.js b/src/script/editor/tool/simpleobject.js
index d49281d391..718c2e988a 100644
--- a/src/script/editor/tool/simpleobject.js
+++ b/src/script/editor/tool/simpleobject.js
@@ -33,6 +33,7 @@ SimpleObjectTool.prototype.mousedown = function (event) {
var rnd = this.editor.render
const p0 = rnd.page2obj(event)
this.dragCtx = { p0 }
+
var ci = this.editor.findItem(event, ['simpleObjects'])
if (ci && ci.map === 'simpleObjects') {
this.editor.hover(null)
@@ -61,8 +62,7 @@ SimpleObjectTool.prototype.mousemove = function (event) {
if (!this.dragCtx.action) {
const action = fromSimpleObjectAddition(
rnd.ctab,
- this.dragCtx.p0,
- this.dragCtx.p0,
+ [this.dragCtx.p0, this.dragCtx.p0],
this.mode
)
//TODO: need to rework actions/operations logic
@@ -74,6 +74,7 @@ SimpleObjectTool.prototype.mousemove = function (event) {
} else {
this.dragCtx.action.perform(rnd.ctab)
}
+
this.dragCtx.action = fromSimpleObjectResizing(
rnd.ctab,
this.dragCtx.itemId,
@@ -98,8 +99,7 @@ SimpleObjectTool.prototype.mouseup = function (event) {
)
this.dragCtx.action = fromSimpleObjectAddition(
rnd.ctab,
- this.dragCtx.p0,
- this.dragCtx.previous,
+ [this.dragCtx.p0, this.dragCtx.previous],
this.mode
)
}
diff --git a/src/script/format/chemGraph/toGraph/prepare.js b/src/script/format/chemGraph/toGraph/prepare.js
index c20b9ccb28..962dcdb898 100644
--- a/src/script/format/chemGraph/toGraph/prepare.js
+++ b/src/script/format/chemGraph/toGraph/prepare.js
@@ -71,11 +71,10 @@ export function prepareStructForGraph(struct) {
struct.simpleObjects.forEach(item => {
graphNodes.push({
type: 'simpleObject',
- center: item.p0,
+ center: item.pos[0],
data: {
mode: item.mode,
- p0: item.p0,
- p1: item.p1
+ pos: item.pos
}
})
})
diff --git a/src/script/format/schemes/simpleObjectSchema.js b/src/script/format/schemes/simpleObjectSchema.js
index 062ef55210..8dd0c0fdd0 100644
--- a/src/script/format/schemes/simpleObjectSchema.js
+++ b/src/script/format/schemes/simpleObjectSchema.js
@@ -34,32 +34,25 @@ const schema = {
mode: {
type: 'string'
},
- p0: {
- type: 'object',
- properties: {
- x: {
- type: 'integer'
- },
- y: {
- type: 'integer'
+ pos: {
+ type: 'array',
+ items: [
+ {
+ type: 'object',
+ properties: {
+ x: {
+ type: 'integer'
+ },
+ y: {
+ type: 'integer'
+ }
+ },
+ required: ['x', 'y']
}
- },
- required: ['x', 'y']
- },
- p1: {
- type: 'object',
- properties: {
- x: {
- type: 'integer'
- },
- y: {
- type: 'integer'
- }
- },
- required: ['x', 'y']
+ ]
}
},
- required: ['type', 'mode', 'p0', 'p1']
+ required: ['type', 'mode', 'pos']
}
}
}
diff --git a/src/script/render/draw.js b/src/script/render/draw.js
index 4fe1a0451e..f5033c6ad6 100644
--- a/src/script/render/draw.js
+++ b/src/script/render/draw.js
@@ -20,18 +20,30 @@ import Raphael from '../raphael-ext'
const tfx = util.tfx
-function rectangle(paper, p0, p1, options) {
+function rectangle(paper, pos, options) {
return paper.rect(
- tfx(Math.min(p0.x, p1.x)),
- tfx(Math.min(p0.y, p1.y)),
- tfx(Math.abs(p1.x - p0.x)),
- tfx(Math.abs(p1.y - p0.y))
+ tfx(Math.min(pos[0].x, pos[1].x)),
+ tfx(Math.min(pos[0].y, pos[1].y)),
+ tfx(Math.abs(pos[1].x - pos[0].x)),
+ tfx(Math.abs(pos[1].y - pos[0].y))
)
}
-function circle(paper, p0, p1, options) {
- let rad = Math.sqrt(Math.pow(p0.x - p1.x, 2), Math.pow(p0.y - p1.y, 2))
- return paper.circle(p0.x, p0.y, rad)
+function circle(paper, pos, options) {
+ const rad = Vec2.dist(pos[0], pos[1])
+ return paper.circle(pos[0].x, pos[0].y, rad)
+}
+
+function polyline(paper, pos, options) {
+ let path = ['M', pos[0].x, pos[0].y]
+ for (let i = 1; i < pos.length; i++) path.push('L', pos[i].x, pos[i].y)
+ return paper.path(path)
+}
+
+function line(paper, pos, options) {
+ let path = ['M', pos[0].x, pos[0].y]
+ path.push('L', pos[1].x, pos[1].y)
+ return paper.path(path)
}
function arrow(paper, a, b, options) {
@@ -394,5 +406,7 @@ export default {
selectionPolygon,
selectionLine,
circle,
- rectangle
+ rectangle,
+ polyline,
+ line
}
diff --git a/src/script/render/options.js b/src/script/render/options.js
index fc8d2561ac..857b1f5d07 100644
--- a/src/script/render/options.js
+++ b/src/script/render/options.js
@@ -86,6 +86,12 @@ function defaultOptions(opt) {
stroke: 'gray',
'stroke-width': '1px'
},
+ highlightStyleSimpleObject: {
+ stroke: '#0c0',
+ 'stroke-width': scaleFactor / 4,
+ 'stroke-linecap': 'round',
+ 'stroke-opacity': 0.6
+ },
atomSelectionPlateRadius: labelFontSize * 1.2
}
diff --git a/src/script/render/restruct/index.js b/src/script/render/restruct/index.js
index faf277b238..c223ee2d7d 100644
--- a/src/script/render/restruct/index.js
+++ b/src/script/render/restruct/index.js
@@ -245,15 +245,19 @@ ReStruct.prototype.addReObjectPath = function (
// eslint-disable-line max-params
if (!path || !this.layers[LAYER_MAP[group]].node.parentNode) return
- const offset = this.render.options.offset
- let bb = visible ? Box2Abs.fromRelBox(util.relBox(path.getBBox())) : null
- const ext = pos && bb ? bb.translate(pos.negated()) : null
- if (offset !== null) {
- path.translateAbs(offset.x, offset.y)
- bb = bb ? bb.translate(offset) : null
- }
- visel.add(path, bb, ext)
- path.insertBefore(this.layers[LAYER_MAP[group]])
+ const paths = Array.isArray(path) ? path : [path]
+
+ paths.forEach(path => {
+ const offset = this.render.options.offset
+ let bb = visible ? Box2Abs.fromRelBox(util.relBox(path.getBBox())) : null
+ const ext = pos && bb ? bb.translate(pos.negated()) : null
+ if (offset !== null) {
+ path.translateAbs(offset.x, offset.y)
+ bb = bb ? bb.translate(offset) : null
+ }
+ visel.add(path, bb, ext)
+ path.insertBefore(this.layers[LAYER_MAP[group]])
+ })
}
ReStruct.prototype.clearMarks = function () {
diff --git a/src/script/render/restruct/resimpleobject.js b/src/script/render/restruct/resimpleobject.js
index 8e72ddf61d..9ef8a07e1f 100644
--- a/src/script/render/restruct/resimpleobject.js
+++ b/src/script/render/restruct/resimpleobject.js
@@ -21,6 +21,8 @@ import util from '../util'
import scale from '../../util/scale'
import Vec2 from 'src/script/util/vec2'
+const tfx = util.tfx
+
function ReSimpleObject(simpleObject) {
this.init('simpleObject')
@@ -30,17 +32,179 @@ ReSimpleObject.prototype = new ReObject()
ReSimpleObject.isSelectable = function () {
return true
}
+ReSimpleObject.prototype.calcDistance = function (p) {
+ const point = new Vec2(p.x, p.y)
+ let dist = 0
+ switch (this.item.mode) {
+ case 'circle': {
+ const dist1 = Vec2.dist(point, this.item.pos[0])
+ const dist2 = Vec2.dist(this.item.pos[0], this.item.pos[1])
+ dist = Math.max(dist1, dist2) - Math.min(dist1, dist2)
+ break
+ }
+ case 'rectangle': {
+ const diffX = Math.min(
+ Math.max(this.item.pos[0].x, point.x) -
+ Math.min(this.item.pos[0].x, point.x),
+ Math.max(this.item.pos[1].x, point.x) -
+ Math.min(this.item.pos[1].x, point.x)
+ )
+ const diffY = Math.min(
+ Math.max(this.item.pos[0].y, point.y) -
+ Math.min(this.item.pos[0].y, point.y),
+ Math.max(this.item.pos[1].y, point.y) -
+ Math.min(this.item.pos[1].y, point.y)
+ )
+ dist = Math.min(diffX, diffY)
+ break
+ }
+ case 'line': {
+ if (
+ (point.x < Math.min(this.item.pos[0].x, this.item.pos[1].x) ||
+ point.x > Math.max(this.item.pos[0].x, this.item.pos[1].x)) &&
+ (point.y < Math.min(this.item.pos[0].y, this.item.pos[1].y) ||
+ point.y > Math.max(this.item.pos[0].y, this.item.pos[1].y))
+ )
+ dist = Math.min(
+ Vec2.dist(this.item.pos[0], point),
+ Vec2.dist(this.item.pos[1], point)
+ )
+ else {
+ const a = Vec2.dist(this.item.pos[0], this.item.pos[1])
+ const b = Vec2.dist(this.item.pos[0], point)
+ const c = Vec2.dist(this.item.pos[1], point)
+ const per = (a + b + c) / 2
+ dist = (2 / a) * Math.sqrt(per * (per - a) * (per - b) * (per - c))
+ }
+ break
+ }
+ default: {
+ throw new Error('Unsupported shape type')
+ }
+ }
+
+ return dist
+}
ReSimpleObject.prototype.highlightPath = function (render) {
- var p = scale.obj2scaled(this.item.center(), render.options)
- var s = render.options.scale
- return render.paper.rect(p.x - s / 4, p.y - s / 4, s / 2, s / 2, s / 8)
+ const point = []
+
+ this.item.pos.forEach((p, index) => {
+ point[index] = scale.obj2scaled(p, render.options)
+ })
+ const s = render.options.scale
+
+ const path = []
+
+ //TODO: It seems that inheritance will be the better approach here
+ switch (this.item.mode) {
+ case 'circle': {
+ const rad = Vec2.dist(point[0], point[1])
+ path.push(
+ render.paper.circle(point[0].x, point[0].y, rad + s / 8),
+ render.paper.circle(point[0].x, point[0].y, rad - s / 8)
+ )
+ break
+ }
+
+ case 'rectangle': {
+ path.push(
+ render.paper.rect(
+ tfx(Math.min(point[0].x, point[1].x) - s / 8),
+ tfx(Math.min(point[0].y, point[1].y) - s / 8),
+ tfx(
+ Math.max(point[0].x, point[1].x) -
+ Math.min(point[0].x, point[1].x) +
+ s / 4
+ ),
+ tfx(
+ Math.max(point[0].y, point[1].y) -
+ Math.min(point[0].y, point[1].y) +
+ s / 4
+ )
+ )
+ )
+
+ path.push(
+ render.paper.rect(
+ tfx(Math.min(point[0].x, point[1].x) + s / 8),
+ tfx(Math.min(point[0].y, point[1].y) + s / 8),
+ tfx(
+ Math.max(point[0].x, point[1].x) -
+ Math.min(point[0].x, point[1].x) -
+ s / 4
+ ),
+ tfx(
+ Math.max(point[0].y, point[1].y) -
+ Math.min(point[0].y, point[1].y) -
+ s / 4
+ )
+ )
+ )
+
+ break
+ }
+ case 'line': {
+ //TODO: reuse this code for polyline
+ const poly = []
+
+ let angle = Math.atan(
+ (point[1].y - point[0].y) / (point[1].x - point[0].x)
+ )
+
+ const p0 = { x: 0, y: 0 }
+ const p1 = { x: 0, y: 0 }
+
+ const k = point[0].x > point[1].x ? -1 : 1
+
+ p0.x = point[0].x - k * ((s / 8) * Math.cos(angle))
+ p0.y = point[0].y - k * ((s / 8) * Math.sin(angle))
+ p1.x = point[1].x + k * ((s / 8) * Math.cos(angle))
+ p1.y = point[1].y + k * ((s / 8) * Math.sin(angle))
+
+ poly.push(
+ 'M',
+ p0.x + ((k * s) / 8) * Math.sin(angle),
+ p0.y - ((k * s) / 8) * Math.cos(angle)
+ )
+ poly.push(
+ 'L',
+ p1.x + ((k * s) / 8) * Math.sin(angle),
+ p1.y - ((k * s) / 8) * Math.cos(angle)
+ )
+ poly.push(
+ 'L',
+ p1.x - ((k * s) / 8) * Math.sin(angle),
+ p1.y + ((k * s) / 8) * Math.cos(angle)
+ )
+ poly.push(
+ 'L',
+ p0.x - ((k * s) / 8) * Math.sin(angle),
+ p0.y + ((k * s) / 8) * Math.cos(angle)
+ )
+ poly.push(
+ 'L',
+ p0.x + ((k * s) / 8) * Math.sin(angle),
+ p0.y - ((k * s) / 8) * Math.cos(angle)
+ )
+
+ path.push(render.paper.path(poly))
+ break
+ }
+ default: {
+ throw new Error('Unsupported shape type')
+ }
+ }
+
+ return path
}
ReSimpleObject.prototype.drawHighlight = function (render) {
- var ret = this.highlightPath(render).attr(render.options.highlightStyle)
- render.ctab.addReObjectPath('highlighting', this.visel, ret)
- return ret
+ const paths = this.highlightPath(render).map(path =>
+ path.attr(render.options.highlightStyle)
+ )
+ render.ctab.addReObjectPath('highlighting', this.visel, paths)
+ return paths
}
ReSimpleObject.prototype.makeSelectionPlate = function (
@@ -48,24 +212,59 @@ ReSimpleObject.prototype.makeSelectionPlate = function (
paper,
styles
) {
- // TODO [MK] review parameters
- return this.highlightPath(restruct.render).attr(styles.selectionStyle)
+ const s = restruct.render.options.scale
+ const pos = []
+ this.item.pos.forEach((p, index) => {
+ pos[index] = scale.obj2scaled(p, restruct.render.options) || new Vec2()
+ })
+
+ let path = null
+ switch (this.item.mode) {
+ case 'circle': {
+ path = draw.circle(paper, pos)
+ break
+ }
+ case 'rectangle': {
+ path = draw.rectangle(paper, pos)
+ break
+ }
+ case 'line': {
+ path = draw.line(paper, pos)
+ break
+ }
+ default: {
+ throw new Error('Unsupported shape type')
+ }
+ }
+
+ return path.attr(styles.highlightStyleSimpleObject)
}
ReSimpleObject.prototype.show = function (restruct, id, options) {
const render = restruct.render
- const p0 = scale.obj2scaled(this.item.p0, options)
- const p1 = scale.obj2scaled(this.item.p1, options)
+ const s = render.options.scale
+ const pos = []
+ this.item.pos.forEach((p, index) => {
+ pos[index] = scale.obj2scaled(p, options) || new Vec2()
+ })
+
let path = null
switch (this.item.mode) {
case 'circle': {
- path = draw.circle(render.paper, p0, p1, options)
+ path = draw.circle(render.paper, pos, options)
break
}
- default: {
- path = draw.rectangle(render.paper, p0, p1, options)
+ case 'rectangle': {
+ path = draw.rectangle(render.paper, pos, options)
break
}
+ case 'line': {
+ path = draw.line(render.paper, pos, options)
+ break
+ }
+ default: {
+ throw new Error('Unsupported shape type')
+ }
}
var offset = options.offset
if (offset != null) path.translateAbs(offset.x, offset.y)
diff --git a/src/script/ui/action/tools.js b/src/script/ui/action/tools.js
index d1483fb98d..6c3e1dd68c 100644
--- a/src/script/ui/action/tools.js
+++ b/src/script/ui/action/tools.js
@@ -120,6 +120,10 @@ const toolActions = {
'shape-rectangle': {
title: 'Shape Rectangle',
action: { tool: 'simpleobject', opts: 'rectangle' }
+ },
+ 'shape-line': {
+ title: 'Shape Line',
+ action: { tool: 'simpleobject', opts: 'line' }
}
}
diff --git a/src/script/ui/app/toolbar.jsx b/src/script/ui/app/toolbar.jsx
index 44cfd800df..3cba9fa4eb 100644
--- a/src/script/ui/app/toolbar.jsx
+++ b/src/script/ui/app/toolbar.jsx
@@ -125,7 +125,7 @@ const toolbox = [
},
{
id: 'shape',
- menu: ['shape-circle', 'shape-rectangle']
+ menu: ['shape-circle', 'shape-rectangle', 'shape-line']
}
]
diff --git a/src/script/ui/dialog/template/template-attach.jsx b/src/script/ui/dialog/template/template-attach.jsx
index b994129b6f..5dc0d837c0 100644
--- a/src/script/ui/dialog/template/template-attach.jsx
+++ b/src/script/ui/dialog/template/template-attach.jsx
@@ -26,7 +26,8 @@ import { initAttach, setAttachPoints, setTmplName } from '../../state/templates'
const EDITOR_STYLES = {
selectionStyle: { fill: '#47b3ec', stroke: 'none' },
- highlightStyle: { stroke: '#1a7090', 'stroke-width': 1.2 }
+ highlightStyle: { stroke: '#1a7090', 'stroke-width': 1.2 },
+ highlightStyleSimpleObject: { 'stroke-opacity': 0.3 }
}
class Attach extends Component {
diff --git a/src/script/util/scale.js b/src/script/util/scale.js
index 5498e2e862..2bf464d6cd 100644
--- a/src/script/util/scale.js
+++ b/src/script/util/scale.js
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
-
function scaled2obj(v, options) {
return v.scaled(1 / options.scale)
}