2014-07-30 03:23:16 +08:00
|
|
|
MAX_PATHS_IN_SEQUENCE = 30
|
|
|
|
|
|
|
|
# A line in the whiteboard
|
|
|
|
# Note: is used to draw lines from the pencil tool and from the line tool, this is why some
|
|
|
|
# methods can receive different set of parameters.
|
|
|
|
# TODO: Maybe this should be split in WhiteboardPathModel for the pencil and
|
|
|
|
# WhiteboardLineModel for the line tool
|
|
|
|
class @WhiteboardLineModel extends WhiteboardToolModel
|
|
|
|
|
|
|
|
constructor: (@paper) ->
|
|
|
|
super @paper
|
|
|
|
|
|
|
|
# the defintion of this shape, kept so we can redraw the shape whenever needed
|
|
|
|
# format: svg path, stroke color, thickness
|
|
|
|
@definition = ["", "#000", "0px"]
|
|
|
|
|
|
|
|
# @lineX = null
|
|
|
|
# @lineY = null
|
|
|
|
|
|
|
|
# Creates a line in the paper
|
|
|
|
# @param {number} x the x value of the line start point as a percentage of the original width
|
|
|
|
# @param {number} y the y value of the line start point as a percentage of the original height
|
|
|
|
# @param {string} colour the colour of the shape to be drawn
|
|
|
|
# @param {number} thickness the thickness of the line to be drawn
|
|
|
|
make: (info) ->
|
|
|
|
console.log "in line MAKE(info): " + info
|
2014-08-01 23:01:44 +08:00
|
|
|
if info?.payload?.data?.coordinate?
|
|
|
|
x = info.payload.data.coordinate.first_x
|
|
|
|
y = info.payload.data.coordinate.first_y
|
|
|
|
color = info.payload.data.line.color
|
|
|
|
thickness = info.payload.data.line.weight
|
|
|
|
|
|
|
|
x1 = x * @gw + @xOffset
|
|
|
|
y1 = y * @gh + @yOffset
|
|
|
|
path = "M" + x1 + " " + y1 + " L" + x1 + " " + y1
|
|
|
|
pathPercent = "M" + x + " " + y + " L" + x + " " + y
|
|
|
|
@obj = @paper.path(path)
|
|
|
|
@obj.attr Utils.strokeAndThickness(color, thickness)
|
|
|
|
@obj.attr({"stroke-linejoin": "round"})
|
|
|
|
|
|
|
|
@definition =
|
|
|
|
shape: "path"
|
|
|
|
data: [pathPercent, @obj.attrs["stroke"], @obj.attrs["stroke-width"]]
|
2014-07-30 03:23:16 +08:00
|
|
|
|
|
|
|
@obj
|
|
|
|
|
|
|
|
# Update the line dimensions
|
|
|
|
# @param {number} x1 1) the x of the first point
|
|
|
|
# 2) the next x point to be added to the line
|
|
|
|
# @param {number} y1 1) the y of the first point
|
|
|
|
# 2) the next y point to be added to the line
|
|
|
|
# @param {number,boolean} x2 1) the x of the second point
|
|
|
|
# 2) true if the line should be added to the current line,
|
|
|
|
# false if it should replace the last point
|
|
|
|
# @param {number} y2 1) the y of the second point
|
|
|
|
# 2) undefined
|
|
|
|
update: (info) ->
|
|
|
|
console.log "in line-UPDATE(info): " + info
|
2014-08-01 23:01:44 +08:00
|
|
|
if info?.payload?.data?.coordinate?
|
|
|
|
x1 = info.payload.data.coordinate.first_x
|
|
|
|
y1 = info.payload.data.coordinate.first_y
|
|
|
|
x2 = info.payload.data.coordinate.last_x
|
|
|
|
y2 = info.payload.data.coordinate.last_y
|
2014-07-30 03:23:16 +08:00
|
|
|
|
2014-08-01 23:01:44 +08:00
|
|
|
if @obj?
|
2014-07-30 03:23:16 +08:00
|
|
|
|
2014-08-01 23:01:44 +08:00
|
|
|
# if adding points from the pencil
|
|
|
|
if _.isBoolean(info.adding)
|
|
|
|
add = info.adding
|
2014-07-30 03:23:16 +08:00
|
|
|
|
2014-08-01 23:01:44 +08:00
|
|
|
pathPercent = "L" + x1 + " " + y1
|
|
|
|
@definition.data[0] += pathPercent
|
2014-07-30 03:23:16 +08:00
|
|
|
|
2014-08-01 23:01:44 +08:00
|
|
|
x1 = x1 * @gw + @xOffset
|
|
|
|
y1 = y1 * @gh + @yOffset
|
2014-07-30 03:23:16 +08:00
|
|
|
|
2014-08-01 23:01:44 +08:00
|
|
|
# if adding to the line
|
|
|
|
if add
|
|
|
|
path = @obj.attrs.path + "L" + x1 + " " + y1
|
|
|
|
@obj.attr path: path
|
2014-07-30 03:23:16 +08:00
|
|
|
|
2014-08-01 23:01:44 +08:00
|
|
|
# if simply updating the last portion (for drawing a straight line)
|
|
|
|
else
|
|
|
|
@obj.attrs.path.pop()
|
|
|
|
path = @obj.attrs.path.join(" ")
|
|
|
|
path = path + "L" + x1 + " " + y1
|
|
|
|
@obj.attr path: path
|
2014-07-30 03:23:16 +08:00
|
|
|
|
2014-08-01 23:01:44 +08:00
|
|
|
# adding lines from the line tool
|
2014-07-30 03:23:16 +08:00
|
|
|
else
|
2014-08-01 23:01:44 +08:00
|
|
|
path = @_buildPath(x1, y1, x2, y2)
|
|
|
|
@definition.data[0] = path
|
2014-07-30 03:23:16 +08:00
|
|
|
|
2014-08-01 23:01:44 +08:00
|
|
|
path = @_scaleLinePath(path, @gw, @gh, @xOffset, @yOffset)
|
|
|
|
@obj.attr path: path
|
2014-07-30 03:23:16 +08:00
|
|
|
|
|
|
|
# Draw a line on the paper
|
|
|
|
# @param {number,string} x1 1) the x value of the first point
|
|
|
|
# 2) the string path
|
|
|
|
# @param {number,string} y1 1) the y value of the first point
|
|
|
|
# 2) the colour
|
|
|
|
# @param {number} x2 1) the x value of the second point
|
|
|
|
# 2) the thickness
|
|
|
|
# @param {number} y2 1) the y value of the second point
|
|
|
|
# 2) undefined
|
|
|
|
# @param {string} colour 1) the colour of the shape to be drawn
|
|
|
|
# 2) undefined
|
|
|
|
# @param {number} thickness 1) the thickness of the line to be drawn
|
|
|
|
# 2) undefined
|
|
|
|
draw: (x1, y1, x2, y2, colour, thickness) ->
|
|
|
|
|
|
|
|
# if the drawing is from the pencil tool, it comes as a path first
|
|
|
|
if _.isString(x1)
|
|
|
|
colour = y1
|
|
|
|
thickness = x2
|
|
|
|
path = x1
|
|
|
|
|
|
|
|
# if the drawing is from the line tool, it comes with two points
|
|
|
|
else
|
|
|
|
path = @_buildPath(x1, y1, x2, y2)
|
|
|
|
|
|
|
|
line = @paper.path(@_scaleLinePath(path, @gw, @gh, @xOffset, @yOffset))
|
|
|
|
line.attr Utils.strokeAndThickness(colour, thickness)
|
|
|
|
line.attr({"stroke-linejoin": "round"})
|
|
|
|
line
|
|
|
|
|
|
|
|
# When dragging for drawing lines starts
|
|
|
|
# @param {number} x the x value of the cursor
|
|
|
|
# @param {number} y the y value of the cursor
|
|
|
|
# TODO: moved here but not finished
|
|
|
|
dragOnStart: (x, y) ->
|
|
|
|
# # find the x and y values in relation to the whiteboard
|
|
|
|
# sx = (@paperWidth - @gw) / 2
|
|
|
|
# sy = (@paperHeight - @gh) / 2
|
|
|
|
# @lineX = x - @containerOffsetLeft - sx + @xOffset
|
|
|
|
# @lineY = y - @containerOffsetTop - sy + @yOffset
|
|
|
|
# values = [ @lineX / @paperWidth, @lineY / @paperHeight, @currentColour, @currentThickness ]
|
|
|
|
# globals.connection.emitMakeShape "line", values
|
|
|
|
|
|
|
|
# As line drawing drag continues
|
|
|
|
# @param {number} dx the difference between the x value from _lineDragStart and now
|
|
|
|
# @param {number} dy the difference between the y value from _lineDragStart and now
|
|
|
|
# @param {number} x the x value of the cursor
|
|
|
|
# @param {number} y the y value of the cursor
|
|
|
|
# TODO: moved here but not finished
|
|
|
|
dragOnMove: (dx, dy, x, y) ->
|
|
|
|
# sx = (@paperWidth - @gw) / 2
|
|
|
|
# sy = (@paperHeight - @gh) / 2
|
|
|
|
# [cx, cy] = @_currentSlideOffsets()
|
|
|
|
# # find the x and y values in relation to the whiteboard
|
|
|
|
# @cx2 = x - @containerOffsetLeft - sx + @xOffset
|
|
|
|
# @cy2 = y - @containerOffsetTop - sy + @yOffset
|
|
|
|
# if @shiftPressed
|
|
|
|
# globals.connection.emitUpdateShape "line", [ @cx2 / @paperWidth, @cy2 / @paperHeight, false ]
|
|
|
|
# else
|
|
|
|
# @currentPathCount++
|
|
|
|
# if @currentPathCount < MAX_PATHS_IN_SEQUENCE
|
|
|
|
# globals.connection.emitUpdateShape "line", [ @cx2 / @paperHeight, @cy2 / @paperHeight, true ]
|
|
|
|
# else if @obj?
|
|
|
|
# @currentPathCount = 0
|
|
|
|
# # save the last path of the line
|
|
|
|
# @obj.attrs.path.pop()
|
|
|
|
# path = @obj.attrs.path.join(" ")
|
|
|
|
# @obj.attr path: (path + "L" + @lineX + " " + @lineY)
|
|
|
|
|
|
|
|
# # scale the path appropriately before sending
|
|
|
|
# pathStr = @obj.attrs.path.join(",")
|
|
|
|
# globals.connection.emitPublishShape "path",
|
|
|
|
# [ @_scaleLinePath(pathStr, 1 / @gw, 1 / @gh),
|
|
|
|
# @currentColour, @currentThickness ]
|
|
|
|
# globals.connection.emitMakeShape "line",
|
|
|
|
# [ @lineX / @paperWidth, @lineY / @paperHeight, @currentColour, @currentThickness ]
|
|
|
|
# @lineX = @cx2
|
|
|
|
# @lineY = @cy2
|
|
|
|
|
|
|
|
# Drawing line has ended
|
|
|
|
# @param {Event} e the mouse event
|
|
|
|
# TODO: moved here but not finished
|
|
|
|
dragOnEnd: (e) ->
|
|
|
|
# if @obj?
|
|
|
|
# path = @obj.attrs.path
|
|
|
|
# @obj = null # any late updates will be blocked by this
|
|
|
|
# # scale the path appropriately before sending
|
|
|
|
# globals.connection.emitPublishShape "path",
|
|
|
|
# [ @_scaleLinePath(path.join(","), 1 / @gw, 1 / @gh),
|
|
|
|
# @currentColour, @currentThickness ]
|
|
|
|
|
|
|
|
_buildPath: (x1, y1, x2, y2) ->
|
|
|
|
"M#{x1} #{y1}L#{x2} #{y2}"
|
|
|
|
|
|
|
|
# Scales a path string to fit within a width and height of the new paper size
|
|
|
|
# @param {number} w width of the shape as a percentage of the original width
|
|
|
|
# @param {number} h height of the shape as a percentage of the original height
|
|
|
|
# @return {string} the path string after being manipulated to new paper size
|
|
|
|
_scaleLinePath: (string, w, h, xOffset=0, yOffset=0) ->
|
|
|
|
path = null
|
|
|
|
points = string.match(/(\d+[.]?\d*)/g)
|
|
|
|
len = points.length
|
|
|
|
j = 0
|
|
|
|
|
|
|
|
# go through each point and multiply it by the new height and width
|
|
|
|
while j < len
|
|
|
|
if j isnt 0
|
|
|
|
path += "L" + (points[j] * w + xOffset) + "," + (points[j + 1] * h + yOffset)
|
|
|
|
else
|
|
|
|
path = "M" + (points[j] * w + xOffset) + "," + (points[j + 1] * h + yOffset)
|
|
|
|
j += 2
|
|
|
|
path
|