The Importance of the GUI in Cross Platform Development
The key question in making your program cross platform is how to port the GUI. One solution is to write separate GUI front-ends for each platform. This gives you great flexibility and lets you hand-fit each interface to the target system, but soon you find you are rewriting the same interface ideas from scratch. You start to wonder if you shouldn't abstract out some concepts, such as creating a button or drawing a line, and use that abstraction instead. This is precisely what portable GUI toolkits already do. So instead of re-inventing the wheel, or, widget, you will probably want to choose a GUI toolkit and hopefully even improve it.
There are two approaches to providing platform-independent GUI functionality. The wrapper approach wraps the native system widgets in an abstraction layer that provides a common functionality among the different systems. The emulated, or pure, approach simply intercepts the native drawing calls and then uses those calls to implement its own widgets.
Wrappers are easier to program because you don't have to write your own widgets. The look and feel of the native target platform is easily maintained because, under the wrapper, you are using the native system widgets. However, wrappers also lose flexibility because they can only provide what the native widgets already provide—a “lowest common denominator” approach to portability. They can't be extended. They do not allow you to exploit the full power of a toolkit.
I personally prefer the pure or emulated widgets over the native wrapper classes. If you are impressed with certain native widget features in the latest release of Windows, you may fear that emulated widgets will lag behind those native, wrapped widgets. For me, it's the other way around. I see the emulated approach as having the flexibility to exceed native platform features. I believe that if the majority of free GUI toolkit makers were working on a common “Linux GUI API”, we would soon outpace Windows and other company-controlled GUI development with the excellence of our new and emulated widgets.
I'm working on programs that need to be fully multilingual, including fairly complicated composition of Chinese, Japanese and Korean characters (kanji). I'm not impressed with the new native widget features of Windows; they don't come close to doing what I need. So with widget wrappers I'm stuck basically rewriting every widget from scratch based on a Canvas widget, whereas with pure widgets I can use the usual object-oriented techniques to extend existing widgets (assuming the API is well-designed). This provides greater flexibility and consistency when writing GUI applications.
For Linux and UNIX there is another problem with native widget wrapping; it is not clear what constitutes native widgets. In Windows and Macintosh this is obvious. But there is no standard GUI API for UNIX (other than the X protocol, which is not a full GUI). The closest UNIX gets is Motif, which is not really a standard and is not free. In other words, in the Linux world, even before you consider questions of portability, you first must choose a GUI library. You must determine what widgets will be your native widgets. In addition to providing all the widgets and structure you want for Linux programs, your chosen GUI toolkit may offer assistance in cross-platform development. And that is what you want. Programming is now more efficient, as you only have to master one set of tools.
Since C and C++ are so popular, most of the toolkits have C or C++ interfaces. In fact, most of the time it is C++ because object-oriented programming seems particularly applicable to GUI code. However, some, such as Fresco, attempt to be language neutral and potentially provide an interface to almost any language. These toolkits come as libraries that must be compiled and linked for each target system. On the other hand, there are the interpreted languages such as Smalltalk, Tcl and Java that can run on multiple systems without having to be compiled for each one. Then there are the toolkits written in C, such as GTK, that can be called from many other languages such as Scheme, Python or Perl. (Note that GTK is not currently cross platform, but see below.)
Linux needs a standard GUI API. It's not that all applications must end up looking and even acting alike as in Windows, but they should be consistent in certain areas; for example, a consistent desktop, consistent help system, cut and paste, drag-and-drop and so forth.
The fragmentation of development energy into too many GUI toolkits is one of the most serious problems facing the Linux community today. There is some recognition of the magnitude of the problem but nobody can agree on which GUI toolkits to use. A good example is the Gnome and KDE desktop projects; Gnome uses GTK, and KDE uses QT.
For Windows and Macintosh, it's simple; you don't have a choice. Naturally, I prefer the fecundating chaos of the world of Linux and GNU to the stifling dictatorial conformity of the Microsoft domain but, as a programmer, it would be satisfying if the choice of GUI toolkit were a no-brainer. It would be nice if there were such a thing as the “Linux GUI API” so that the synergy of the Linux developers' community could better foster the creation of innovative and compelling programs rather than merely innovative but unfinished tools.
In contrast to the well-focused, Linus-centered Linux kernel development, everyone has their own idea for GUI toolkits and proceeds in their own direction. They usually only make it 90% of the way. A new toolkit comes along, reduplicates the first 90%, then fades away or is overtaken by another toolkit that charges ahead but never reaches the goal. These GUI toolkit development projects cannot seem to sustain the energy and support needed to add that last 10%. The contents of this “last 10%” vary, but usually include such things as support for internationalized input methods and fonts, and threads. This is frustrating, to say the least.
If I had my way, Fresco would be the number one toolkit for everyone to work on. However, I can't force anyone to do that, and I can't do it all myself. Many others, with different favorites, are in a similar predicament.
Not everyone will share my taste (understatement), but here are my thumbnails of some of the most promising candidates. Note that most of my own interest in cross-platform development has been for Linux (UNIX/X11) and Windows. If a solution also supports Macintosh and OS/2, it's merely an extra bonus. I have favored toolkits that are free and unencumbered of odious licensing restrictions. There are about 100 GUI Toolkits listed on the “GUI Toolkit, Framework Page”, so clearly this is just a small sampling.
Fresco is an object-oriented user-interface toolkit, designed by Mark Linton, among others. Mark Linton led the development of the InterViews toolkit at Stanford, and he seems to have learned a lot about GUI API design from that experience. Fresco is implemented in C++ (Ada and Java versions are also available) but the programming interface is written in IDL (Interface Definition Language) and so it is language neutral. Fresco uses CORBA and supports distributed graphical embedding. It supports structured graphics and resolution independence. It supports X, Windows and Macintosh. Widget implementations are exposed through kits which can allow a different look and feel on each platform; however, only a Motif look and feel has been implemented.
With Fresco it is very easy to extend widgets and write new ones. I wrote a simple, yet flexible table widget in a couple of hours. It uses the concept of a DAG (directed acyclic graph) of glyphs, which can be figures, layouts or widgets. The DAG includes full 2-D transformation information, which makes for some impressive demos. One example is a drawing editor that embeds a copy of itself in the drawing, scaled and rotated, that is still fully functional. It is both cool and powerful. For layouts it uses TeX's concept of boxes and glue, which is also convenient and powerful.
However, I guess Fresco is one of those things that is almost too good to be true. Originally a contender as a new X consortium standard, the companies that sponsored the work have abandoned it, and commercial UNIX is going with Motif instead. This places a lot of responsibility on anyone who decides to use Fresco. If there is anything you need, you'll probably have to write it yourself. The two biggest missing pieces are support for printing and for the system clipboard/selection. Fresco needs more widgets, more polishing, and more documentation, i.e., it needs more people working with it and on it.
I recommend looking at the design of Fresco even if you don't plan on using it. Fresco may just be ahead of its time. Look for some of the concepts included in Fresco to be hailed as brand new revolutionary technology in the next 10 years.
OpenStep is a GUI API (along with some non-GUI functions) originally based on the NextStep system. GNUstep is a free implementation of OpenStep. It is a work in progress and has not really reached a usable state yet.
The API seems above average. One nice feature is the use of the powerful Display Postscript for screen drawing which makes printing close to trivial.
The biggest issue is that it uses Objective-C. I don't feel like learning one more language, but after years of trying to find the best solution to the GUI toolkit issue, I may. With the recent Apple-Next hype going on, OpenStep could get enough momentum and hype behind it that using it for free software could pay off. Apple has adopted OpenStep as the future direction for the MAC API, and they will also provide an implementation for Windows. However, the future success of Apple and OpenStep is unclear.
GNUStep is licensed under the LGPL so it can be used in both free and commercial programs.
wxWindows was one of the first free C++ cross-platform GUI toolkits. It takes the wrapper approach to providing cross-platform functionality, wrapping either Motif or XView on X and Windows widgets on Windows. There is also a partial port of an older version of wxWindows to Macintosh.
wxWindows has much practical functionality and lots of development activity, but it suffers from the disadvantages of wrapping other widget libraries rather than implementing its own. It's not as consistent and flexible as it could be. Different platforms often have different functionality and different bugs, and development between platforms is not always in sync; therefore, you have to be careful that your program actually works on all platforms.
There are many extra high-level widgets written in wxWindows, such as tables and HTML viewers. wxWindows also provides some higher-level architecture functionality such as a Doc/View and Print Preview, although I have not personally tested these.
If your program doesn't require more advanced interfaces than provided by the common functionality of the simple native widgets across platforms, wxWindows is a good, practical choice.
A new version of wxWindows in the works, version 2.0, will have some changes in the API in an attempt to make it more functional. There is also a project to make wxWindows wrap the GTK widget library, and a project to implement generic widgets using wxWindows drawing calls. It is too early to predict how these changes and additions will affect the future of wxWindows.
Tcl/Tk is a popular solution for GUI programs on X, and it has been ported to Windows and Macintosh. Tcl is a simple scripting language, and Tk is a widget set that can be used with Tcl to create interfaces. I do not find the Tcl language particularly appealing, and Tk is tied fairly closely to Tcl, although some effort is being made to more cleanly separate the two. There are bindings for other languages such as Scheme, Python and Perl. However, using Tk from C or C++ is reportedly somewhat awkward. I have noticed that Tk applications tend to be rather sluggish, but I don't know if this is because of Tcl or the Tk widgets themselves.
One other disadvantage of Tk is that the look and feel (sort of like Motif) is the same across all platforms, so the interface may look out of place to Windows and Macintosh users, although I have heard attempts to remedy this are underway.
Despite the disadvantages, Tk does have a lot of full featured widgets. I understand it is possible to create interfaces relatively quickly. It is certainly worth considering.
A programming language and portable virtual machine and a collection of libraries (called packages), these three technologies together are now apparently called “Java”. Java has received a lot of hype in the past couple of years. While the virtual machine and the rigidly specified language provide some minor portability features, the most interesting part of Java to me is the cross-platform GUI API. The original GUI API, known as the AWT, is a simple wrapper library that has nothing in particular going for it. However, Sun is now creating a new set of pure Java widgets, known as “Swing”, which seems to be well designed and fully featured. With all the hype and momentum behind Java, Swing has the potential to become one of the best GUI libraries available.
The disadvantage, of course, is that Swing (part of the JFC, Java Foundation Classes) is about as far from language neutral as possible. If you want to use Swing, you must take the Java language and the other Java libraries with it, generally abandoning your perfectly good existing libraries.
My biggest complaint about Java is just that I feel like I'm not really developing for Linux anymore; instead I'm developing for the “Java platform”. I get fatigued wading through all the hype and nonsense that the trendiness of Java engenders, and I miss the refreshing honesty of the Linux world. I'm also not totally comfortable with the fact that Sun controls the direction of Java. If we in the free software world don't like something about it, there's ultimately nothing we can do, despite Sun's assurances of openness. There are free implementations of the Java language and virtual machine, but at the rate Sun is creating APIs, free implementations of the libraries trail far behind.
I would like to see the ability to use the high quality Java JFC library and still integrate with the direction of the free software world. Perhaps some cooperation with the GNOME project to allow Java applications using Swing to comply with the GNOME application policies would be helpful. Then people could write GNOME applications in Java, even if they used JFC instead of GTK.
Qt is a commercial C++ toolkit available for X and Windows. It is not free in the monetary sense, costing about $2200 for both the X and Windows version. There is a special exception: if you write a free program for X you can use it for free. However, this free program is not really free in the GNU sense, or in the Debian Free Software Guidelines sense, which causes many people (including me) to be wary of basing projects on Qt.
Technically, Qt is reasonably well designed. Particularly notable is its flexible “signals and slots” method of event handling. Qt is being used in the KDE desktop project.
Win32 is the API for Windows NT and Windows 95. Because of its popularity, it is also being used as a cross-platform API. Microsoft sells an expensive package that will allow you to compile Win32 programs for Macintosh. There are also expensive Win32 libraries available for various flavors of UNIX. The Wine (windows emulator) project is attempting to create a free implementation of Win32 on top of X, along with a binary emulator to run Windows executables directly.
The problem with using Win32 for Wine is that Wine is not mature enough yet, and because the API is controlled by Microsoft, the free implementation will always lag behind Microsoft's own. Win32 is, obviously, a Windows-centric API, and it is not a particularly good API, so the prospect of using it to develop Linux GUI programs is not very exciting. However, if you already have a lot of Win32 code written, or are already very experienced with the API, it may be worth considering investigating one of the implementations.
OSF/Motif is a set of commercial libraries and widgets built on top of X Toolkit Intrinsics (Xt) which in turn is built on top of Xlib, the lowest layer of X. Motif, in my opinion, is just adequate. Creating applications with Motif is tedious, and from the user's point of view Motif is also just passable, nothing to get excited about. Unfortunately, it is Motif, rather than something technically excellent like Fresco, that the commercial UNIX vendors have declared the official UNIX GUI standard (along with the Common Desktop Environment, CDE, which is built upon Motif) under the auspices of the Open Group.
However, just being declared a standard doesn't make it so. Many people dislike the mediocre quality of Motif and use other solutions for programming X applications. And since Motif is not free, it is not very widespread among Linux users. The vast majority of X applications included in Linux distributions do not use Motif. So, regardless of the Open Group's decree, Motif cannot really be considered the obvious native UNIX GUI library the way Win32 is for Windows and QuickDraw and the Toolbox is for Macintosh. The best that can be said is that most toolkits for X tend to provide a look that is somewhat similar to Motif.
Motif does have one advantage, though; it does provide the ability to create much of what you will ever need in a GUI for your program, even if it takes a lot of time and effort. Motif has much of the functionality of that last 10%, such as full keyboard control, a resource system to customize widgets, support for internationalized input methods and fonts and for threaded programs.
There is a free implementation of Motif available, called Lesstif, that is just becoming usable for some applications. It still needs work to provide the coverage that the latest version of Motif (2.1) has, however. There are commercial versions of Motif for NT, although they are expensive, so it is possible to use Motif in a cross-platform application. I believe Xlib and Xt have already been ported to NT, and theoretically I suppose Lesstif could be ported, which, again theoretically, could provide a free solution on NT.
GTK is the GIMP ToolKit (see LJ Issue 47), the widget library used in the free image manipulation program the GIMP. (See LJ, Issues 43, 44, 45 and 46.) The most interesting thing about it is that it seems to be gaining some momentum in the Linux free software world, as more and more projects are using it. Perhaps most notable is GNOME, a project to create a unified, consistent graphical desktop environment built entirely on free software.
In the software world, momentum is often more important than technical design, so GTK is worth investigating for that reason alone. Not that GTK is technically bad. It is a fairly low-level toolkit, written in C, so it doesn't provide a lot of high-level support. The attempt to use object-oriented design implemented in C creates a lot of busy work in the code that is somewhat distracting. However, because it is written in C, it can be used by almost any language, and there are already bindings for C++, Guile, Scheme, Objective C, Perl and probably others. This is no doubt one of the reasons for GTK's popularity.
The design seems reasonable. It is not as flexible as Fresco, but at least it gets some of the basics right, like having a button contain a widget rather than a character string. It also provides layout using horizontal and vertical boxes, which although I found the methods not as intuitive as the TeX inspired boxes and glue of Fresco, they still provide a reasonably straightforward interface.
For handling events, GTK uses a system of signals and slots, like Qt. The C++ interface to GTK, known as GTK--, also provides a nice implementation of the signal/slot methods using templates, an improvement over Qt's macros.
GTK is still immature. It lacks support for full keyboard control, a resource system, unified printing interface and internationalized input and display. It also is currently only for X. It is implemented on top of a low-level, thin wrapper around some Xlib functions, called GDK. This may make porting to other systems easier, although if the wrapper is so thin it requires Xlib semantics, it may be harder. I include it here because ideally the best Linux GUI toolkit will also be a cross-platform GUI toolkit. I hope that as GTK matures into a more obvious choice for a Linux GUI toolkit it will also become a more obvious choice for a cross-platform solution, and we won't have so much fragmentation and duplication of effort.
In short, I have found no obvious winner among the various toolkits. I'm using Java and the Swing package now, while investigating GTK and others in more detail. Ah, yes, I am still dreaming that Fresco will rise again, Phoenix-like, from the ashes.
Michael Babcock has been using Linux since 1992. His programming interests include multi-lingual software (especially Chinese and Japanese), parsing techniques, graphics and anything that will help improve and promote Linux. He enjoys playing basketball, playing the guitar and listening to The Fall. He expects to graduate from the University of Montana in May 1998 with a bachelor's degree in computer science. He can be reached via e-mail at email@example.com.