From: Greg Menke
Subject: Lispworks, managing CAPI interface complexity
Date: 
Message-ID: <m3znjwtqkr.fsf@europa.pienet>
I'm building a CAPI based application that graphs performance data
from an arbitrary number of Solaris machines.  Its divided into 2
parts, one handles accumulating data from the selected machines &
graphing it, the other has all the widgets necessary to maintain the
list of machines and queries.  All this is causing the interface to
contain a lot of active controls, and I'm somewhat concerned that its
going to be difficult to manage it.

So, I was wondering if there is an obvious way to divide the problem.
I want to keep the controls active on the same interface, so I don't
think I want to split the system up into multiple interfaces, which I
think means I would like to partition the interface defclass into
functional groups so I can more easily mess around with the layout.

Since :panes and :layout each accept a list of items, I was wondering
if there might be any not-too-painful approach for defining each
functional set of controls as a separate macro, which are then
consolidated at compile time in define-interface.

Thanks for any hints,

Greg Menke

From: Paul Tarvydas
Subject: Re: Lispworks, managing CAPI interface complexity
Date: 
Message-ID: <sAMMa.45624$2ay.26495@news01.bloor.is.net.cable.rogers.com>
Maybe a stupid question: are you laying this out manually or are you using
the interface builder tool (works>>tools>>interface builder)?  The
interface builder gives you a hierarchical tree (i.e. manageable)
representation of the interface, allows you to cut/copy/paste, etc, which
sounds like what you want to do.  The tool outputs a text-editable
"define-interface".

pt
From: Greg Menke
Subject: Re: Lispworks, managing CAPI interface complexity
Date: 
Message-ID: <m3isqktj03.fsf@europa.pienet>
Paul Tarvydas <········@attcanada.ca> writes:

> Maybe a stupid question: are you laying this out manually or are you using
> the interface builder tool (works>>tools>>interface builder)?  The
> interface builder gives you a hierarchical tree (i.e. manageable)
> representation of the interface, allows you to cut/copy/paste, etc, which
> sounds like what you want to do.  The tool outputs a text-editable
> "define-interface".

A mixture of manual and Interface Builder.  The Interface Builder is a
little buggy under Linux- 4.3 is supposed to fix it.  It works OK, but
won't save the definition properly so you end up accumulating lots of
definitions of the interface.  So, I use it to experiment with layouts
until I get something I want, then copy the define-interface code over
to my program.  In this case, the interface is an amalgam of several
different layouts.  Even if I did design the whole thing in the
Interface Builder, its still a pretty complex interface, and the
sourcecode definition doesn't facilitate a modular approach- or at
least its not obvious to me how to make it so.

Gregm
From: Paul Tarvydas
Subject: Re: Lispworks, managing CAPI interface complexity
Date: 
Message-ID: <BEWMa.52542$2ay.12988@news01.bloor.is.net.cable.rogers.com>
Greg Menke wrote:

> A mixture of manual and Interface Builder.  The Interface Builder is a
> little buggy under Linux- 4.3 is supposed to fix it.  It works OK, but
> won't save the definition properly so you end up accumulating lots of
> definitions of the interface.  So, I use it to experiment with layouts

I've always assumed that this was a "feature" (revision control / ability to
keep multiple interfaces in a single file).  It works the same way under
Windows.

...
> different layouts.  Even if I did design the whole thing in the
> Interface Builder, its still a pretty complex interface, and the
> sourcecode definition doesn't facilitate a modular approach- or at
> least its not obvious to me how to make it so.

Maybe we have different thresholds for what we consider "modular enough", or
maybe we're doing things differently.  Here's what I do (maybe it will
help?  Hope it doesn't bore you by seeming too obvious):

I think of an interface as a single "control panel" (hardware analogy) with
a bundle of wires sticking out of it going to the actual control software. 

I imagine that wires carry info in one direction only (this is an important
organizational concept, believe it or not).  E.g. buttons on the interface
send data "out" of the interface to controller code.  Stuff like drawing
surfaces have data coming "into" them from the controller.  CAPI
output-panes have outputs (input-models) and inputs (drawing ops) that
should be treated as if they are "totally separate".

This might be where we differ in outlook:  Using my perspective, the
interface (control panel) is a single complete unit that does not need to
be modularized, but, the interface contains *no* code.  The controller code
is modularized (using standard CL techniques (separate files, classes,
whatever)), but contains no interfaces.

I keep each tool-generated interface in a separate .lisp file, all other
code goes into other files (I tend to put default-input-model stuff and
supporting code in a separate file, too).

"Outputs" from the control panel simply invoke callback functions, e.g.
button-xyz-pushed.

"Inputs" to the control panel are handled by :accessor declarations (I tend
to add these to the define-interface manually, but probably could use the
tool to do it).

So, in the interface-controlling code, I can access any interesting chunk of
the interface with a simple sexp, e.g. "(chunk intf)", e.g.

   ...
   (status-line-cursor
    capi:title-pane
    :visible-max-width *status-line-element-width*
    :visible-min-width *status-line-element-width*
    :width *status-line-element-width*
    :accessor status-line-cursor)
   ...

(in this case, I would access this status line with "(status-line-cursor
intf)")

When functionality overlaps, e.g. a menu / a toolbar / a button perform the
same function, I liberally use two levels of function calls.  The interface
calls separate functions for each action - e.g. "menu-select",
"toolbar-select" and "button-select" - and each of those functions massages
the args appropriately then calls the common code, e.g. "script-select".

Using this sort of stuff, I've currently got an interface .lisp file that's
1300 lines long and I find it entirely manageable.

pt
From: Greg Menke
Subject: Re: Lispworks, managing CAPI interface complexity
Date: 
Message-ID: <m365mjscun.fsf@europa.pienet>
Paul Tarvydas <········@attcanada.ca> writes:

> Greg Menke wrote:
> 
> > A mixture of manual and Interface Builder.  The Interface Builder is a
> > little buggy under Linux- 4.3 is supposed to fix it.  It works OK, but
> > won't save the definition properly so you end up accumulating lots of
> > definitions of the interface.  So, I use it to experiment with layouts
> 
> I've always assumed that this was a "feature" (revision control / ability to
> keep multiple interfaces in a single file).  It works the same way under
> Windows.

Interesting... Thinking it was a bug, I reported it to Xanalys some
time ago and they responded it would be fixed in 4.3.  IIRC, the docs
suggest only one definition of each interface is saved, and that
multiple interfaces may be defined in a given .lisp file.

> 
> ...
> > different layouts.  Even if I did design the whole thing in the
> > Interface Builder, its still a pretty complex interface, and the
> > sourcecode definition doesn't facilitate a modular approach- or at
> > least its not obvious to me how to make it so.
> 
> Maybe we have different thresholds for what we consider "modular enough", or
> maybe we're doing things differently.  Here's what I do (maybe it will
> help?  Hope it doesn't bore you by seeming too obvious):
> 

<..snip..>

> 
> Using this sort of stuff, I've currently got an interface .lisp file that's
> 1300 lines long and I find it entirely manageable.

No, its very helpful!  I think I understand what you're getting at.
If so, I think my concern is one more hangover from the Visual C++/MFC
way of doing things.  There a complex form makes for an extremely
complicated class, tending inexorably towards unmaintainability.

Just from resorting the layout and pane sections of the
define-interface, I've usefully re-arranged the control defintions,
and now I am free to organize the callbacks (and :accessor calls- no
more slot-value for me!) in some correspondly helpful manner- but
outside the interface definition.  Thus, all the control fiddling and
state can be structured independently, leaving the interface
definition to bind it all together.  Cool.  Man do I ever LOVE how CL
does classes- so non-painful!

Gregm