kdf
Version:
290 lines (220 loc) • 9.09 kB
text/coffeescript
KDView = require './../../core/view.coffee'
KDCustomHTMLView = require './../../core/customhtmlview.coffee'
module.exports = class KDDiaScene extends KDView
constructor:(options = {}, data)->
options.cssClass = KD.utils.curry "kddia-scene", options.cssClass
options.bind = KD.utils.curry "mousemove", options.bind
options.lineCap or= "round"
options.lineWidth ?= 2
options.lineColor or= "#ccc"
options.lineColorActive or= "orange"
options.lineDashes ?= []
options.fakeLineColor or= "green"
options.fakeLineDashes ?= []
options.curveDistance ?= 50
super
= []
= []
= []
= []
= []
diaAdded:(container, diaObj)->
diaObj.on "JointRequestsLine", "handleLineRequest"
diaObj.on "DragInAction", => diaObj
diaObj.on "RemoveMyConnections", => diaObj
addContainer:(container, pos = {})->
container
container.on "NewDiaObjectAdded", "diaAdded"
container.on "DragInAction", "updateScene"
container.on "UpdateScene", "updateScene"
container.on "HighlightDia", "highlightLines"
.push container
padding = (container.getOption 'draggable')?.containment?.padding
if padding
pos.x = Math.max padding, pos.x ? 0
pos.y = Math.max padding, pos.y ? 0
container.setX pos.x if pos.x?
container.setY pos.y if pos.y?
drawFakeLine:(options={})->
{sx,sy,ex,ey} = options
.beginPath()
.moveTo sx, sy
.lineTo ex, ey
.lineCap = "lineCap"
.lineWidth = "lineWidth"
.strokeStyle = .parent.getOption('colorTag') or \
"fakeLineColor"
lineDashes = "fakeLineDashes"
.setLineDash lineDashes if lineDashes.length > 0
.stroke()
click:(e)->
return if e.target isnt e.currentTarget
mouseMove:(e)->
return unless
{x, y} = .getPos()
ex = x + (e.clientX - .getX())
ey = y + (e.clientY - .getY())
{sx:x, sy:y, ex, ey}
mouseUp:(e)->
return unless
targetId = $(e.target).closest(".kddia-object").attr("dia-id")
sourceId = .getDiaId()
delete
# Cleanup fake scene
return unless targetId
source = sourceId
target = targetId
target.joint = target, source unless target.joint
source, target if target.joint
guessJoint:(target, source)->
return "left" if source.joint is "right" and target.dia.joints.left?
return "right" if source.joint is "left" and target.dia.joints.right?
getDia:(id)->
# Find a better way for this
parts = ( id.match /dia\-((.*)\-joint\-(.*)|(.*))/ ).filter (m)->return !!m
return null unless parts
[objId, joint] = parts.slice(-2)
joint = null if objId is joint
for container in
break if dia = container.dias[objId]
return {dia, joint, container}
highlightLines:(dia=[], update=yes)->
if not Array.isArray dia then dia = [dia]
= dia
joint.off 'DeleteRequested' for joint in
container.emit 'UnhighlightDias' for container in
= []
if update
return unless .length is 1
dia = dia.first
for connection in
{source, target} = connection
if (source.dia is dia) or (target.dia is dia)
[source, target].forEach (conn)=>
conn.dia.setClass 'highlight'
unless conn.dia is dia
joint = conn.dia.joints[conn.joint]
if joint not in
joint.showDeleteButton()
joint.on 'DeleteRequested', 'disconnect'
.push joint
handleLineRequest:(joint)->
= joint
findTargetConnection:(dia, joint)->
isEqual = (connection)=>
(dia is connection.dia) and (joint is connection.joint)
activeDia = .first
for conn in
if ((isEqual conn.source) or (isEqual conn.target)) and \
((conn.source.dia is activeDia) or (conn.target.dia is activeDia))
return conn
# Needs refactoring ~ GG
disconnect:(dia, joint)->
return if .length isnt 1
connectionsToDelete = dia, joint
= (c for c in when c isnt connectionsToDelete)
disconnectAllConnections:(dia)->
newConnections = []
for connection in
{source, target} = connection
if dia.getDiaId() not in [source.dia.getDiaId(), target.dia.getDiaId()]
newConnections.push connection
= newConnections
allowedToConnect: (source, target)->
return no unless source and target
return no if source.dia?.id is target.dia?.id
for i in [0..1]
if source.dia.allowedConnections? and \
Object.keys(source.dia.allowedConnections).length > 0
allowList = source.dia.allowedConnections
restrictions = allowList[target.dia.constructor.name]
return no unless restrictions
return no if source.joint in restrictions
[source, target] = [target, source]
return yes
connect:(source, target, update=yes)->
return if not source, target
# log "Connecting #{source.dia.id} to #{target.dia.id}"
"ConnectionCreated", source, target
.push {source, target}
target.dia, update
resetScene:->
= []
updateScene:->
connection for connection in
connection for connection in
drawConnectionLine:({source, target, options})->
return unless source or target
options or= {}
activeColor = 'lineColorActive'
lineDashes = 'lineDashes'
lineColor = 'lineColor'
.beginPath()
activeDia = if source.dia in then source \
else if target.dia in then target
if activeDia
lineColor = options.lineColor or \
(activeDia.dia.getOption 'colorTag') or activeColor
lineDashes = options.lineDashes or \
(activeDia.dia.getOption 'lineDashes') or lineDashes
sJoint = source.dia.getJointPos source.joint
tJoint = target.dia.getJointPos target.joint
.strokeStyle = lineColor
.setLineDash lineDashes if lineDashes.length > 0
.moveTo sJoint.x, sJoint.y
cd = 'curveDistance'
[sx, sy, tx, ty] = [0, 0, 0, 0]
if source.joint in ["top", "bottom"]
sy = if source.joint is "top" then -cd else cd
else if source.joint in ["left", "right"]
sx = if source.joint is "left" then -cd else cd
if target.joint in ["top", "bottom"]
ty = if target.joint is "top" then -cd else cd
else if target.joint in ["left", "right"]
tx = if target.joint is "left" then -cd else cd
.bezierCurveTo(sJoint.x + sx, sJoint.y + sy, \
tJoint.x + tx, tJoint.y + ty, \
tJoint.x, tJoint.y)
.lineWidth = 'lineWidth'
.stroke()
addFakeConnection:(connection)->
connection
.push connection
createCanvas:->
?.destroy()
?.destroy()
= new KDCustomHTMLView
tagName : "canvas"
attributes :
= .getElement().getContext "2d"
# Fallback function for Firefox and Safari
# which does not support lineDashes correctly ~ GG
.setLineDash = noop unless .setLineDash?
= new KDCustomHTMLView
tagName : "canvas"
cssClass : "fakeCanvas"
attributes :
= .getElement().getContext "2d"
setScale:(scale = 1)->
container.setScale scale for container in
cleanup:(canvas)->
canvas.setAttributes
parentDidResize:->
super
do _.throttle =>
getSceneSize:-> width: , height:
dumpScene:->
log ,
reset:(update = yes)->
= []
= []
if update