\chapter{The dialog editor} \label{sec:dialogeditor} \index{controls,GUI tool for}% The dialog editor is a GUI based tool for the definition of dialog windows (windows with controls). It supports the following phases of the definition of a GUI: \begin{itemize} \tick{Specifying the required controls} Prototypes of controls are dragged to the {\em target} dialog window. They are moved to---roughly---the right location. \tick{Refining the controls} The controls may be refined: specifying labels, sizes, fonts, items in menus, etc. \tick{Fixing the layout and size of the window} The layout specification for the dialog window is established. The Dialog Editor guesses the layout intentions of the user and translates these into \product{}'s dialog-window symbolic layout statements. \tick{Specifying behaviour} Both internal behaviour and the link to the application may be established using graphics. The dialog may be tested, while graphical animation illustrates how user-actions are processed and transferred to the application. \tick{Generation of code} A Prolog description of the dialog window is realised by dragging the dialog from the list of dialog-windows to a PceEmacs window running in Prolog mode. \tick{Linking the dialog in the application} The generated code is a clause of the predicate dialog/2. The first argument of this clause {\em identifies} the dialog, while the second arguments describes the structure and behaviour of the dialog. The body is empty. The library predicate make_dialog/2 is used to create a dialog window from the description of dialog/2. \end{itemize} \section{Guided tour} We will now illustrate the functionality of the Dialog Editor by defining a simple prompt dialog that asks for a name and has an {\sf ok} and {\sf cancel} button to confirm or cancel the operation. The result is shown in \figref{diaaskname} \postscriptfig{diaaskname}{Ask-name dialog generated by the Dialog Editor} \subsection{Creating the target dialog window} First, start the manual tools using manpce/0 or user_help/0. Then, start the dialog editor using the option {\sf Tools/Dialog Editor}. The main window of the dialog editor is now opened on the screen. Use the option {\sf File/New Dialog} and enter the name `ask_name'. This will add ask_name to the Dialog Windows browser and open an window with the title `Ask Name'. See \figref{diaeditor1}. This window is called the `target window'. \postscriptfig[width=\textwidth]{diaeditor1}{The Dialog Editor with the ask-name target} \subsection{Adding controls to the new window} Next, the controls are dragged to the dialog window. The control marked \includegraphics[height=2ex]{textitemicon} specifies a text-entry-field. Drag this icon using the left-mouse button to the target dialog. If the mouse is above the target dialog, a dotted box will indicate the outline of the new item when it is dropped. Drop it in about the right location. Now drag two instances of \includegraphics[height=2ex]{buttonicon} to the target dialog and place them again at about the right location. Items can be moved by dragging them with the left button. They can also be {\bf copied} to other target dialog windows by dragging them there and they can be {\bf deleted} by dragging them to the window holding the prototypes. Now, double-click, using the left button, the text-entry field. A dialog with attributes will appear. The caret is positioned at the {\sf Name} field. Clear the name field (Control-U is the fastest way) and enter {\tt name}, followed by RETURN. The system will automatically fill the {\sf Label} field with {\sf Name} (capitalising the name of the control). If the label should be anything else than the capitalised name, type the correct label now. The other fields are self-explanatory, except for the {\sf Type} field. This specifies the type of object edited by the text-entry field. See `text_item <->type' for details. Pressing {\sf Help} creates a window containing the online manual cards of all displayed attributes. Double click on both buttons to fix the name/label. Assign the ok button to be the default button. The result is shown in \figref{diaeditor2}. \postscriptfig[width=\textwidth]{diaeditor2}{The Dialog Editor after specifying attributes} \subsection{Defining the layout} Next, the {\sf Mode} menu of the main Dialog Editor window is used to select {\sf Layout Mode}. The button {\sf Layout} guesses the symbolic layout description of the dialog and places the items. If you are not satisfied with the result, press {\sf Undo}. Next, you can help the layout mechanism by positioning the items closer to the intended position and try again, or place the items by hand. In the latter case, the generated code will express the layout using pixel-locations rather then a symbolic description and the result may look bad if the end-user runs \product{} with a different look-and-feel. The {\sf Fit} button adjusts the size of the dialog window to its content. \subsection{Specifying the behaviour} The next step is to specify the {\em behaviour} of the dialog window. Select the {\sf Action} mode and press the {\sf Behaviour Model} button to open the behaviour window. Now drag all items from the target dialog window to the behaviour window. Each control is now represented by a behavioural component. Each such component defines a number of {\em ports}. The Dialog Editor distinguishes between three types of ports: \begin{itemize} \tick{send-port} \index{send,port}% A send-port is the representation of a send-method defined on the controller represented by the behavioural component. \tick{get-port} \index{get,port}% A get-port is the representation of a get-method defined on the controller. \tick{event-port} \index{event,port}% An event-port is the representation of an instance variable defined on the controller that can hold an executable (\class{code}) object (see \secref{exeobjects}). Controls use these variables to define the {\em callback} actions of the dialog item. \end{itemize} The window (background) represents the {\em target} dialog as a whole. Ports may be added to both behavioural components and the background window using the popup menu associated with the right mouse-button. While hovering over the various parts of the behavioural model, the feedback window at the bottom describes the meaning of the current item. The popup menus defined on all components of the model provide context-sensitive access to the \product{} online manual as well as the online documentation of the Dialog Editor. In general, the action(s) associated with a control are specified by connecting its event-ports to a send-port in the diagram. The line connecting both ports has a fat dot in the middle. Get-ports may be linked to this fat dot to specify {\em arguments} for the send-operation. If a get-method needs to be performed on the value of a get-port to define the argument, {\sf Extend} the get-port, define a new get-port on the extension and link the result to the argument dot. For our {\sf Ask Name} dialog, we need to make a {\em modal} dialog, see \secref{modal}. Such a dialog returns by invoking the ->return method on the dialog window. The popup of the background is used to define a send-port named {\tt return}, representing ->return to the dialog. Position the pointer above the new item to validate your action. Now, as both methods will make the dialog return immediately, link the {\tt message} event-port of both buttons to this {\tt return} send-port. Link the {\tt selection} get-port of the text field to the argument dot of the link from the {\sf Ok} button. This specifies that the dialog will return with the `text_item <-selection' if the {\sf Ok} button is pressed. Add the constant @nil to the background using the popup menu on the background. This finishes the specification of our dialog window. The resulting behaviour model is shown in \figref{diaeditor3}. \postscriptfig[width=4.5in]{diaeditor3}{Behaviour model of {\sf Ask Name}} \subsection{Generating source code} \index{source code,from dialog editor}% To generate source code, start PceEmacs using the {\sf Edit} command from the background menu. This will open PceEmacs on the file {\tt ask_name.pl}. Any other PceEmacs window editing a Prolog source file will do as well. Drag the {\tt ask_name} entry from the main window of the Dialog Editor to the PceEmacs window. The window will indicate it is ready to accept the Prolog source code. Now `drop' the code. The source code will be inserted at the caret location. See \figref{diaeditor4}. \postscriptfig[width=\textwidth]{diaeditor4}{Creating source-code} \subsection{Linking the source code} The generated source is a {\em description} of the dialog window. This description requires an interpreter to create the dialog window and use it in an application. This interpreter is implemented by make_dialog/2: \begin{description} \predicate{make_dialog}{2}{?Reference, :Identifier} Create a dialog window from a description generated by the Dialog Editor. The predicate make_dialog/2 searches for a predicate dialog/2 and calls this using the given dialog {\em Identifier} to obtain a description of the dialog window. See dialog/2 for the syntax of the description. \predicate{dialog}{2}{?Identifier, ?Description} Clause as generated by the dialog editor. The description is a list of \mbox{ {\tt :=} } pairs. It contains the following elements: \begin{itemize} \tick{object} Points to the Prolog variable defining the main object reference (the first argument of make_dialog/2). \tick{parts} A list of \mbox{ {\tt :=} }. make_dialog/2 will simply call new/2 on these terms to create the parts of the dialog window. \tick{modifications} List of \mbox{ {\tt :=} } that have to be applied to the parts to modify them from the default to the target configuration. The is a list of \mbox{ {\tt :=} }. \tick{layout} List of \mbox{{\tt below(, )}} and \mbox{{\tt right(, )}}, describing the symbolic layout of the dialog window. \tick{behaviour} List of \mbox{ {\tt :=} }, describing the behaviour of the control element. is a list of \mbox{ {\tt :=} }, describing the \class{code} objects associated with the controls. \end{itemize} \end{description} The wrapper program to make the dialog-description useful from an application is given below. First make_dialog/2 is used to create the dialog. Next the dialog is opened in the center of the display and the system waits for the `frame ->return' message to be send. \begin{code} ask_name(Name) :- make_dialog(D, ask_name), get(D, confirm_centered, RawName), send(D, destroy), Name = RawName. \end{code} \subsection{Summary} We have now completed the first guided tour through the Dialog Editor, introducing the main concepts and the process of creating a dialog window using this tool. After creating a target dialog window, controls are added to the dialog using drag-and-drop. Their attributes are edited by double-clicking the new controls and filling the subsequently shown dialog window. Next, the items are dragged roughly to the right location, the editor is placed in layout mode and the {\sf layout} button is used to let the Dialog Editor guess the symbolic layout description. Next the behaviour is defined using the behaviour model editor. Event-ports (control-attributes defining the callback of a control) are linked to send-ports (send-method ports) and arguments are linked to this activation relation. Finally the dialog window is dropped in a PceEmacs window running in Prolog mode (the default when editing a file with extension {\tt .pl} or {\tt .pro}). Finally, a small wrapper must be defined that creates the dialog window from the description using make_dialog/2 and opens the dialog in the proper way. \section{Miscellaneous topics} This section discusses various topics that were omitted from the Guided Tour to keep it simple. \subsection{Specifying callback to prolog} Using the background popup of the behaviour editor, the object @prolog (see \secref{pceprolog}) can be added to the model. Select {\sf Add Send Port} to add a new predicate to the @prolog interface. Then type the name of the predicate. Now link the event-port of a control to the predicate and link the arguments. If the predicate is not defined, select `Edit' on menu of @prolog to start PceEmacs on the source file. Now drag the predicate to the PceEmacs window. This will insert the head of the predicate at the caret. See \figref{diaprolog} \postscriptfig[width=\textwidth]{diaprolog}{Specifying Call-back to Prolog} \subsection{Advanced example of behaviour} \Figref{viewer} is the screen dump of an application and its behaviour model of a tool that shows all files in a directory and clicking on a file shows the file's contents in the editor to the left. It demonstrates various aspects of advanced features for specifying behaviour. \begin{itemize} \tick{The text-field {\sf directory}} Represented in the model by (1). It is a normal \class{text_item}, but the `text_item <->type' field is set to `directory'. This implies the <-selection of the text-item will return a \class{directory} object. \tick{Showing the files of the directory} If the text-item is modified, a list of files in the directory should be shown in the `file_list', a \class{list_browser}. The method `list_browser ->members' may be used to fill the browser with a collection of items. This method expects a \class{chain} object. The get method `directory <-files' provides a chain holding the names of all files in the directory. Thus, the event-port `message' of the directory field must invoke the send-port `members' of the file-list. The argument should be the result of applying <-files on the <-selection of the text-entry field. To specify this, the get-port `selection' is {\em expanded} using the popup menu of this port. This operation adds (2) to the diagram. The system infers this expansion is an instance of class \class{directory} and shows the most useful get-ports in its get-port menu. The `files' get-port is added to (2) and linked to the activation relation between `text_item ->message' and `list_browser ->members'. To {\bf test} this part, put the Dialog editor in `run' mode, type the name of a directory and {\sf ENTER} to activate the event-port. If anything goes wrong, the {\sf Simulate} option of the various popup menus in the diagram may be used to test small parts of the model. The {\em Documentation} option of these menus may be used to view the relevant documentation from the online manual tools. \tick{Specifying the initial directory as a parameter} Initialisation of the dialog is expressed by adding one or more {\em init-ports} to the diagram using the background menu. In this particular case, we would like to be able to pass a directory to start as a parameter. Hence, a {\em parameter-port} is added with the name `dir'. First, the ->selection is set using the parameter and then the item is ->executed to activate its ->message. Code generation will append the directory parameter to the identifier of the dialog/2 clause. In this case, this clause will start as: \begin{code} dialog(viewer(Dir), [ ... ]). \end{code} An instance is opened using the following calls: \begin{code} ..., make_dialog(D, viewer(StartDir)), send(D, open), ... \end{code} \tick{Showing a file} The first step is to link the event-port `select_message' of the file_list to the file_contents (3) \class{editor} object's send-port `load'. This method expects a file. Due to the type conversion rules of class \class{file}, the name of a file suffices, but the names from file_list are relative to the directory object (2). First, the <-selection of the file_list is expanded, resulting in (5), a \class{dict_item} object. The `dict_item <-key' contains the name of the file. The method `directory <-file' can be used to create a \class{file} object from a name, that specifies an absolute path. A get-port `file' is added to (2) and this get-port is linked to the activation relation. This get operation requires the filename argument from (5). \end{itemize} \postscriptfig[width=\textwidth]{viewer}{A file viewer} \subsection{Specifying conditional actions} \Figref{diacond} shows an example of a conditional activation relation. A conditional relation is created making a connection from the fat dot in the middle of an activation relation to a send-port. Success or failure of the send-port will be interpreted as a condition on the activation relation. \postscriptfig[width=\textwidth]{diacond}{Conditional activation} \subsection{Load and save formats} The Dialog Editor provides two load/save formats. The {\sf Load}, {\sf Save}, {\sf Save As} and {\sf Save All} save and load the status of the dialog editor as an \product{} object using `object ->save_in_file'. This format loads quickly, but is rather vulnerable to future changes in the Dialog Editor or any of the graphical classes. Alternatively, the Dialog Editor can restore itself from the identifier of a dialog/2 clause generated by itself or (slightly) modified. In this case, the layout of the behaviour model will be lost. We advice to use Save/Load during application development. If, during the maintenance phase of your product it is necessary to modify a dialog, either simply edit the dialog/2 clause, or load both the application and the dialog editor and use {\sf Reload From Id} to restart the Dialog Editor. \section{Status and problems} The current version of the Dialog Editor is experimental. It can be used for serious application development as the output format is extensible, so future extensions to the Dialog Editor will not break already generated dialog windows. The main problems identified are: \begin{itemize} \tick{Defining new controls} It is desirable to be able to create new (compound) controls using the dialog editor and save these in a library. At the moment new controls can only be created by programming them as a user-defined class. Connecting these user-defined controls to the Dialog Editor is not difficult, but no supported interface has been defined. \tick{Layout detection} The layout detection often makes mistakes, partly because it does not know about various important layout concepts. \tick{Integration with user-defined classes} It is desirable to integrate the dialog editor in a neat way with user-defined classes. Notably, the editor should support activating and defining methods on a user-defined refinement of the containing frame. \end{itemize} \section{Summary and Conclusions} Though the dialog editor has attracted quite some attention when it was developed, it remains a difficult product. Using WYSIWYG style of interface building appears attractive, but looses generalisations that can be made in a programming language. If you have been in a country of which you don't speak the language you understand that pointing is a rather crippled way to express your needs. Especially \productpl{} is strong in meta-representation and symbolic layout and the combination can easily be exploited to automate most of the simple control generation. A good WYSIWYG should provide a smooth transition between the beginners choice for WYSIWYG and the expert choice of using language. It was one of the aims of this project to achieve this transaction but modern \productpl{} applications are generally programmed in classes and the dialog editor presented here is build around direct relations between objects.