Skip to content

Commit

Permalink
Fix being able to set parents in states
Browse files Browse the repository at this point in the history
  • Loading branch information
koenbok committed May 3, 2016
1 parent 908bfd0 commit 94e779d
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 29 deletions.
79 changes: 50 additions & 29 deletions framer/LayerStates.coffee
Expand Up @@ -57,12 +57,6 @@ class exports.LayerStates extends BaseClass
# Switches to a specific state. If animationOptions are
# given use those, otherwise the default options.

# We actually do want to allow this. A state can be set to something
# that does not equal the property values for that state.

# if stateName is @_currentState
# return

if not @_states.hasOwnProperty(stateName)
throw Error "No such state: '#{stateName}'"

Expand All @@ -84,7 +78,9 @@ class exports.LayerStates extends BaseClass
continue

# Allow dynamic properties as functions
value = value.call(@layer, @layer, propertyName, stateName) if _.isFunction(value)
if _.isFunction(value)
value = value.call(@layer, @layer, propertyName, stateName)

# Set the new value
properties[propertyName] = value

Expand All @@ -93,40 +89,45 @@ class exports.LayerStates extends BaseClass
animatablePropertyKeys = []

for k, v of properties

# We can animate numbers
if _.isNumber(v)
animatablePropertyKeys.push(k)

# We can animate colors
else if Color.isColorObject(v)
animatablePropertyKeys.push(k)
else if v == null
animatablePropertyKeys.push(k)

# If we don't have any animatable properties, we always switch instant
if animatablePropertyKeys.length == 0
instant = true

if instant is true
# We want to switch immediately without animation
if instant
@layer.props = properties
@emit Events.StateDidSwitch, _.last(@_previousStates), @_currentState, @
@emit(Events.StateDidSwitch, _.last(@_previousStates), @_currentState, @)
return

# If there are, we start the animation here
animationOptions ?= @animationOptions
animationOptions.properties = properties

else
# Start the animation and update the state when finished
animationOptions ?= @animationOptions
animationOptions.properties = properties
@_animation?.stop()
@_animation = @layer.animate(animationOptions)

@_animation?.stop()
@_animation = @layer.animate animationOptions
@_animation.once "stop", =>
# Once the animation is done, we set all the keys that we could not animate
@_animation.once "stop", =>

# Set all the values for keys that we couldn't animate
for k, v of properties
@layer[k] = v unless _.isNumber(v) or Color.isColorObject(v)
for k, v of properties
@layer[k] = v if v not in animatablePropertyKeys

@emit(Events.StateDidSwitch, _.last(@_previousStates), @_currentState, @) unless _.last(@_previousStates) is stateName
# If we changed the state, we send the event that we did
if _.last(@_previousStates) isnt stateName
@emit(Events.StateDidSwitch, _.last(@_previousStates), @_currentState, @)



switchInstant: (stateName) ->
@switch stateName, null, true
@switch(stateName, null, true)

@define "state", get: -> @_currentState
@define "current", get: -> @_currentState
Expand All @@ -138,7 +139,7 @@ class exports.LayerStates extends BaseClass

animatingKeys: ->

# Get a list of all the propeties controlled by states
# Get a list of all the properties controlled by states

keys = []

Expand Down Expand Up @@ -177,11 +178,31 @@ class exports.LayerStates extends BaseClass

# TODO: Maybe we want to support advanced data structures like objects in the future too.
for k, v of properties
# We check if the property name ends with color, because we don't want
# to convert every string that looks like a Color, like the html property containing "add"
if _.isString(v) and _.endsWith(k.toLowerCase(),"color") and Color.isColorString(v)

if @_isValidColor(k, v)
stateProperties[k] = new Color(v)
else if _.isNumber(v) or _.isFunction(v) or _.isBoolean(v) or _.isString(v) or Color.isColorObject(v) or v == null
continue

if @_isValidProperty(k, v)
stateProperties[k] = v

return stateProperties

@_isValidColor: (k, v) ->

# We check if the property name ends with color, because we don't want
# to convert every string that looks like a Color, like the html property containing "add"
if _.endsWith(k.toLowerCase(), "color") and _.isString(v) and Color.isColorString(v)
return true

return false

@_isValidProperty: (k, v) ->
return true if _.isNumber(v)
return true if _.isFunction(v)
return true if _.isBoolean(v)
return true if _.isString(v)
return true if Color.isColorObject(v)
return true if v is null
return true if v?.constructor?.name is "Layer"
return false
20 changes: 20 additions & 0 deletions test/tests/LayerStatesTest.coffee
@@ -1,3 +1,5 @@
assert = require "assert"

describe "LayerStates", ->

describe "Events", ->
Expand Down Expand Up @@ -179,3 +181,21 @@ describe "LayerStates", ->

layer.states.switchInstant "default"
layer.x.should.equal 0

it "should set the parent", ->

layerA = new Layer
layerB = new Layer
parent: layerA

layerB.states.add
stateA:
parent: null

assert.equal(layerB.parent, layerA)

layerB.states.switchInstant "stateA"
assert.equal(layerB.parent, null)

layerB.states.switchInstant "default"
# assert.equal(layerB.parent, layerA)

0 comments on commit 94e779d

Please sign in to comment.