raubarede/Ruiby

View on GitHub
lib/ruiby_gtk/dyn_var.rb

Summary

Maintainability
A
35 mins
Test Coverage
# Creative Commons BY-SA :  Regis d'Aubarede <regis.aubarede@gmail.com>
# LGPL

=begin
DynVar is a Value object (as TkVariable) : 
* a DynVar represent a ruby variable, which recover read/write access.
* observer patern is use for to subscribe to a variable : each vriting will be submmitted to each
  subscriber
DynVar.stock(name,value) can be used for ensure that value will be persist to file by Ruiby-stock mecanisme.

Usage :
    var=DynVar.new(22)
    var.observ {|v| puts v} 
    .....
    Thread.new { sleep 1 ; var.value=var.value+1 }
    ....
    sleep 

v=DynVar.stock("VV",33)
p v.value
v.value=44
exit(0)

>first execution: 
 33
>seconde execution :
 44

Ruiby Usage:
===========
In widgets <entry,ientry,label,islider,check_button> the initial value (generaly a Number or a String) can be replaced by a DynVar 

>exemple :
v=DynVar("aa")
entry(v)
label(v)

>> each input in entry will change the string qshowed by label

see samples/dyn.rb

=end

################## Variable binding for widget : (shower/editor widget) <==> (int/float/string/bool variable) ###########

class DynVar
  class << self
    def stock(name,defv) 
      v= Ruiby.stock_get(name,defv)
      var=DynVar.new(v,name)
      if ! @ldyn
         @ldyn=[]    
         at_exit { DynVar.save_stock }
      end
      @ldyn << var
      var
    end
    def save_stock 
      (@ldyn||[]).each { |v| Ruiby.stock_put(v.name, v.value.to_s) if v.name }
    end
  end
  def initialize(v,name="") @value=v ; @abo={} ; @name=name end
  def set_name(name) @name=name                            end
  def name() @name                                         end
  def observ(&blk)  @abo[caller] = blk  ; blk.call(@value) end
  def do_notification()
     return if @abo.size==0
     abo=@abo.clone
     return if abo.size==0
     there=self
     gui_invoke_wait { after(100) { abo.each { |a,b|  b.call(there.value) } } } 
  end
  def value=(v)  (tr(@value,v);  @value=v ; do_notification()) if @value!=v end
  def value()     @value  end
  def set_as_bool(v) 
    @value=case  @value
         when Numeric then v ? 1 : 0 
         when String then v ? "1" : ""
         else !!v
    end
    do_notification()
  end
  def get_as_bool() 
    case @value
    when Numeric then @value!=0 
    when String then @value && @value.length>0
    else 
      !! @value
    end
  end
  def set_trace(on)
    @trace=on
  end
  def tr(old,neww)
    puts "trace var from #{old} to #{neww}" if @trace
  end
  def destroy()
    @abo=[]
  end
end

################################# Object binding
# As Struct, but data member are all DynVar
# see samples/dyn.rb
def make_DynClass(h={"dummy"=>"?"})
  Class.new() do
    def initialize(x={})
      @values=self.def_init().merge(x).each_with_object({}){ |(name,v),h|  h[name]=DynVar.new(v) }
    end
    define_method(:def_init) { h.dup } 
    define_method(:keys) {  h.keys }
    define_method(:to_h) {  @values.each_with_object({}) { |(k,v),h1| h1[k]=v.value} }
    h.each do |key,value|
      define_method(key) { @values[key] }
    end
  end
end  

# make_DynClass, but data are saved at exit time.
# see samples/dyn.rb
def make_StockDynClass(h={"dummy"=>"?"})
  Class.new() do
    def initialize(oname="",x={})
      @values=self.def_init().merge(x).each_with_object({}){ |(name,v),h| h[name]=DynVar.stock(oname+"/"+name,v)}
    end
    define_method(:def_init) { h.dup } 
    define_method(:keys) {  h.keys }
    define_method(:to_h) {  @values.each_with_object({}) { |(k,v),h1| h1[k]=v.value} }
    h.each do |key,value|
      define_method(key) { @values[key] }
    end
  end
end  
def make_StockDynObject(oname,h) make_StockDynClass(h).new(oname) end