Skip to content

Instantly share code, notes, and snippets.

@adamsanderson
Created April 22, 2009 05:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamsanderson/99612 to your computer and use it in GitHub Desktop.
Save adamsanderson/99612 to your computer and use it in GitHub Desktop.
#! /usr/bin/env jruby
include Java
import java.lang.System
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.JTextField
import javax.swing.event.DocumentListener
import java.awt.GridLayout
class Calculator < JFrame
def initialize(name='Calculator', &block)
super(name)
self.layout = GridLayout.new(0, 2)
@fields = {}
configue(&block)
pack
show
end
def configue(&block)
data = CalculatorDSL.new(&block)
data.inputs.each do |input|
add JLabel.new(input.to_s)
add @fields[input] = JTextField.new
end
data.outputs.each do |output, spec|
add JLabel.new(output.to_s)
add field = JTextField.new
field.enabled = false
@fields[output] = field # can cause loops
calculation = spec.pop
compute = lambda{
values = spec.map{|key| @fields[key].get_text.to_i }
result = calculation.call(*values)
field.set_text(result.to_s)
}
spec.each{|key| @fields[key].get_document.add_document_listener(FieldListener.new(compute))}
end
end
end
class CalculatorDSL
attr_reader :inputs, :outputs
def initialize(&block)
@inputs = []
@outputs = {}
instance_eval &block
end
def input *names
names.each{|name| @inputs << name }
end
def output specs
specs.each{|name, spec| @outputs[name] = spec}
end
end
class FieldListener
include DocumentListener
def initialize(block)
@block = block
end
def insertUpdate(e); update; end
def removeUpdate(e); update; end
def changedUpdate(e); update; end
def update; @block.call; end
end
# This is the equivelant DSL
Calculator.new do
input :width
input :height
output :area => [:width, :height, lambda{|w,h| w * h}]
output :price => [:area, lambda{|area| "$#{area * 25}" }]
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment