API for seesaw.bind
-
by Dave Ray
Full namespace name:
seesaw.bind
Overview
Functions for binding the value of one thing to another, for example
synchronizing an atom with changes to a slider.
Public Variables and Functions
b-do
macro
Usage: (b-do bindings & body)
Macro helper for (seesaw.bind/b-do*). Takes a single-argument fn-style
binding vector and a body. When a new value is received it is passed
to the binding and the body is executes. The result is discarded.
See:
(seesaw.bind/b-do*)
b-do*
function
Usage: (b-do* f & args)
Creates a bindable that takes an incoming value v, executes
(f v args) and does nothing further. That is, it's the end of the binding
chain.
See:
(seesaw.bind/bind)
(seesaw.bind/b-do)
b-send
function
Usage: (b-send agent f & args)
Creates a bindable that (send)s to an agent using the given function each
time its input changes. That is, each time a new value comes in,
(apply send agent f new-value args) is called.
This bindable's value (the current value of the atom) is subscribable.
Example:
; Accumulate list of selections in a vector
(bind (selection my-list) (b-send my-agent conj))
b-send-off
function
Usage: (b-send-off agent f & args)
Creates a bindable that (send-off)s to an agent using the given function each
time its input changes. That is, each time a new value comes in,
(apply send agent f new-value args) is called.
This bindable's value (the current value of the atom) is subscribable.
Example:
; Accumulate list of selections in a vector
(bind (selection my-list) (b-send-off my-agent conj))
b-swap!
function
Usage: (b-swap! atom f & args)
Creates a bindable that swaps! an atom's value using the given function each
time its input changes. That is, each time a new value comes in,
(apply swap! atom f new-value args) is called.
This bindable's value (the current value of the atom) is subscribable.
Example:
; Accumulate list of selections in a vector
(bind (selection my-list) (b-swap! my-atom conj))
bind
function
Usage: (bind first-source target & more)
Chains together two or more bindables into a listening chain.
When the value of source changes it is passed along and updates
the value of target and so on.
Note that the return value of this function is itself a composite
bindable so it can be subscribed to, or nested in other chains.
The return value, like (seesaw.bind/subscribe) and (seesaw.event/listen)
can also be invoked as a no-arg function to back out all the subscriptions
made by bind.
Examples:
; Bind the text of a text box to an atom. As the user types in
; t, the value of a is updated.
(let [t (text)
a (atom nil)]
(bind (.getDocument t) a))
; Bind a the value of a slider to an atom, with a transform
; that forces the value to [0, 1]
(let [s (slider :min 0 :max 1)
a (atom 0.0)]
(bind s (transform / 100.0) a))
; Bind the value of an atom to a label
(let [a (atom "hi")
lbl (label)]
(bind a (transform #(.toUpperCase %)) (property lbl :text))))
Notes:
Creating a binding does *not* automatically synchronize the values.
Circular bindings will usually work.
composite
function
Usage: (composite start end)
Create a composite bindable from the start and end of a binding chain
filter
function
Usage: (filter pred)
Executes a predicate on incoming value. If the predicate returns a truthy
value, the incoming value is passed on to the next bindable in the chain.
Otherwise, nothing is notified.
Examples:
; Block out of range values
(let [input (text)
output (slider :min 0 :max 100)]
(bind
input
(filter #(< 0 % 100))
output))
Notes:
This works a lot like (clojure.core/filter)
See:
(seesaw.bind/some)
(clojure.core/filter)
funnel
function
Usage: (funnel & bindables)
Create a binding chain with several input chains. Provides a
vector of input values further along the chain.
Example: Only enable a button if there is some text in both fields.
(let [t1 (text)
t2 (text)
b (button)]
(bind
(funnel
(property t1 :text)
(property t2 :text))
(transform #(every? seq %))
(property b :enabled?)))
notify
function
Usage: (notify this v)
Pass a new value to this bindable. Causes all subscribed handlers
to be called with the value.
notify-later
function
Usage: (notify-later)
Creates a bindable that notifies its subscribers (next in chain) on the
swing thread using (seesaw.invoke/invoke-later). You should use this to
ensure that things happen on the right thread, e.g. (seesaw.bind/property)
and (seesaw.bind/selection).
See:
(seesaw.invoke/invoke-later)
notify-now
function
Usage: (notify-now)
Creates a bindable that notifies its subscribers (next in chain) on the
swing thread using (seesaw.invoke/invoke-now). You should use this to
ensure that things happen on the right thread, e.g. (seesaw.bind/property)
and (seesaw.bind/selection).
Note that sincel invoke-now is used, you're in danger of deadlocks. Be careful.
See:
(seesaw.invoke/invoke-soon)
notify-soon
function
Usage: (notify-soon)
Creates a bindable that notifies its subscribers (next in chain) on the
swing thread using (seesaw.invoke/invoke-soon). You should use this to
ensure that things happen on the right thread, e.g. (seesaw.bind/property)
and (seesaw.bind/selection).
See:
(seesaw.invoke/invoke-soon)
property
function
Usage: (property target property-name)
Returns a bindable (suitable to pass to seesaw.bind/bind) that
connects to a property of a widget, e.g. :foreground, :enabled?,
etc.
Examples:
; Map the text in a text box to the foreground color of a label
; Pass the text through Seesaw's color function first to get
; a color value.
(let [t (text :text "white")
lbl (label :text "Color is shown here" :opaque? true)]
(bind (.getDocument t)
(transform #(try (color %) (catch Exception (color 0 0 0))))
(property lbl :background)))
See:
(seesaw.bind/bind)
selection
function
Usage: (selection widget options)
(selection widget)
Converts the selection of a widget into a bindable. Applies to listbox,
table, tree, combobox, checkbox, etc, etc. In short, anything to which
(seesaw.core/selection) applies.
options corresponds to the option map passed to (seesaw.core/selection)
and (seesaw.core/selection)
Examples:
; Bind checkbox state to enabled state of a widget
(let [cb (checkbox :text "Enable")
t (text)]
(bind (selection cb) (property t :enabled?)))
See:
(seesaw.bind/bind)
(seesaw.core/selection)
(seesaw.core/selection!)
some
function
Usage: (some pred)
Executes a predicate on incoming value. If the predicate returns a truthy
value, that value is passed on to the next bindable in the chain. Otherwise,
nothing is notified.
Examples:
; Try to convert a text string to a number. Do nothing if the conversion
; Fails
(let [input (text)
output (slider :min 0 :max 100)]
(bind input (some #(try (Integer/parseInt %) (catch Exception nil))) output))
Notes:
This works a lot like (clojure.core/some)
See:
(seesaw.bind/filter)
(clojure.core/some)
subscribe
function
Usage: (subscribe this handler)
Subscribes a handler to changes in this bindable.
handler is a single argument function that takes the
new value of the bindable.
Must return a no-arg function that unsubscribes the handler
from future changes.
tee
function
Usage: (tee & bindables)
Create a tee junction in a bindable chain.
Examples:
; Take the content of a text box and show it as upper and lower
; case in two labels
(let [t (text)
upper (label)
lower (label)]
(bind (property t :text)
(tee (bind (transform #(.toUpperCase %)) (property upper :text))
(bind (transform #(.toLowerCase %)) (property lower :text)))))
See:
(seesaw.bind/bind)
function
Usage: (transform f & args)
Creates a bindable that takes an incoming value v, applies
(f v args), and passes the result on. f should be side-effect
free.
See:
(seesaw.bind/bind)
value
function
Usage: (value widget)
Converts the value of a widget into a bindable. Applies to listbox,
table, tree, combobox, checkbox, etc, etc. In short, anything to which
(seesaw.core/value) applies. This is a "receive-only" bindable since
there is no good way to detect changes in the values of composites.
Examples:
; Map the value of an atom (a map) into the value of a panel.
(let [a (atom nil)
p (border-panel :north (checkbox :id :cb :text "Enable")
:south (text :id :tb)]
(bind a (value p)))
; ... now setting a to {:cb true :tb "Hi"} will check the checkbox
; and change the text field to "Hi"
See:
(seesaw.bind/bind)
(seesaw.core/value!)