I am working on a Clojure macro to help build GridBagLayout-based JPanels. I can get Java classes in a defaults map inside the macro to namespace-qualify, but not those passed in as arguments. What magic combination of backquotes, quotes, tildas, or something else do I need?
(import [java.awt GridBagConstraints GridBagLayout Insets]
[javax.swing JButton JPanel])
(defmacro make-constraints [gridx gridy & constraints]
(let [defaults
{:gridwidth 1 :gridheight 1 :weightx 0 :weighty 0
:anchor 'GridBagConstraints/WEST :fill 'GridBagConstraints/NONE
:insets `(Insets. 5 5 5 5) :ipadx 0 :ipady 0}
values
(assoc (merge defaults (apply hash-map constraints))
:gridx gridx :gridy gridy)]
`(GridBagConstraints. ~@(map (fn [value]
(if
(or
(number? value)
(string? value)
(char? value)
(true? value)
(false? value)
(nil? value))
value
`~value))
(map values
[:gridx :gridy :gridwidth :gridheight
:weightx :weighty :anchor :fill
:insets :ipadx :ipady])))))
When I use the Insets defined in the defaults map, it gets qualified (not “symbol-captured”) as (java.awt.Insets ...):
user=> (macroexpand-1 '(make-constraints 0 0 :weightx 1))
(java.awt.GridBagConstraints.
0 0 1 1 1 0
GridBagConstraints/WEST GridBagConstraints/NONE
(java.awt.Insets. 5 5 5 5) 0 0)
but when I pass it as an argument, it does not:
user=> (macroexpand-1 '(make-constraints 1 1 :insets (Insets. 2 2 2 2)))
(java.awt.GridBagConstraints.
1 1 1 1 0 0
GridBagConstraints/WEST GridBagConstraints/NONE
(Insets. 2 2 2 2) 0 0)
I’m not just trying to be a stickler. I am getting compiler errors that it cannot find a proper GridBagConstraints constructor.
Here is my solution. I am using it in a Swing application that I am writing. It has already saved me many lines of code writing (for two different panels) and will be as fast as hand-written code.
Thanks to amalloy, user100464, and kotarak for the help.