Hi!
I am experimenting with macros to do more "declarative" setups in guiserver. Here is a macro that I have created to make a three button setup:
(define-macro (button3 _parent _name _buttons)
(letn ((panel (sym (string (eval _parent) "-" (eval _name))))
(slots '("west" "center" "east"))
(bname nil)
(i nil))
(gs:panel panel)
(gs:set-border-layout panel)
(dotimes (i (length (eval _buttons)))
(setq bname (sym (string panel "-" ((eval _buttons) i 0))))
(println "Setting up " bname)
(gs:button bname 'gs:no-action ((eval _buttons) i 1))
(gs:add-to panel bname (slots i))
)))
I call it like this:
(button3 'DC 'East '((Next "-->") (View "<o>") (Kill "X")))
This creates a panel (DC-East) that has three buttons (DC-East-Next, DC-East-View and DC-East-Kill). They're all set up and ready to go.
However, I can't figure out how to pass in an optional event handler for each button and have the macro assemble it correctly for the gs:button call. I want to do something like this
;; The "View" button doesn't have a handler yet, should default to gs:no-action.
(button3 'DC 'East '((Next "-->" 'next-card) (View "<o>") (Kill "X" 'kill-card)))
I am just getting invalid function or macro expansion problems when I try to do this. Any suggestions?
Thanks!
OK, think I've got it. Here's the revised macro:
(define-macro (button3 _parent _name _buttons)
(letn ((panel (sym (string (eval _parent) "-" (eval _name))))
(slots '("west" "center" "east"))
(bname nil)
(i nil))
(gs:panel panel)
(gs:set-border-layout panel)
(dotimes (i (length (eval _buttons)))
(setq bname (sym (string panel "-" ((eval _buttons) i 0))))
(gs:button bname
(if (= 3 (length ((eval _buttons) i)))
((eval _buttons) i 2)
'gs:no-action)
((eval _buttons) i 1))
(gs:add-to panel bname (slots i))
))
)
The key is that the guiserver will accept strings instead of symbols, but you have to indicate the namespace (context):
(button3 'DC 'West
'((New "new..." "MAIN:card-new")
(Clone "clone...")
(Back "<--" "MAIN:card-back")))
This will set 'card-new and 'card-back as event handlers, but the clone button will use the default gs:no-action.
It would be nice to know how to do this with proper symbols in the macro, but this is working for now and the macro simplifies my GUI setup code quite a lot.
If anyone has any improvements to suggest, I'm all ears!
Hey oofoe,
Try with a function (instead of macro); see if it works too. Here:
(define (button3-fn _parent _name _buttons)
(let (panel (sym (string _parent "-" _name))
slots '("west" "center" "east"))
(gs:panel panel)
(gs:set-border-layout panel)
(dolist (b _buttons)
(let (bname (sym (string panel "-" (b 0))))
(gs:button bname
(if (= 3 (length b))
(b 2)
'gs:no-action)
(b 1))
(gs:add-to panel bname (slots $idx))))))
This is untested; so please test.
Also, I don't know anything about gs, so I can't comment on the rest. (I tried to get gs running on my obsd box but it seems to hang on gs:init call -- doesn't come back from the call.)
Quote from: "rickyboy"
This is untested; so please test.
Also, I don't know anything about gs, so I can't comment on the rest.
I unknowingly busted a rhyme. Good Lord. :D
Thanks for taking a look!
Macros are supposed to be useful for "writing the code that you would have written if you had the patience". Since guiserver uses symbols, I figured that they would be perfect for button assembly boilerplate. However, I had to cheat with sending strings to guiserver because the symbols weren't getting quoted in the correct namespace. So here I admit there's no real advantage to the macro.
It seems there's also the (macro) function, which may do more what I want. So I'll probably try it later.