On Feb 6, 4:44 pm, Keith Bennett <keithrbenn...@gmail.com> wrote: > In a substantial GUI app, it is extremely important for visual > consistency, maintainability, reliability, and extensibility for as > many components as possible to be coded once and reused (i.e. DRY).
A long time ago in a galaxy far away (okay, 1992-1994 in Cupertino) I worked on an OS project written in Dylan when it was still a lisp. Applications were built from frames (in the sense of frame languages for knowledge representation), and presented to the user by means of s- expressions that described the data to be presented, the values to be obtained from the user, and the events that were to transform the presentation. If you were to read through a full description of our UI system (both implemented, and proposed but never implemented) it would probably sort of remind you of HTML and CSS. In detail it was pretty different (we're talking about 1992 here; HTML was new and CSS not yet invented), but in conception, it was similar: you describe a UI element with a set of nestable expressions, and style and configure it with (also nestable) styles. For example, if you wanted to display a dialog box to get some values from the user, you could call the macro user-bind: (user-bind ((name <string>) (age <integer>)) (do-stuff-with-user-data name age)) user-bind expanded into code that built a dialog window, constructed appropriate widgets to retrieve a string and a integer, and provided an OK and cancel button. Click okay and the user-bind form continued, evaluating the user code in an environment in which name and age were bound to the values provided by the user; cancel and a suitable condition was signaled. user-bind and similar macros accepted hinting parameters to specify what kind of widget you wanted and how to lay them out. In the longer term the plan was to define a style language to be used like so: (bind ((*dialog-style* (style <tool-dialog> :scale :small :system-font *system-dialog- font*)) (*button-style* (style <small-button-style> :color-scheme *dialog-bright- color-scheme*))) (user-bind ((name <string>) (age <integer>)) (do-stuff-with-user-data name age))) The idea was that the macros and methods built a UI element suitable for capturing the events you needed. For each variable you wanted to bind, the declared type told the system what kind of widget to create. In cases where more than one kind of widget was appropriate, a default choice would be provided in lexical variables that you could override by rebinding them. Similarly, style and layout were described by lexical variables that could be rebound. Clojure maps would be very hand here; it would be straightforward to nest style deltas and obtain the correct style information in a given lexical contour using merge. Not all UIs are dialog-like, of course; so there were also functions and macros to create longer-lived objects. A suitable combination of input parameters and lexical bindings made the same sorts of presentation choices, and established event-handlers for the constructed elements. I can imagine implementing something like those tools for Clojure +Swing (or bare AWT, or Pivot, or SWT, or whatever). A Clojure-like implementation might make long-lived UI elements agents. You could of course bind such elements to variables, as was done in the system we built; alternatively, or additionally, you could take a cue from SK8 and Symbolics Dynamic Windows, and make it possible to obtain a valid reference to a screen object by clicking it, and then paste that reference into code. Then update the agent to use extended or modified styles and UI elements. Finally, ask the widget for a copy of the environment that specifies it. WIth such a scheme you can write UI elements as well-structured code, interact with live objects created with the code, modify them interactively by direct manipulation and by evaluating forms, and save the current state of the widgets to a (presumably versioned) file. If I were doing work like this now in Clojure, I'd be inclined to use vectors rather than macros for most of the UI element specification. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---