class Ducktape::Link

Attributes

binding_source[R]
converter[RW]
expression[RW]
mode[RW]
source[RW]
target[RW]

Public Class Methods

new(binding_source, target) click to toggle source
# File lib/ducktape/link.rb, line 15
def initialize(binding_source, target)
  @binding_source = binding_source
  @source         = WeakReference.new(binding_source.source)
  @expression     = Expression::BindingParser.parse(binding_source.path)
  @target         = WeakReference.new(target)
  @converter      = binding_source.converter
  @mode           = binding_source.mode

  @expression.owner = self
end

Public Instance Methods

bind() click to toggle source
# File lib/ducktape/link.rb, line 38
def bind
  with_cleanup { @expression.bind(@source.object, :value) }
  nil
end
broken?() click to toggle source
# File lib/ducktape/link.rb, line 26
def broken?
  !(@source && @target && @source.object && @target.object)
end
forward?() click to toggle source
# File lib/ducktape/link.rb, line 30
def forward?
  BindingSource::PROPAGATE_TO_TARGET.include?(@mode)
end
reverse?() click to toggle source
# File lib/ducktape/link.rb, line 34
def reverse?
  BindingSource::PROPAGATE_TO_SOURCE.include?(@mode)
end
source_value() click to toggle source
# File lib/ducktape/link.rb, line 58
def source_value
  assert_mode :get, :source, :forward
  with_cleanup { @converter.convert(@expression.value) }
end
target_value() click to toggle source
# File lib/ducktape/link.rb, line 63
def target_value
  assert_mode :get, :target, :reverse
  with_cleanup { @converter.revert(@target.object.value) }
end
unbind() click to toggle source
# File lib/ducktape/link.rb, line 43
def unbind
  with_cleanup { @expression.unbind }
  nil
end
update_source() click to toggle source
# File lib/ducktape/link.rb, line 48
def update_source
  assert_mode :set, :source, :reverse
  with_cleanup { @expression.value = target_value }
end
update_target() click to toggle source
# File lib/ducktape/link.rb, line 53
def update_target
  assert_mode :set, :target, :forward
  with_cleanup { @target.object.set_value source_value }
end

Private Instance Methods

assert_mode(accessor, type, mode) click to toggle source
# File lib/ducktape/link.rb, line 70
def assert_mode(accessor, type, mode)
  raise ModeError, "cannot #{accessor} #{type} value on a non #{mode} link" unless public_send("#{mode}?")
end
path_changed() click to toggle source
# File lib/ducktape/link.rb, line 74
def path_changed
  bind
  forward? ? update_target : update_source
  nil
end
value_changed() click to toggle source
# File lib/ducktape/link.rb, line 80
def value_changed
  return unless forward?
  update_target
  nil
end
with_cleanup() { || ... } click to toggle source
# File lib/ducktape/link.rb, line 86
def with_cleanup
  return yield unless broken?
  unbind if @expression
  @target.object.remove_source if @target && @target.object
  @source, @target, @expression = nil
end