motion_require "support/attr_default" =begin { delay: 0.5, duration: 2.5, # array of integers or symbols corresponding to UIViewAnimationOptions options: [:curve_ease_in, :autoreverse] operations: [{ # see operation/base.rb type: :move, from: 0, to: 40, id: :one }], after: { # another animation object } } =end module Walt class Animation extend Walt::Support::AttrDefault PROPERTIES = [:delay, :duration, :after, :operations, :options] attr_accessor *PROPERTIES def initialize(params = {}) params.each do |key, value| if PROPERTIES.include?(key.to_sym) self.send("#{key}=", value) end end end def after=(after) _after = after case after when Walt::Animation when NSDictionary _after = Walt::Animation.new(after) else raise "Invalid class for after animation #{after.inspect}" end @after = _after end attr_default :operations, [] def operations=(operations) _operations = [] operations.each do |op| case op when Walt::Operation::Base _operations << op when NSDictionary _operations << Walt::Operation.for(op) else raise "Invalid class for operation #{op.inspect}" end end @operations = _operations end attr_default :assets, {} def assets=(assets) _assets = {} case assets when NSArray assets.each do |asset| _asset = (asset.is_a?(Walt::Asset) ? asset : Walt::Asset.for(asset)) _assets[_asset.id] = _asset end when NSDictionary assets.each do |key, value| asset = value _asset = (asset.is_a?(Walt::Asset) ? asset : Walt::Asset.for(asset)) _assets[_asset.id] = _asset end else raise "Not a valid class for assets: #{assets.inspect}" end @assets = _assets end attr_default :options, [UIViewAnimationOptionCurveEaseInOut] def options=(options) _options = options.is_a?(NSArray) ? options : [options] @options = _options end def animation_options int = 0 self.options.each { |i| int = int | Walt::Support.constant("UIViewAnimationOption", i)} int end def animate @operations_completed = 0 self.operations.each do |operation| asset = self.assets[operation.id] if !asset raise "No asset found for operation #{operation} id #{operation.id}" end operation.setup(asset.view, self) UIView.animateWithDuration(self.duration, delay:self.delay.to_f, options:self.animation_options, animations:lambda { operation.finalize(asset.view, self) }, completion:lambda { |completed| @operations_completed += 1 if @operations_completed == self.operations.count && self.after self.after.assets = self.assets self.after.animate end } ) end end end end