
David Sankel wrote:
Questions :: 1) How does the interface look in Test_midlevel.hs? Is there any critiques in regard to using this style in CGA (Common GUI API)?
1. Widgets aren't being given names. This makes it impossible to refer to them from outside of the code. It also eliminates the possibility of implementing a useable Xt (e.g. Motif) backend. Toolkits which don't name widgets can just ignore the name.
I'm sorry, I don't understand what you mean by "impossible to refer to them from outside of the code". Can you give me an example of what you are talking about.
X resources. In an Xt-based program, every widget has a "pathname", so widget properties can be specified in external files, command-line arguments etc. Also, the Editres protocol allows one program to query/set properties of a named widget in another program.
2. Widget properties (label, position, dimension) are being embedded in the code, which is a bad idea. This point is closely tied in with point 1.
Where should this be in your opinion?
For Xt-based programs, these settings are obtained via X resources. The X resource mechanism operates by merging several files to create a resource database. Properties which are specific to the application (e.g. widget labels) normally go into a file which is provided with the application (look in /usr/lib/X11/app-defaults/ or /etc/X11/app-defaults/ for examples). Other properties (typically stylistic properties such as colours and fonts) are normally defined by the user (e.g. in ~/.Xdefaults or via the RESOURCE_MANAGER property on the root window). The mechanism by which resource files are located allows for per-language resource files, as well as for different resource files for mono/colour displays, different resource files for different hosts (a single installation may be used on multiple systems via NFS), etc. On Windows, natural language strings normally live in a string table resource. This means that the translators only need to translate a simple text file, not source code. Also, specifying literal dimensions is normally wrong. A widget's dimensions vary depending upon the label (which is language-specific) and the font (which is a user preference). Xt-based toolkits don't normally use absolute positions, but specify positions relative to an edge of another widget or the parent. This deals with the fact that you don't know the sizes of the widgets at compile time, and allows the layout to remain sensible if the parent is resized (or if the parent's initial size wasn't what you were expecting; under X, you can't *force* a top-level window to have a specific size).
3. Personally, I would prefer a generic widget creation function, rather than a different function for each type of widget. E.g. Xt has XtCreateWidget(), with the widget class being passed as an argument. A more Haskell-ish approach would be to use typeclasses, e.g.:
class Widget a where create :: String -> a -> [Property] -> IO a -- create name parent properties = ...
That should be: create :: (Widget b) => String -> b -> [Property] -> IO a A widget's parent must be a widget, but not necessarily the same type of widget.
Why would you prefer this over the other method?
Partly for simplicity and uniformity in general, and partly for simplifying code which constructs UIs dynamically. If you have the generic interface, you can easily implement type-specific versions, e.g.: createLabel :: (Widget a) => String -> a -> [Property] -> IO LabelWidget createLabel = create createButton :: (Widget a) => String -> a -> [Property] -> IO ButtonWidget createButton = create OTOH, if you only have the type-specific versions, implementing a generic function comes down to a case statement which has to be extended as new types are added.
One problem with this method seems to be runtime errors for nonexistant classes.
No; with either approach, the class has to exist at compile time. If
you have widget-class values which are passed as an argument (as for
XtCreateWidget), you have to get the value from somewhere. With type
classes, the compiler will infer a specific type, which has to exist.
--
Glynn Clements