Permalink
Browse files

refactor the event system, add lots of tweaks

  • Loading branch information...
1 parent b97189f commit a17f5072a16f995e41de9d34c117f57290175804 @caleb committed May 31, 2014
Showing with 277 additions and 145 deletions.
  1. +39 −14 lib/crop-box.coffee
  2. +103 −12 lib/drawing.coffee
  3. +10 −2 lib/events.coffee
  4. +3 −0 lib/funderscore.coffee
  5. +11 −105 lib/rodeo-crop.coffee
  6. +93 −0 lib/stage.coffee
  7. +18 −12 public/index.html
View
@@ -22,6 +22,7 @@ class CropBox extends drawing.Drawable
@cropHeight = options.cropHeight || @handleSize * 4
@dragging = null
+ @mouseDown = false
@handles = {}
@@ -37,6 +38,14 @@ class CropBox extends drawing.Drawable
@cropHeight = if previousCrop.h >= crop.h then crop.h else previousCrop.h
@setCropFrameAndUpdateFrame @cropFrame()
+ @on 'mouseout', @onMouseOut
+ @on 'mousemove', @onMouseMove
+ @on 'mousedown', @onMouseDown
+ @on 'mouseup', @onMouseUp
+ @on 'dragstart', @onDragStart
+ @on 'dragend', @onDragEnd
+ @on 'dragmove', @onDragMove
+
frame: () ->
{
x: if @w < 0 then @x + @w else @x
@@ -73,6 +82,7 @@ class CropBox extends drawing.Drawable
@h = frame.h
@updateCropFrameFromFrame()
+ @markDirty()
updateFrameFromCropFrame: () ->
naturalBounds = @image.naturalBounds()
@@ -84,6 +94,8 @@ class CropBox extends drawing.Drawable
@w = (imageBounds.w * (@cropWidth / naturalBounds.w))
@h = (imageBounds.h * (@cropHeight / naturalBounds.h))
+ @markDirty()
+
setCropFrameAndUpdateFrame: (cropArea) ->
naturalBounds = @image.naturalBounds()
@@ -127,10 +139,12 @@ class CropBox extends drawing.Drawable
return false
- onMouseOut: (point) ->
+ onMouseOut: (e) ->
@canvas.style.cursor = 'default'
- onMouseMove: (point) ->
+ onMouseMove: (e) ->
+ point = e.canvasPoint
+
for direction, handle of @handles
if handle.containsCanvasPoint point
switch direction
@@ -160,10 +174,12 @@ class CropBox extends drawing.Drawable
y: Math.min Math.max(point.y, 0), @parent.frame().h
}
- onMouseDown: (point) ->
onMouseUp: (point) ->
- @dragging = null
- onDragStart: (point) ->
+ @dragging = @mouseDown = null
+
+ onDragStart: (e) ->
+ point = e.canvasPoint
+
for direction, handle of @handles
if handle.containsCanvasPoint point
localPoint = handle.convertFromCanvas point
@@ -181,7 +197,9 @@ class CropBox extends drawing.Drawable
offsetX: localPoint.x
offsetY: localPoint.y
- onDragMove: (point) ->
+ onDragMove: (e) ->
+ point = e.canvasPoint
+
if @dragging?.object == @
# move the whole crop area
localPoint = @convertFromCanvas point
@@ -190,6 +208,7 @@ class CropBox extends drawing.Drawable
y: localPoint.y - @dragging.offsetY
@updateCropFrameFromFrame()
+ @markDirty()
else if @dragging?.resizeDirection
parentPoint = @parent.convertFromCanvas point
@@ -244,8 +263,11 @@ class CropBox extends drawing.Drawable
@y = @y
@updateCropFrameFromFrame()
+ @markDirty()
+
+ onDragEnd: (e) ->
+ point = e.canvasPoint
- onDragEnd: (point) ->
# reset our frame after a drag to fix negative widths/heights used during
# the dragging process
frame = @frame()
@@ -257,7 +279,7 @@ class CropBox extends drawing.Drawable
# trigger our change event at the end of the change
@trigger 'change', @cropFrame()
- onClick: (point) ->
+ onClick: (e) ->
moveTo: (point) ->
pos = @convertToParent point
@@ -305,10 +327,10 @@ class CropBox extends drawing.Drawable
w: @parent.w - (frame.x + frame.w)
h: frame.h
- @topScreen.draw ctx
- @leftScreen.draw ctx
- @rightScreen.draw ctx
- @bottomScreen.draw ctx
+ @topScreen.render ctx
+ @leftScreen.render ctx
+ @rightScreen.render ctx
+ @bottomScreen.render ctx
drawHandles: (ctx) ->
frame = @frame()
@@ -340,7 +362,7 @@ class CropBox extends drawing.Drawable
@handles["br"] = newRect frame.w, frame.h
for direction, handle of @handles
- handle.draw ctx
+ handle.render ctx
drawCropLines: (ctx) ->
frame = @frame()
@@ -352,7 +374,8 @@ class CropBox extends drawing.Drawable
opacity = "0.5"
lineDash = 8
- @isolateAndMoveToParent ctx, (ctx) =>
+ ctx.save()
+ @positionContext ctx, (ctx) =>
ctx.beginPath()
ctx.strokeStyle = "rgba(255,255,255,#{opacity})"
ctx.rect 0.5, 0.5, frame.w, frame.h
@@ -396,6 +419,8 @@ class CropBox extends drawing.Drawable
ctx.lineTo frame.w, y
ctx.stroke()
+ ctx.restore()
+
draw: (ctx) ->
@drawScreen ctx
@drawCropLines ctx
View
@@ -11,6 +11,7 @@ class Drawable extends Events
@y = options.y
@w = options.w
@h = options.h
+ @dirty = true
@scale = options.scale
@parent = options.parent
@canvas = options.canvas
@@ -22,6 +23,33 @@ class Drawable extends Events
for own key, value of options
@[key] = value
+ markDirty: () ->
+ @dirty = true
+ @parent.markDirty() if @parent
+
+ bubble: (eventName, event, args...) ->
+ event.currentTarget = @
+ @trigger.apply @, arguments
+
+ parent = @parent
+ while parent
+ # clone the event so we can change the current target for this listening node
+ event = _.clone event
+ event.currentTarget = parent
+ parent.trigger.apply parent, [eventName, event].concat(args)
+ parent = parent.parent
+
+ findChildAtPoint: (point) ->
+ i = @children.length - 1
+ while i >= 0
+ child = @children[i]
+ grandChild = child.findChildAtPoint point
+ if grandChild
+ return grandChild
+ else
+ return child if child.containsCanvasPoint point
+ i--
+
bounds: ->
{
x: 0
@@ -88,12 +116,6 @@ class Drawable extends Events
ctx.translate pos.x, pos.y
fn.call @, ctx
- isolateAndMoveToParent: (ctx, fn) ->
- ctx.save()
- @positionContext ctx, (ctx) ->
- fn.call @, ctx
- ctx.restore()
-
containsCanvasPoint: (point) ->
localPoint = @convertFromCanvas point
@containsPoint localPoint
@@ -106,22 +128,82 @@ class Drawable extends Events
addChild: (child) ->
child.parent = @
@children.push child
+ @markDirty()
removeChild: (child) ->
i = @children.indexOf child
if i >= 0
child.parent = null
@children.splice i, 1
+ @markDirty()
- drawChildren: (ctx) ->
+ renderChildren: (ctx) ->
for child in @children
- child.draw ctx if child.enabled
+ child.render ctx if child.enabled
+
+ clear: (ctx) ->
+ frame = @frame()
+ if @parent
+ positionContext ctx, (ctx) =>
+ ctx.clearRect frame.x, frame.y, frame.w, frame.h
+ else
+ ctx.clearRect frame.x, frame.y, frame.w, frame.h
+
+ render: (ctx) ->
+ ctx.save()
+ @draw ctx
+ ctx.restore()
+ @renderChildren ctx
+ @dirty = false
draw: (ctx) ->
# noop
drawing.Drawable = Drawable
+class PaddedContainer extends Drawable
+ constructor: (options = {}) ->
+ super options
+
+ @padding = options.padding || 10
+ @fillParent = options.fillParent || true
+
+ frame: () ->
+ if @fillParent
+ parentFrame = @parent.frame()
+ {
+ x: @padding
+ y: @padding
+ w: parentFrame.w - 2 * @padding
+ h: parentFrame.h - 2 * @padding
+ }
+ else
+ {
+ x: @x + @padding
+ y: @y + @padding
+ w: @w - 2 * @padding
+ h: @h - 2 * @padding
+ }
+
+ bounds: () ->
+ if @fillParent
+ parentFrame = @parent.frame()
+ {
+ x: 0
+ y: 0
+ w: parentFrame.w - 2 * @padding
+ h: parentFrame.h - 2 * @padding
+ }
+ else
+ {
+ x: 0
+ y: 0
+ w: @w - 2 * @padding
+ h: @h - 2 * @padding
+ }
+
+drawing.PaddedContainer = PaddedContainer
+
class CanvasImage extends Drawable
constructor: (options) ->
super options
@@ -151,6 +233,8 @@ class CanvasImage extends Drawable
@cropStack = []
@originalNaturalBounds = @naturalBounds()
+ @markDirty()
+
setSource: (source) ->
@clearImage()
@source = source
@@ -192,6 +276,8 @@ class CanvasImage extends Drawable
@trigger 'crop', @, @cropStack[@cropStack.length - 2], @cropFrame()
+ @markDirty()
+
undoCrop: () ->
@cropped = true
@@ -211,6 +297,8 @@ class CanvasImage extends Drawable
@trigger 'crop', @, previousCropFrame, @cropFrame()
+ @markDirty()
+
resizeToParent: () ->
cw = @parent.frame().w
ch = @parent.frame().h
@@ -234,28 +322,31 @@ class CanvasImage extends Drawable
@trigger 'reposition', @frame()
draw: (ctx) ->
- @isolateAndMoveToParent ctx, (ctx) ->
+ @positionContext ctx, (ctx) ->
if @cropped
ctx.drawImage @img, @cropX, @cropY, @cropWidth, @cropHeight, 0, 0, @w, @h
else
ctx.drawImage @img, 0, 0, @w, @h
- @drawChildren ctx
-
loadImage: ->
@img = document.createElement 'img'
@img.onload = =>
@loaded = true
@naturalWidth = @img.naturalWidth
@naturalHeight = @img.naturalHeight
+ @cropped = false
+ @cropStack = []
+
@cropX = 0
@cropY = 0
@cropWidth = @img.naturalWidth
@cropHeight = @img.naturalHeight
@cropStack.push @cropFrame()
+ @markDirty()
+
@trigger 'load', @
@img.src = @source
@@ -269,7 +360,7 @@ class Rectangle extends Drawable
@lineWidth = options.lineWidth
draw: (ctx) ->
- @isolateAndMoveToParent ctx, (ctx) =>
+ @positionContext ctx, (ctx) =>
ctx.fillStyle = @fillStyle if @fillStyle
ctx.strokeStyle = @strokeStyle if @strokeStyle
ctx.lineWidth = @lineWidth if @lineWidth
View
@@ -1,16 +1,24 @@
+`import _ from "funderscore"`
+
class Events
on: (event, callback, context) ->
@events ||= {}
@events[event] ||= []
- @events[event].push [callback, context]
+ @events[event].push [callback, context] if _.isFunction callback
trigger: (event) ->
tail = Array.prototype.slice.call arguments, 1
- callbacks = @events[event] || []
+ callbacks = if @events && @events[event] then @events[event] else []
for callbackStruct in callbacks
callback = callbackStruct[0]
context = callbackStruct[1] || @
callback.apply context, tail
+class Event
+ constructor: (options) ->
+ for k, v of options
+ @[k] = v
+
`export default Events`
+`export { Event }`
Oops, something went wrong.

0 comments on commit a17f507

Please sign in to comment.