Accessing Java code in Vodka is easy: Any Java class that is available
on the Vodka runtime's classpath can be imported with an
import native declaration.
Moreover and thanks to the partial-application operator ->, we can
write code
that, on the first glance, looks almost like regular Java code:
# # Create a swing frame with a button inside that will print a message # when clicked # import library.util; import native javax.swing.JButton; import native javax.swing.JLabel; import native javax.swing.JFrame; import native java.awt.FlowLayout; import library.swingUtil; button = JButton("Button"); button->addActionListener(ActionListener(actionPerformed: fn e: Console.print("Click!"))); frame = JFrame("MyFrame"); frame->getContentPane()->setLayout(FlowLayout()); frame->getContentPane()->add(JLabel("Click here:")); frame->getContentPane()->add(button); frame->pack(); frame->show(); stop();
In addition to calling Java methods ourselves, we can create objects
that implement particular Java interfaces, as is the case with
the above action listener. In fact, we can turn any record with
appropriately named function-value fields into an implementation of a Java
interface by passing the record to the interface
constructor (in this case ActionListener).
Although feeling at home with the API may be a nice thing, it would not be much of an improvement, if writing Swing code "the old way" was the sole means of GUI construction in our language. To illustrate our more declarative approach to GUI development (found e.g. in OpenLaszlo), which concentrates on the data dependencies rather than on state-changes, we are going to construct the following window:

Dragging one of sliders changes the width or height of the green rectangle, whose area is displayed as a numberic value inside. If the green rectangle grows larger than 20,000 square pixels, a text notice is shown. In the lower half of the window, the selection from the popup menu determines from which of the text fields the content of the label at the bottom is drawn. Editing that text field also changes the text below interactively.

In implementing this functionality, we make use of reference cells, another kind of advanced mutable variables we can implement in the language itself. Reference cells allow us to define data dependencies between variables and have state changes be tracked automatically.
In order to achieve this, the set operation on reference cells no longer
takes a value that defines the contents of the variable, but a function that is
executed to (re-)compute the actual value. Within this function, other variables may be
referenced by calling their subscribe operation.
# # Upper region of the window # sliderX = VSlider(0, 200); sliderY = VSlider(0, 200); areaValue = VCell ( fn t: sliderX.value.subscribe(t) * sliderY.value.subscribe(t) ); areaLabel = VLabel("-"); areaLabel.value.set ( fn t: toString(areaValue.value.subscribe(t)) ); areaPanel = VFlowPanel[areaLabel]; areaPanel.comp->setBackground(Color(0, 255, 0)); areaPanel.size.set ( fn t: (sliderX.value.subscribe(t), sliderY.value.subscribe(t)) ); notice = VLabel("wow, this is HUGE ... !!"); notice.visibility.set ( fn t: areaValue.value.subscribe(t) > 20000 );
In constructing the lower half of the window, we make use of the fact that reference cells, too, can be
treated as first class values. The value of the selection cell is one of the text fields,
and the value of the selectionText
label is defined as the value of that text field, which is the value of the selection cell.
# # Lower half components # textA = VTextField("A quick brown fox"); textB = VTextField("jumped over the lazy dogs"); textA.size.set(fn t: (200, 22)); textB.size.set(fn t: (200, 22)); menu = VComboBox(["Text A","Text B"]->toArray()); selectionText = VLabel("-"); selectionText.size.set(fn t: (200, 22)); selection = VCell ( fn t: (if menu.value.subscribe(t)->equals("Text A") then textA else textB) ); selectionText.value.set ( fn t: (selection.value.subscribe(t)).value.subscribe(t) );
Assembling components into panels is a little easier, too, with the help of generator literals:
# # JFrame assembly # sliders = VFlowPanel [ VLabel("Width:"), sliderX, VLabel("Height:"), sliderY, areaPanel, notice ]; sliders.size.set(fn t: (220, 300)); texts = VFlowPanel [ VLabel("Text A:"), textA, VLabel("Text B:"), textB, VLabel("Selection:"), menu, selectionText ]; texts.size.set(fn t: (220, 250)); base = VFlowPanel [sliders, texts]; frame = JFrame("MyFrame"); frame->setContentPane(base.comp); frame->setSize(220, 550); frame->show(); stop();
Putting these code snippets together yields exactly the required functionality, without writing a single callback or update function ourselves. Moreover, the reference cell implementation is clever enough to recompute just those cells that have actually changed, and to promote those changes in a topologically sorted way.