Module: Such::Thing

Defined in:
lib/such/thing.rb

Constant Summary collapse

INTOS =

TODO:GTK!?

[:set_submenu, :pack_start, :append, :add]
PARAMETERS =
{}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.configure(conf) ⇒ Object



6
7
8
# File 'lib/such/thing.rb', line 6

def self.configure(conf)
  conf.each{|k,v| PARAMETERS[k]=v}
end

.do_config(obj, *parameters, &block) ⇒ Object



120
121
122
123
124
125
# File 'lib/such/thing.rb', line 120

def self.do_config(obj, *parameters, &block)
  container, arguments, methods, signals = Thing.do_parameters(parameters)
  Thing.do_methods(obj, methods, container)
  Thing.do_links(obj, signals, block)
  warn "Warning: arguments not used in do_config(#{obj.class}...)." if arguments.length > 0
end


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/such/thing.rb', line 101

def self.do_links(obj, signals, block)
  return if signals.first==''
  none = (signals.length==0)
  if block
    signals.push('clicked') if block and none # TODO: GTK!?
    signals.each do |signal|
      break if signal==''
      begin
        obj.signal_connect(signal){|*emits| block.call(*emits, signal)} # TODO: GTK!?
        Thing.trace_signal(obj, signal) if $VERBOSE
      rescue GLib::NoSignalError
        warn "Warning: no \"#{signal}\" signal for #{obj.class}"
      end
    end
  elsif not none
    warn "Warning: No block given for #{signals.join(',')} on #{obj.class}."
  end
end

.do_method(obj, mthd, *args) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/such/thing.rb', line 77

def self.do_method(obj, mthd, *args)
  Thing.trace_method(obj, mthd, args) if $VERBOSE
  m = obj.method(mthd)
  begin
    m.call(*args)
  rescue ArgumentError, TypeError
    # Assume user meant to iterate. Note that the heuristic is not perfect.
    $stderr.puts "# Iterated Method #{mthd} ^^^" if $VERBOSE
    [*args].each{|arg| m.call(*arg)}
    if $!.class == ArgumentError and not m.arity == 1
      warn "Warning: Iterated method's arity not one."
    end
  end
end

.do_methods(obj, methods, container = nil) ⇒ Object



92
93
94
95
96
97
98
99
# File 'lib/such/thing.rb', line 92

def self.do_methods(obj, methods, container=nil)
  # If user does not specify how to add to container, assume default way.
  methods[:into]=Thing.which_method(container) if container and !methods.has_key?(:into)
  methods.each do |mthd, args|
    (mthd==:into)? Thing.into(obj, container, *args) :
                   Thing.do_method(obj, mthd, *args)
  end
end

.do_parameters(parameters) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/such/thing.rb', line 33

def self.do_parameters(parameters)
  container, arguments, methods, signals = nil, [], {}, []
  while parameter = parameters.shift
    case parameter
    when Symbol
      # Symbols are expected to translate to something else.
      Thing.do_symbol(parameter, parameters)
    when Array
      # Arrays are added to the Thing's arguments list.
      arguments += parameter
    when Hash
      # Hashes are expected to be a symbol list of methods on Thing with respective arguments.
      # It's possible to override a previously defined method with new arguments.
      parameter.each{|k,v| methods[k]=v}
    when String
      # Typically a signal: Thing#signal_connect(signal){|*emits| block.call(*emits)}
      signals.push(parameter)
    else
      # Assume it's a container
      container = parameter
    end
  end
  signals.uniq!
  return container, arguments, methods, signals
end

.do_symbol(parameter, parameters) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/such/thing.rb', line 18

def self.do_symbol(parameter, parameters)
  if PARAMETERS.has_key?(parameter)
    p = PARAMETERS[parameter]
    (parameter[-1]=='!')? parameters.unshift(*p) : parameters.unshift(p)
  else
    if parameter[-1]=='!'
      p = parameter[0..-2]
      parameters.unshift(p.downcase.to_sym)
      parameters.unshift(p.upcase.to_sym)
    else
      warn "Warning: Such::Thing::PARAMETERS[#{parameter}] not defined"
    end
  end
end

.into(obj, container = nil, mthd = nil, *args) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/such/thing.rb', line 64

def self.into(obj, container=nil, mthd=nil, *args)
  if container
    mthd=Thing.which_method(container) unless mthd
    unless mthd.class==Symbol and container.respond_to?(mthd)
      raise "Need container & method. Got #{container.class}##{mthd}(#{obj.class}...)"
    end
    Thing.trace_method(container, mthd, [obj.class,*args]) if $VERBOSE
    container.method(mthd).call(obj, *args)
  else
    warn "Warning: Container for #{self.class} not given."
  end
end

.trace_method(obj, mthd, args) ⇒ Object



10
11
12
# File 'lib/such/thing.rb', line 10

def self.trace_method(obj, mthd, args)
  $stderr.puts "#{obj.class}##{mthd}(#{[*args].join(',')})"
end

.trace_signal(obj, signal) ⇒ Object



14
15
16
# File 'lib/such/thing.rb', line 14

def self.trace_signal(obj, signal)
  $stderr.puts "#{obj.class} links #{signal}"
end

.which_method(container, methods = INTOS) ⇒ Object



59
60
61
62
# File 'lib/such/thing.rb', line 59

def self.which_method(container, methods=INTOS)
  methods.each{|mthd| return mthd if container.respond_to?(mthd)}
  raise "Don't know how to put into #{container.class}."
end

Instance Method Details

#initialize(*parameters, &block) ⇒ Object



127
128
129
130
131
132
# File 'lib/such/thing.rb', line 127

def initialize(*parameters, &block)
  container, arguments, methods, signals = Thing.do_parameters(parameters)
  super(*arguments)
  Thing.do_methods(self, methods, container)
  Thing.do_links(self, signals, block)
end