Bay Area Scala Enthusiasts, November 2011
Consider a simple Swing application with a couple of combo boxes and some labels.

Consider a simple Swing application with a couple of combo boxes and some labels.

Changing the selection of the combo boxes updates the text in the labels.



private String label3Prefix = ""; private String label3Suffix = ""; private String label4Prefix = ""; private String label4Suffix = "";
private String updateLabel3Prefix(String value) {
label3Prefix = value;
return label3Text();
}
private String updateLabel3Suffix(String value) {
label3Suffix = value;
return label3Text();
}
private String updateLabel4Prefix(String value) {
label4Prefix = value;
return label4Text();
}
private String updateLabel4Suffix(String value) {
label4Suffix = value;
return label4Text();
}
private String label3Text() {
return label3Prefix + " is " + label3Suffix;
}
private String label4Text() {
return label4Prefix + " ain't " + label4Suffix;
}
private void combo1Updated() {
String value = combo1.getSelectedItem().toString();
label1.setText(value);
label3.setText(updateLabel3Prefix(value));
label4.setText(updateLabel4Prefix(value));
}
private void combo2Updated() {
String value = combo2.getSelectedItem().toString();
label2.setText(value);
label3.setText(updateLabel3Suffix(value));
label4.setText(updateLabel4Suffix(value));
}
combo1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
combo1Updated();
}
});
combo2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
combo2Updated();
}
});
scala> val combo1 = new JComboBox(Array[AnyRef]("Fred", "Sam", "Joe"))
combo1: javax.swing.JComboBox = ...
scala> println("combo1 is: " + signal(combo1))
combo1 is: Fred
scala> combo1.setSelectedIndex(0)
combo1 is: Fred
scala> combo1.setSelectedIndex(1)
combo1 is: Sam
scala> combo1.setSelectedIndex(2)
combo1 is: Joe
fruit { implicit s: Signals =>
label1.setText(signal(combo1))
label2.setText(signal(combo2))
label3.setText(signal(combo1) + " is " + signal(combo2))
label4.setText(signal(combo1) + " ain't " + signal(combo2))
}
class Signal(selectable: Selectable) {
private var c: Option[String => Unit] = None
selectable.addActionListener(new ActionListener() {
def actionPerformed(e: ActionEvent) {
c.foreach(_(selectable.getSelectedItem.toString))
}
})
def apply(k: (String => Unit)) {
c = Option(k)
k(selectable.getSelectedItem.toString)
}
}
trait Fruit {
type Selectable = {
def getSelectedItem(): AnyRef
def addActionListener(a: ActionListener): Unit
}
val signals = collection.mutable.HashMap[Int, Signal]()
def signal(selectable: Selectable, x: Int): String @suspendable = shift { k: (String => Unit) =>
if (!signals.contains(x)) signals(x) = new Signal(selectable)
signals(x)(k)
}
def fruit(f: => Unit @suspendable) = reset(f)
}
A couple of approaches, each with issues
fruit { implicit s: Signals =>
label1.setText(signal(combo1))
label2.setText(signal(combo2))
label3.setText(signal(combo1) + " is " + signal(combo2))
label4.setText(signal(combo1) + " ain't " + signal(combo2))
}