Macros and guiserver?

Started by oofoe, July 04, 2016, 05:16:16 AM

Previous topic - Next topic

oofoe

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!
Testing can show the presence of bugs, but not their absence.

oofoe

#1
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!
Testing can show the presence of bugs, but not their absence.

rickyboy

#2
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.)
(λx. x x) (λx. x x)

rickyboy

#3
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
(λx. x x) (λx. x x)

oofoe

#4
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.
Testing can show the presence of bugs, but not their absence.