\section{Informing the user} \label{sec:report} \subsection{Aim of the report mechanism} Objects perform actions on behalf of the user. Sometimes it is desirable to inform the application user of progress, status or problems. In older applications, the action code often contained knowledge about the environment in which the object was embedded. This harms reusability and therefore \product{} provides a generic mechanism to deal with such messages. \subsection{The report interface} Whenever an object needs to inform the user, the programmer can use the `object ->report' method. The definition of this method is below. \begin{description} \sendmethod{object}{report}{type, format, argument ...} Inform the user. The message is constructed from {\em format} and the {\em argument} list. See `string->format' for a description of the C printf-like formatting syntax of \product{}. {\em type} describes the nature of the message and is used by the reporting mechanism to decide on the presentation-style. See \secref{reporttypes} for the available types and their meaning. \end{description} The object posting the report message will normally not be able to display the message. The main task of the implementations of this method in class \class{object}, \class{visual}, \class{frame} and \class{dialog} is to divert the report to an object that can present it. By default, this is either a \class{label} or the \class{display} object (@display). The implementation of `object ->report' will simply check whether there is a current event (see @event), which implicates the action was initiated by the user and then forward the ->report message to the `event <-receiver', which is normally the controller activated by the user. If there is no current event, the action must be initiated by a user query to the host-language and therefore `object ->report' will print its feedback to the host-language console using `@pce ->format'. The implementation of `visual ->report' will simply forward the message to its containing visual object. If the message arrives at an instance of class \class{frame}, the implementation of `frame ->report' will broadcast the message to each of its windows, but avoid sending it back to the window it came from. If this fails and the frame is a transient frame for another frame, the report is forward to the main frame. Class \class{dialog} will look for an object named {\tt reporter}. If it can find such an object (typically a \class{label}), the report is sent to this object. If all fails, the report will arrive at the @display object, which takes care of default handling. See \secref{reporttypes} on how the different report types are handled. \subsubsection{Information types} \label{sec:reporttypes} The report {\em type} indicates the semantic category of the report and defines how it is handled. The following report types are defined: \begin{itemize} \tick{status} Information on progress, status change of the system, etc. such information should not attract much attention. By default, \product{} will format the message at an appropriate location. If no such location can be found the message is ignored. \tick{inform} The user requested information and this is the reply. Handled as {\tt status}, but if no appropriate location can be found it will invoke `@display ->inform', presenting a messagebox. \tick{progress} Indicates progress in ongoing computation. Feedback is generally similar to {\tt status}, but followed by a `graphical ->flush' to take immediate effect. A sequence of {\tt progress} reports should be closed with a {\tt done} report. \tick{done} Terminates a (sequence of) ->report: progress messages. \tick{warning} The user probably made a minor mistake for which a simple alert such as provided by `graphical ->alert' suffices. If there is an appropriate location for the message it will be formatted there. \tick{error} Something serious went wrong and the user needs to be informed of this. For example a file could not be read or written. If no appropriate location could be found `@display ->inform' is used to bring the message to the attention of the user. \end{itemize} \subsection{Redefining report handling} There are two aspects in which the reporting mechanism can be redefined. The first concerns the {\em location} and the other the {\em presentation} of the report. The {\em location} is changed by defining the method <-report_to. All the generic implementations of this method will first invoke <-report_to on itself. If this method yields an answer, the report is forwarded to this answer. For example, class \class{text_buffer} defines a <-report_to that forwards all reports to its associated editor object. The {\em presentation} is changed by changing the implementation of `label ->report' or `display ->report. As this determines the look and feel of an application, applications should be reluctant using this. \subsection{Example} The typical way to exploit the report mechanism is by attaching a label named {\em reporter} to a dialog window of the applications frame. For example, an application consisting of a menu-bar, browser and a graphical window window could choose to make place for a small dialog for feedback at the bottom. The following fragment would build the window layout of such an application: \begin{pcecode} reportdemo :- new(Frame, frame('Reporter demo')), new(B, browser), send(new(picture), right, B), send(new(MD, dialog), above, B), send(new(RD, dialog), below, B), send(Frame, append, B), send(MD, append, new(MB, menu_bar)), send(MD, pen, 0), send(MD, gap, size(0,0)), send(MB, append, new(File, popup(file))), send_list(File, append, [ menu_item(load, message(@prolog, load, Frame), end_group := @on), menu_item(quit, message(Frame, destroy)) ]), send(RD, append, label(reporter)), send(RD, gap, size(5, 0)), send(Frame, open). \end{pcecode} Now suppose the implementation of the `load' action takes considerable time. The implementation below reads a file assuming each line in the file contains a word. \begin{pcecode} :- pce_autoload(finder, library(find_file)). :- pce_global(@finder, new(finder)). load(Frame) :- get(@finder, file, exists := @on, FileName), send(Frame, report, progress, 'Loading %s ...', FileName), get(Frame, member, browser, Browser), new(File, file(FileName)), send(File, open, read), ( repeat, ( get(File, read_line, Line) -> send(Line, strip), send(Browser, append, Line), fail ; !, send(File, close) ) ), send(Frame, report, done). \end{pcecode} The result is shown in \figref{reportdemo}. \postscriptfig[width=4in]{reportdemo}{The `reporter' demo}