# # tk/optionobj.rb : control options for a group of widgets # # NOTE: If you want to use key-only option (no value), # use Tk::None for the value of the key-only option. # # e.g. hash_kv({'aaa'=>1, 'bbb'=>Tk::None, 'ccc'=>3}) # => ["-aaa", 1, "-bbb", "-ccc", 3] # require 'tk' module Tk class OptionObj < Hash include TkUtil def initialize(hash = nil) super() @observ = [] update_without_notify(_symbolkey2str(hash)) if hash end def observ_info @observ.dup end def observs @observ.collect{|win| if win.kind_of?(Array) win[0] else win end } end def _remove_win(win) if win.kind_of?(Array) widget, method = win @observ.delete_if{|x| if x.kind_of?(Array) x[0] == widget else x == widget end } else @observ.delete_if{|x| if x.kind_of?(Array) x[0] == win else x == win end } end end private :_remove_win def assign(*wins) # win := # widget #==> call widget.configure(hash) # [widget] #==> call widget.configure(hash) # [widget, nil, {src=>target, ... }] # #==> call widget.configure(hash) # with converting hash-key # [widget, method] #==> call widget.method(hash) # [widget, method, {src=>target, ... }] # #==> call widget.method(hash) # with converting hash-key # [widget [receiver, method, arg, ... ]] # #==> call receiver.method(arg, ... , hash) # [widget [receiver, method, arg, ... ], {src=>target, ... }] # #==> call receiver.method(arg, ... , hash) # with onverting hash-key # # src := option_name_on_optobj # # target := # nil #==> not use the src # option_name_on_target_widget # [ option_name_on_target_widget, ... ] # #==> set all of them # wins.each{|win| _remove_win(win) @observ << win notify(win) } self end def unassign(*wins) wins.each{|win| _remove_win(win) } self end def notify(target = nil) if target targets = [target] elsif @observ.empty? return self else targets = @observ.dup end return self if empty? org_hash = _symbolkey2str(self) targets.each{|win| widget = receiver = win hash = org_hash begin if win.kind_of?(Array) widget, method, conv_tbl = win receiver = widget if conv_tbl hash = {} org_hash.each{|key, val| key = conv_tbl[key] if conv_tbl.key?(key) next unless key if key.kind_of?(Array) key.each{|k| hash[k] = val} else hash[key] = val end } end if method.kind_of?(Array) receiver, method, *args = method receiver.__send__(method, *(args << hash)) elsif method widget.__send__(method, hash) else widget.configure(hash) end else widget.configure(self) end rescue => e if ( ( widget.kind_of?(TkObject) \ && widget.respond_to?('exist?') \ && ! receiver.exist? ) \ || ( receiver.kind_of?(TkObject) \ && receiver.respond_to?('exist?') \ && ! receiver.exist? ) ) @observ.delete(win) else fail e end end } self end alias apply notify def +(hash) unless hash.kind_of?(Hash) fail ArgumentError, "expect a Hash" end new_obj = self.dup new_obj.update_without_notify(_symbolkey2str(hash)) new_obj end alias update_without_notify update def update(hash) update_without_notify(_symbolkey2str(hash)) notify end def configure(key, value=nil) if key.kind_of?(Hash) update(key) else store(key,value) end end def [](key) super(key.to_s) end alias cget [] def store(key, val) key = key.to_s super(key, val) notify end def []=(key, val) store(key,val) end def replace(hash) super(_symbolkey2str(hash)) notify end def default(opt) fail RuntimeError, "unknown option `#{opt}'" end private :default undef :default= end end