Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 01 Dec 1996 06:00:32 -0800
From:      "Jordan K. Hubbard" <jkh@time.cdrom.com>
To:        Michael Smith <msmith@atrad.adelaide.edu.au>
Cc:        hackers@freebsd.org
Subject:   Re: text, menu/dialog/windowing, library, ideas? 
Message-ID:  <15861.849448832@time.cdrom.com>
In-Reply-To: Your message of "Sun, 01 Dec 1996 23:15:01 %2B1030." <199612011245.XAA29703@genesis.atrad.adelaide.edu.au> 

next in thread | previous in thread | raw e-mail | index | archive | help
> Argh!  Aren't there _any_ decent, simple, text windowing libraries out
> there?

It sure wouldn't seem like it, no... :-(

> I've looked at :
>  - libdialog (of sysinstall fame)
Bleah.

>  - 'SAA' (from an obscure german FTP site)
Bleah.

>  - D-Flat
Bleah.

> Each of these falls short of expectations in one or more important
> fashions.  libdialog is zorklike, and Jordan gives off bad emanations
> about it.  'SAA' has a hideously unfriendly interface metaphor, and
> D-Flat is a DOS monster written with no regard for structure,
> documentation or portability.

Right.  And pretty much every other one you'll find, like cdk or the
stuff in ncurses, is either the wrong approach entirely or extremely
difficult to bring into another encapsulation paradigm like TCL.  Most
C library designers think that it's OK to have 14 different structure
types being passed around, which makes it a real nightmare for the
encapsulator.

> Has anyone written or used a CUA-style package that offers the basic
> stuff; a menubar, popup dialogs, form entry etc.?

If so, I sure haven't found it yet, and I've looked.

Ultimately, I think what we're going to have to do is design it from
scratch.  It might even be kind of fun, but I'm still wrestling with
some of the design concepts and have come up with multiple approaches
to the problem, all of which have various pros and cons going for
them.

One approach would be to take a very high level slice at the problem
and write a series of very generic "presentation objects" (or
"interactors" or whatever the hell you want to call them).  They would
basically provide the API for creating, passing data to and asking for
the status of various objects like "list", "dialog" and "form".  You'd
see each object in a very high level way, with callback lists and
set/get functions handling all interaction between your frontend and
backend code.  If you also add a naming scheme so that an object can
be identified in the hierarchy and queried generically for status or
asked to select itself, you can probably even decouple of concept of
"forms" or "lists" from most of the code - all you really care about
is that you've got some data to display and that the front end is
doing an adequate job, after all, and whether it's a popup menu or a
list becomes fairly arbitrary and should be changable without having
to change anything but the GUI layout description file.

If you then make the method for rendering an object or getting data
from the user a function pointer, you can even back-fill these
functions right before you're set to do final instantiation of the
objects and go into your "event loop", thus decoupling it from curses
or X.  E.g.:

	DObject *top, *button;
	DClass *disp_class;

	DInitialize();
	top = addDObjects("top_layout.frm");
	if (XOpenDisplay(NULL) == NULL)
	    disp_class = DOpenClass("X11");
	else
	    disp_class = DOpenClass("ncurses");
	bindDclass(top, disp_class);	/* Traverse object tree and each object
					   at its display method by looking
					   the association in disp_class by
					   object type */

	/* Do object specific bindings */
	button = DFind(top, "outerpane.buttonpanel.fred");
	DBindAction(button, jump_and_puke);

	DRealizeAllObjects(top);
	while (1) {
		if (DProcessNextEvent(top) == DEXIT)
		    break;
	}

Or something like that. :-)

All that really buys you, however, is the ability to shuffle off all
your icky curses or X specific code into a "display class" object, and
you still need to extend every one of your object classes for each new
object you add (unless that object has no meaning for that display
class, in which case I guess its presence would just be a no-op) which
is kind of a downside.

An alternative, of course, would be to go to a different level of
abstraction and have each object make more elementary "drawing
requests" of a generic drawing method class, so a button for example
could say "draw a box around me with these dimensions and then paint
this text string in the middle for my label."  The drawing class
would, again, be bound into the object hierarchy in some way right
before initial rendering time, but the objects themselves would be
more generic in that you'd only have to have one essential set of
rendering instructions for each, those instructions would just be
interpreted differently based one whichever global renderer you had
selected.  You could add new objects at will, and in only one place,
until/unless you started running into a necessity for wholly new set
of drawing primitives.

Needless to say, I rejected the latter alternative on the grounds that
the problem was becoming over-engineered and it's probably bogus to
think that you can invent a mini graphics library that's going to make
reasonable looking objects for any conceivable environment. :-)


The final alternative I contemplated was to make the generic object
hierarchy but simply have different versions of the library for curses
and X.  E.g. you'd write the entire library as a single hierarchy of
objects, complete with their rendering methods, and stick to a common
naming convention.  Then you make your main() selectively load a
different shared library based on whether it's running under X or not
and your "button" suddenly becomes a X or curses button by virtue of
the way the shared library binding works.  This would be the simplest
of the 3 scenarios but still require that you extend each version of
the library in the same ways (e.g. if I add a machine gun object for
closing windows then I've got to do it in all versions of the
library).


Doing all of this in X is simple and has lots of alternatives, up to
and including lots of nice toolkits like "Qt" or XForms.  The problem
is that making stuff look nice in ncurses is a pain in the ass, and
effective use of color and the line-drawing character set on syscons
displays even more so.  I was kind of hoping that an ncurses expert
would show himself by now, but evidently not. :-( I could do the X
side of this with my eyes closed, but not the curses stuff.  Every
time I think I have its simple-*sounding* model all figured out,
refresh() does things to the screen which leave me mystified.

					Jordan



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?15861.849448832>