Szymon Witamborski edited this page May 14, 2011 · 7 revisions

From programmer's (user's) point of view GUI FTW! is divided to two parts: compile-time and runtime. At compile time you create functions that will create your GUI at runtime. There's no windows, widgets or any other state initialized at that point. You create two type of functions: GUI creators and style sheets.

GUI structures

GUI structure (don't confuse it with GUI state which is something different) is your tree of widgets, so by it you define where your widgets are put. For example if you want a window with two panels in it each one having one button and one text field you would write:

  [panel [text-field]
  [panel [text-field]

(Where window, panel, etc. are yours frameworks classes for windows and panels.)

Styles and Style Sheets

On contrary, style sheets tell how element looks and how it behaves. So, in style sheet you'll define all object properties and event handlers. Style sheets are composed of individual styles. A style is a list of pairs: key and value. Keys corresponds 1:1 to JavaBean properties (all those setXxx(v) methods). So, if you have setText(String text) method in some class, you'd write :text "Some text" in style.

Each object in GUI structure have its private style which comes right after it's class, so earlier example becomes:

[window [:title "My Window"]
  [panel [] [text-field]
  [panel [] [text-field]

Notice that if some widget have children you have to pass empty style explicitly.

There are few special properties and those begin with asterisk (*). Two are defined by GUI FTW itself:

  • *id -- identificator of an object. Label (preferably of keyword type) that belongs to that object and no other.
  • *groups -- list of groups identificators that this object belongs to.

There are others like *cons or *lay that are implemented in frontends and will be discused later.

Once object has an id or belongs to some group, it can be styled by style sheets. Style sheets are list of styles with additional information: to which identificators they're revelant. To accomodate that style sheet definition looks like this:

(stylesheet [:window :buttons] [:color "red"]
            [:panels :menu] [:background-color "blue"])

This style sheet will have [:color "red"] style for :window and :buttons and [:background-color "blue"] style for :panels and :menu. Meaning of identificators (whether it's individual id or group) in style sheet is not important. Groups and individual ids can be mixed freely.


Events are like other properties but instead to setters they correspond to event listeners. You are not constrained to standard event listeners. You can create and use any custom listeners that follows that pattern.

Event Specification

Name of the event "property" maps 1:1 to *Listener class and method to implement. It's composed of this two as follows: first name of the class (without "Listener" part) a + sign and name of the method. All names can be in lispy-notation instead of CamelCase and they will be translated to canonic Java form (CamelCase everywhere).

Example: You want to hook into "mouse clicked" event in Swing. Corresponding method lives in java.awt.event.MouseListener. You import this class and add property :mouse+mouse-clicked to the object. Notice that you have "mouse" two times. It's so common that GUI FTW! have shortcut for this. You can write :mouse++clicked instead.

Event Handler Implementation

Value for event "property" is a function that takes two arguments: GUI state and event object.

Full mouse clicked event will look like this:

:mouse++clicked (fn [gui event] ...)


GUI FTW! is as abstract as possible at it's core. Which means that no functionality specific to Swing in SWT is in core. These functionalities are squized to minimum and they reside in so-called frontends. You usually won't invoke guiftw.tree/parse-gui which is core GUI structure parser. You'd rather invoke one of the frontends which are very thin wrappers around parse-gui macro.


Swing frontend resides in guiftw.swing namespace and one macro that you should be interested in is swing. It feeds parse-gui macro with Swing-specific functionality.


Analogous to Swing, for SWT there's guiftw.swt namespace and swt macro. Remember that GUI FTW! doesn't come with SWT jars. You have to add them manually to your project.

Generating GUI Creator

parse-gui, (so also swt and swing) macro will generate function to create your GUI at runtime. Both frontends take one argument: GUI structure and return function that will create that GUI structure for you.

With swing you declare your GUI creator fn like this:

(def window
  (swing [JFrame [:title "This is a window!"
                  :visible true]
           [JButton [:text "There's a button here"]]]))

After that window is a function that takes variable number of arguments, all are optional (you can ommit them at will, no need for nilling them):

  • GUI state (see next section),
  • parent element for elements in this tree,
  • any number of stylesheets.

If you don't pass GUI state, it'll be created for you. If you pass parent explicitly element at root of GUI structure will be added to parent as a child. Then you can pass any number of stylesheets which gives you flexibility to mix them at runtime.

Runtime State (GUI State)

GUI creator will instantiate all objects defined in GUI structure and return GUI state. GUI state is a map wrapped in an atom. This map contains those predefined keys:

  • :ids -- a map with objects indentified by their :*id property,
  • :groups -- a map with lists of objects grouped by :*group property,
  • :root -- top-level object in GUI tree (usually the window).

So, if you marked some object with :my-button id, you can refer to it like this:

(-> @gui-state :ids :my-button)

You can put any number of custom keys in GUI state. They will be preserved. Say you have a window GUI creator fn and you want to put some custom variables in state. Initializing such a window will look like this:

(window (atom {:my-agent (agent 123)
               :my-atom (atom 456)}))

Notice that GUI state is always passed to event handlers. So in simple programs you probably won't care about returned value. It's also important to stress the fact that you can decide when different parts of your GUI share state. It's a matter of passing same GUI state to creators. When mixing this with passing parent explicitly they can be part of same window but have different GUI states.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.