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>