HTML PLAIN reference V1.1
4. The graphical user interface
Next: 5. Example and test Up: HTML PLAIN reference V1.1 Previous: 3. Parsing the documents
While many users may prefer to edit the files directly in ASCII mode, using an editor like Emacs or vi, there is always the danger that the user does not obey the syntax rules given by the files to edit. In this case, the user must always use tab to separate the entries; if he does not, the settings will not be read correctly.
The graphical front end prevents this by automatically generating the correct syntax. It also provides a more pleasant front end than vi, and is easier to use than Emacs. Because the front end only has the functions that are required, it is much more intuitive than a huge word processor or text editor.
Why did I choose Tcl/Tk, and not a different graphical toolkit? Due to my experience with Perl, something like Perl/Tk sounded very attractive, too, but Tcl/Tk is so widely used that I just had to try it. I had never programmed in Tcl before, but it was not too hard to learn. The syntax is rather unusual, without any round brackets and without having the equal sign for assignments. Tcl/Tk proved to be quite a good toolkit for developing the editors, mainly for two reasons:
Due to its advantages, Tcl (and later the windowing toolkit Tk) became fairly widespread, mainly in the Unix domain. Even though there are Mac OS and Windows versions available, these were hardly ever used. Tcl was invented as a ``glue language'' between applications, and there are still a few important Tcl applications left nowadays, such as ``expect''. (``expect'' automates interactive programs such as ftp.)
Tk built on that philosophy, and allows to write small GUI applications rather easily and quickly. However, the number of predefined widgets is rather small compared to modern graphical toolkit such as the Gimp toolkit [gtk] and the Qt library [Qt]. For example, I missed a table-like widget, or a list box widget with multiple columns (including column titles). Both of the other libraries mentioned above have these as standard widgets.
Tk's canvas widget allows the programmer to build such more complex widgets; however, this still involves quite a bit of work. Probably this and the fact that Tcl is entirely different compared to other programming languages account for the relatively small number of Tcl/Tk applications which are released in these days. Tcl/Tk is still a very good tool for prototyping small applications, before the programmer moves on to more complex and more powerful toolkits.
Besides Tcl/Tk, gtk+ and Qt were two other alternatives. Both have a Windows version of their library, but Qt has no Mac OS version. While gtk+ is written in a sort of ``object oriented C'', Qt is a pure C++ library. This makes Qt easier to deal with, as C++'s object oriented syntax allows quite an intuitive way of developing graphical applications. There is also a C++ wrapper for gtk+ (called gtk-).
One of the reasons not to choose a compiled language for early development is the time that the programmer has to wait for each compilation. This influenced my choice in favor of Tcl/Tk. There are also other reasons, though: Towards the end of 1998, when the development of the GUI tools started, Qt still had license problems; it did not allow programmers to publish patched versions. Also, it is not very popular, and visually not more attractive than Tcl/Tk (of course this is also a matter of taste).
Gtk+ is highly customizable and by no doubt the best looking graphical toolkit. It also offers a wide range of widgets. On the downside, as it is often the case with libraries that develop quickly, the documentation was never quite up to date, and it was a fast moving target, with new releases every week. The C++ version, which I would have preferred over Tcl/Tk, was still in catching up with the numerous features that were added weekly to gtk+. Therefore, gtk- was not a good option by the end of 1998 (there was not even an up to date tutorial for it). By now, version 1.2 of gtk+ and version 1.0 of gtk- has been released. Gtk- could almost catch up with the gtk+ development, so it is now a good time to write new applications using one of these two libraries.
If the graphical tools should become popular enough, I may rewrite them in gtk one day. I will also consider the gtk for future applications. However, it was not mature enough when I started the development of my applications.
Table 4.1 shows an overview of all Tcl/Tk modules that are used by the utilities for HTML PLAIN. All programs have a
This editor basically reads a file with Perl assignments in the form
All assignments with the structure mentioned above are shown as ``Setting/Value'' in a list with two columns. Because the name of the setting is read only and the number of the settings is fixed, the front end is quite simple. It allows the right hand columns to be changed, but not the left hand ones. Due to the fact that no entries can be deleted or inserted, it is also easy to add the comments again when saving the documents, and fit in any other lines that did not contribute to the settings.
This was the first one of the series of configuration tools I wrote. The design
is very basic; the only tricky component are the two linked list boxes. Even
though it is extensively covered in [Wel97, pp. 513 ff.], the implementation
given there is not completely bug free, and lacks any keyboard support. It tried
my best to improve it, but there are still a few occasions where the two list
boxes do not cooperate as expected - and it seems to be impossible to fix that.
This screen shot (as any other screen shot) has been taken under WindowMaker. It shows the configuration editor. The settings are shown to the left, their values to the right. As soon as a user selects on a setting (or its value) either with the mouse or with the keyboard, it appears in the upper part of the window. The first entry is read only, so the cursor will appear just at the second part where the setting can be changed. The comments in the script file are used as status messages in the program, in order to provide the user some guidance for selecting the correct setting.
The user confirms the changes with [Return] or by pressing the ``Ok'' button. The change can be canceled by pressing [Esc] or selecting a different entry. The ``Reload'' button (later renamed to ``Revert'') reverts the changes back to the state of the last saved file.
This program has exactly the same functionality as the standard version, but the fields are directly changeable, like in a table or spreadsheet. The user can choose between the two programs.
Implementing the spreadsheet-look-alike required using the Tk canvas, which allows the free placement of a wide range of widgets. Implementing the scrolling is surprisingly simple, and the example given in [Wel97, pp. 411 ff.] could almost directly be used in the actual program. However, there were again some subtleties and problems that were not covered by the book.
First, it seems to be impossible to make the text entries in the canvas object scale if the window size is changed. The canvas grows or shrinks with the surrounding parent window, but the size of the entry widgets is always the same. The book did not provide any hints on whether this can be implemented or not. The only solution that worked was to choose a generous size for the entry widgets and then disabling horizontal resizing, which is of course not a very nice solution.
Second, keyboard traversal and focus behavior were again not covered by the example, but because using a canvas yields a much cleaner implementation than by trying to make two list boxes cooperate, it was not hard to implement that.
This program lets the user change the values of the variables defined, and also add new settings or delete existing ones. The editor works very similarly to the configuration editor. Unlike in the configuration editor, the comments are changeable, and the number of entries can change, too. This required a whole range of new methods, some of which were not compatible with the object that handles the two list boxes for the configuration editor. Therefore, the code had to be forked, and the module that handles the two list boxes is slightly different.
The user can again select the entry that he wants to change with the mouse or the keyboard. Alternatively, he can press [Insert] or [Delete] in order to create an empty entry or delete an existing one, respectively. An ``Undo'' operation has been added in order to provide recovery from accidental deletions. The program also checks whether a changed or new entry collides with existing ones (since no two variable names may be the same).
Unfortunately, tracking the position of comments that go over an entire line is quite difficult when entries are added or deleted. Therefore, the method that loads the file stores these comments in a separate list and inserts them all at the beginning of the file when it is saved. This mangles the order in which the comments were inserted. It is recommended not to use comments that go over an entire line or multiple lines, and indeed this option is not allowed in the editor, which only allows the insertion of comments at the end of a definition. This should be all right in most cases, as comments that go over an entire line are commonly only used at the beginning of a file (e. g. for copyright notes).
In order to save some typing when the user wants a WWW color (one out of 216 colors whose R, G, B values are multiples of 0x33) or a filename (e. g. if he wants to refer to a non-HTML document), two dialogs ``Insert Color'' and ``Insert Filename'' have been provided. They can both be invoked with the right button, in which case a pop-up menu appears. (On Mac computers with one button, a modifier key has to be pressed together with the mouse button for getting the same function.) The filename selection is not worth further description, because it just uses the given Tk dialogtk_getOpenFile. The color picker has been rewritten from scratch, though.
There are two color pickers that ship with the standard Tk libraries. One is thetk_chooseColor dialog, which belongs to the Tk library and is available through a simple library call. That colorpicker is quite small, fast and simple, but it does not help the user in choosing a color that is compatible to the standard 216 color palette. Another disadvantage is that only the colors that are derived from the current RGB value by changing one number of the (R, G, B) triple are shown. It is therefore not always easy for a user to imagine which slider he has to move in order to end up with the color he likes, especially not if he is not familiar with the RGB model.
Therefore I tried to improve the other given color picker which is commonly found under/usr/lib/tk8.0/demos/tcolor or a similar name. That color picker supports the RGB, CMYK and HSV models and also shows a large number of predefined color names. This may sound very appealing (especially for professional artists). However, there are some serious drawbacks:
Therefore I decided to write a new color picker from scratch, which does not have any of these disadvantages. The user can conveniently select one of the 216 colors directly with the mouse, or enter a numerical value (in which case the color that matches the entered one best is chosen from the graphical representation). The rectangle to the lower left always shows the exact chosen color. The only disadvantage with this color picker is the fact that drawing all 216 colors in the first place takes a while under Tk, but the delay is acceptable (roughly one second, probably less with fast CPUs).
The template editor has almost exactly the same functionality as the variable editor; therefore, the two programs share most of their code in a module calledcommon.tcl. The major difference between both programs is the fact that tag redefinitions can span several lines; therefore the parsing of the file structure and the user interface become a bit more complicated.
One of the more outstanding features of the template editor is syntax coloring. This could be relatively easily achieved in tcl/tk, because the text entry widget supports ``tags'' which allow to change the style of a certain part of the text very easily, and also ``marks'' which enable the programmer to keep track of certain parts of the text, independently of absolute locations.
Of course the algorithm for the easy recognition of the portions of the text that need to be highlighted still needs to be written. I use the following approach: Every keystroke is ignored, except for the few special keystrokes which either delete a character or add one of the syntactically important ones, being"<", ">", "&", ";" and the double quote itself. For other texts than HTML, this could of course be extended. For HTML entities between "&" and ";", the action to be taken is quite simple: if there is a closing ";" within the current line, color everything that forms the HTML entity, otherwise use a warning color indicating a syntax error. The same goes for HTML tags, even though they can span multiple lines. However, for clarity and simplicity, this is not allowed in the template editor.
It soon turned out that just having some special code for each one of the delimiters of a symbol may be fast, but would soon lead to rather messy code. This is mainly because the deletion of such a character can yield to many possible states. E. g. the deletion of a"&" sign can be in one of the following situations (the underlined "&" gets deleted):
Therefore, the whole line has to be parsed when a character changes. This can be speeded up by only doing that when one of the delimiters of a syntactic entity is added or deleted. For HTML, these symbols are"<", ">", "&", ";", "!" (for comments) and the double quote. If such a symbol is typed, the whole line is parsed and colored.
Deletion of a character is still a special case, because two lines may be joined. However, this was not much of a problem. For similar reasons, [Return] has also to be treated specially, because it separates two lines.
In the implementation, the default handler is carried out after the supplied custom handler. This means that if the user types a character, the custom handler is carried out before that character is actually inserted into the buffer! This is of course not acceptable for an editor with syntax coloring, since the true text is always known one keystroke too late. Fortunately, the order in which events are processed can be changed by thebindtags command. This allows to override the ordering in which the handlers are carried out.
However, if the default handler is carried out, we run into a problem when a character is deleted. Because the character is removed from the buffer before our handler is invoked, we can no longer find out which character was actually deleted. Therefore the only solution is to have our handler executed first and then execute the default handler. If our handler is called, we have to insert the typed key ourselves, in order to have an updated buffer. Of course we have to suppress the default handler in that case, since this would result in having every character inserted twice. The current implementation overrides the default handler for all special characters (the delimiter symbols, backspace, delete and return) and does not allow the default handler to run in these cases. For all normal characters, the default handler does the job of inserting the character.
The procedure for coloring a line of text is not too complicated. A regular expression search shows us the first occurrence of a delimiting character, in which case we look for the character that ends the entity. In the case of an HTML tag, whenever we see a"<", we look for the closing ">" and color all the text between the two angular brackets (and the brackets itself) with the appropriate color. This can be easily achieved by using Tk ``tags'' for changing the appearance of text (see Section 4.5.1). We have to take care to delete all existing tags in a line first, before re-tagging that line.
Because different syntactical entities may occur within each other (e. g. a quoted string within an HTML tag), the procedure is recursive. Usually it is not allowed to have a different kind of entity within another one (e. g. a quoted string within an HTML entity), in which case we indicate this syntax error with a special color.
Due to the simple pattern matching used, the syntax coloring is not perfect and cannot detect all mistakes. E. g. if someone types
Other than the replacement of the simple entry widget by a more sophisticated text widget with syntax coloring, there are few differences between the template and the variable editor. The possibility to insert colors or filenames directly into the text has been omitted, because this should be done in the variable editor. The idea is that the user defines a variable for each color used, in order to be able to change that color more easily later on. This variable can then be used in several places in the template.
Of course the file format is slightly different, which leads to a different parsing method for loading the files. Namely the line spanning tags and C comments were tricky to handle. Because Tcl's regular expressions are not quite as powerful as Perl's, only C comments which go from the beginning to the end of a line are allowed. Since C comments are only used by people who edit the file directly in ASCII mode, this should not be a problem. The template editor also inserts all long comments at the beginning of a file when saving it, thus having the same minor restriction as the variable editor.
In order to allow easier testing by as many people as possible, a small demo program is provided that launches all the other programs so the user does not have to remember which.tcl files to use.
I first tried to find some testers via freshmeat |http://freshmeat.net/| (a page that announces many newly released software, mainly Open Source software for Linux), and there were indeed many people who downloaded it during the time when it was visible on the front page (about 40 people per hour during about five hours), which is quite surprising, because I did not release the back end yet, so the program did not actually do anything useful at that stage :-)
However, I did not get any feedback either. Probably no one cared that much about a simple Tcl/Tk user interface in order to help me to improve it. Therefore the next release would include the back end and all required documentation. And indeed, I got a little feedback, which proved quite useful - mainly for improving the documentation.