Re: newbie CAPI question
Paul Tarvydas writes:
>
> ...
> > What seems un-Lispy to me is the way I'm extracting values from the
> > window in do-login: pulling values by accessors works for a simple
> > window, but as I scale up to add grids of database records, this seems
> > really inelegant. I'm thinking that there must be some generally
> > accepted way of iterating across a pane, finding the values entered by
> > the user, and mapping them into CLOS slots (where the CLOS objects are
> > being persisted via CLSQL or something similar) without having to
> > specify each accessor directly. Or perhaps this isn't even the best
> > way to go about it?
> >
> > I'd appreciate any advice (or pointers to other material that I should
> > be reading) on 1) better approaches for the code below, and 2)
> > building CAPI applications with GUI/CLOS mappings.
> ...
>
>
> d) Remember that you can sub-class capi doo-dads. You can add your
> own getter/setter/update-view methods if this makes sense in your
> design. Remember that CLOS oo works differently from most other
> kinds of oo - you can add methods specialized on combinations of
> method parameter types, so sub-classing isn't always necessary, or,
> sub-classing can help tune the control-flow through a maze of
> widgets. Capi callbacks need not be functions, they can be methods,
> too.
>
I think this is an important point (amongst the others). I came from a
Visual Basic/MSVC perspective and it took me a while to "get" the
subclassing aspects of CAPI (the more practice you get at Common Lisp
the more it becomes clear). If you view the interface as well as the
controls within it as candidates for subclassing, you can add a lot of
"local" semantics- data slots, generic functions, etc to tailor behavior
to your requirements.
That means you need not be bound to specifying only capi controls in the
interface definition- if you create a class that inherits from a CAPI
object, then you can use it in the interface just as a CAPI object of
the type you inherited from. You can take that too far by piling all
kinds of extra junk in the class which tends to bind the interface to
your app data, which in turn causes accumulation of complexity in the
interface control code- which turns into a real drag.
In practical terms, it means you can incorporate arbitrary amounts of
metadata in the controls rather than in parallel data-structures, and
use the controls themselves as parameters in generic functions. Though
the tradeoff is binding app data to the interface structure, it reduces
the variable space you have to maintain. Which is to say the ability to
do so is a tool which needs to be used appropriately.
To strengthen the division between data and interface, it might be
possible to consider the inherited capi class as the "interface form" of
a data class, then construct the interface by obtaining the right
objects from the data portion of the app rather than contructing things
at display time. I've not tried a capi app that way, I don't know
relevant, important, or correct the concept is.
Greg