Commit 74e11935 authored by Ian Lynagh's avatar Ian Lynagh
Browse files

Remove gui/poll.tex

It's not part of the report, and hasn't been touched for 10 years.
parent ea28a8e1
\documentclass{article}
\newcommand{\Party}[1]{\stepcounter{enumi}\arabic{enumi} \bf #1}
\newcommand{\rationale}[1]{{\footnotesize\bf #1}}
\begin{document}
\section{Opinions}
This is a collections of opinions on the general nature of what should
comprise a GUI library for Haskell. This document is the starting
point of defining a common GUI API, CGA for short. The CGA will be
published in a separate document. The source of this summary is the
GUI mailing list from January 2003 onwards.
The following opinions are ordered by the first contribution.
\begin{enumerate}
\item[\Party{Simon Peyton Jones}] Opinion:
\begin{enumerate}
\item \label{allspj} want GUI library which is available on major platforms
\item want confidence in its continuity
\item \label{interspj} compromise to gain portability
\item \label{hinderspj} having platform specific bits is OK
\item \label{highspj} no yet: high-level design
\item \label{scratchspj} want specification of mid-level API before
discussing implementation details
\end{enumerate}
Proposal:
\begin{enumerate}
\item use Clean's Object I/O back-end
\item write a common API specification which has implementations on
different platforms, providing as much functionality as possible
\end{enumerate}
\item[\Party{David Sankel}] Opinion:
\begin{enumerate}
\item \label{allds} platform-independence is of primary importance
\end{enumerate}
Proposal:
\begin{enumerate}
\item use Qt as guideline for portable widget set
\end{enumerate}
\item[\Party{Keith Wansbrough}] Opinion:
\begin{enumerate}
\item \label{interkw} want minimal API which can be implemented by
each toolkit
\end{enumerate}
\item[\Party{Wolfgang Jeltsch}] Opinion:
\begin{enumerate}
\item \label{lookwj} look and feel of the native platform is
important, also in terms of connecting to additional functionality
\item GTK violates native look and feel even on Windows %30 Jan 2003
\item \label{lowwj} to achieve a native look and feel across
platforms, the common API needs to be at a higher level than the
veneer (L) level
\end{enumerate}
Proposal:
\begin{enumerate}
\item \label{langwj} write the low-level (i.e. imperative) layer in
C so it can be used from other languages
\end{enumerate}
\item[\Party{Vincenzo Ciancia}] Opinion:
\begin{enumerate}
\item \label{lowvnn} adopt a rather high-level approach and map
existing back-ends to it, Object I/O level would be OK
\item Haskell should have free GUI back-ends (i.e.~not Qt)
\item \label{scratchvnn} design the standard API from scratch and
implement it with what is already there (e.g. the Gtk bindings)
\item ...but independent of the specific GUI back-ends
\item create the interface between the back-ends and the common API
in Haskell
\item \label{lookwnn} native look and feel is important
\end{enumerate}
Proposals:
\begin{enumerate}
\item \label{docvnn} adopt an existing XML model as API or for parts
of it
\end{enumerate}
\item[\Party{Bryn Keller}] Opinion:
\begin{enumerate}
\item \label{feelbk} Gtk is no good on Windows (at least version 1)
\item Qt and wxWindows would be alright on Windows
\end{enumerate}
\item[\Party{Sengan Baring-Gould}] Opinion:
\begin{enumerate}
\item \label{highsbg} no working high-level approach available
\item \label{lowsbg} it's painful to work with the low-level veneers
\item \label{midsbg}wants a medium level approach like Object I/O
\item SWT uses a C layer which emulates widgets which the native
platform does not support, but it is possible to write platform
specific bits. Adopt similar technique for the common API.
\item don't use the C SWT layer directly, it's too thin
\item \label{dirtysbg} don't be afraid to emulate widgets if the
platform does not provide them
\end{enumerate}
\item[\Party{Krasimir Angelov}] Opinion:
\begin{enumerate}
\item \label{lookka} want native look and feel
\item \label{dirtyka} ...but states how features not found on a
specific platform can be emulated and that it's OK to do so
\item \label{portka} Haskell's Object I/O library is too Windows
specific as it is (example: Scrollbars), furthermore there are
open design decisions (creation of identifiers, legacy Clean
communication model)
\item Standard GUI library needs different back-ends
\item \label{lowka} want low-level common API
\end{enumerate}
\item[\Party{Axel Simon}] Opinion:
\begin{enumerate}
\item \label{hinderas} want full-featured GUI capabilities
\item \label{allas} want portability (run everywhere)
\item don't want to reinvent the wheel in Haskell
\item want a standard GUI API soon
\item \label{scratchas} look at all back-ends before starting to define
an API that interfaces to them
\end{enumerate}
Proposal:
\begin{enumerate}
\item \label{lowas} write a mid-level common API to which people can attach
back-ends (based on Object I/O or GIO)
\end{enumerate}
\item[\Party{Adrian Hey}] Opinion:
\begin{enumerate}
\item Qt and wxWindows are hard to bind due to their
implementation language (C++), especially memory management
\item \label{lookah} doubt the native look and feel claim of Qt and wxWindows
\item \label{allah} don't care about look and feel, portability (runs
everywhere) is important
\item implementing widget in Haskell gives a more stable
back-end than using toolkits
\item using an imperative toolkit shines through % 24 Jan 16:09
\item \label{highah}no high-level GUI library yet
\end{enumerate}
\item[\Party{Antony Courtney}] Opinion:
\begin{enumerate}
\item \label{highac} don't define a high-level GUI API
\end{enumerate}
\item[\Party{Glynn Clements}] Opinion:
\begin{enumerate}
\item \label{lookgc} feel is very important for users
\item opposes to write GUI code specific to the Haskell library
(emulate widgets)
\item using a native-widget library means less maintenance for the
Haskell API
\item a sole document-level API is too inflexible in practice
\item the common API has to model the menu bar issue of Aqua
\end{enumerate}
Proposal:
\begin{enumerate}
\item create a library using the native platforms while adhering to
the native look and feel
\end{enumerate}
\item[\Party{Seth Kurtzberg}] Opinion:
\begin{enumerate}
\item impractical to have native look and feel by
rewriting a GUI library
\item define a general API on top of existing toolkits
\item obeying the native look and feel is quite difficult to do in a
portable way
\item do a thorough discussion before implementing
\item \label{scratchsk} easier to define more abstract API from
simpler ones than matching back-ends to more abstract APIs % Jan 24 16:48
\item \label{hindersk} it is OK that the common API has reduced
functionality but then it must provide means to use the platform
specific back-ends
\end{enumerate}
\item[\Party{Peter Achten}] Opinion:
\begin{enumerate}
\item \label{lookpa} native look and feel is important
\item \label{portpa} Object I/O (either version) is portable by
design and it should be possible to attach any back-end
\item \label{highpa} non high-level GUI APIs in functional programming
languages are still better than writing in C
\end{enumerate}
\item[\Party{John Meacham}] Opinion:
\begin{enumerate}
\item \label{midjm} wants mid-level common API on top of existing bindings
\item \label{feeljm} points to an article
\verb+http://www.t4p.com/xplat.htm+ stating that there is no cross
platform API which delivers native look and feel
\end{enumerate}
\item[\Party{Wolfgang Thaller}] Opinion:
\begin{enumerate}
\item native look and feel is important (especially: Mac)
\item \label{feelwt} there is no cross platform GUI toolkit which
delivers native look and feel
\item \label{lookwt} there are special properties of Aqua (menu bar,
quit menu entry) that need to be enforced by the API
\item \label{interwt} have a subset API which gives the native look
and feel on all platforms
\end{enumerate}
\item[\Party{Simon Marlow}] Opinion:
\begin{enumerate}
\item \label{hindersm} need platform specific APIs for native look and feel
\item \label{intersm} want reduced common API for all platforms
\end{enumerate}
\item[\Party{Daan Leijen}] Opinion:
\begin{enumerate}
\item wants a layer L between a mid-level API (like Object I/O) and
the bare veneer, because would mean we could share the work for
the medium layer
\item \label{scratchdl} let an existing API evolve than define one
from scratch
\end{enumerate}
Proposal:
\begin{enumerate}
\item Ports as the low-level portable API
\end{enumerate}
\item[\Party{Dylan Thurston}] Opinion:
\begin{enumerate}
\item \label{hinderdt} ensure that the common API is extensible to the
native, platform-dependent functionality
\end{enumerate}
\end{enumerate}
\section{Objectives for a Common GUI API}
Having summarized this information I will now try to distill the
essence from it. Note that the references mentioned do not always
support the argument itself but rather the consequence.
\begin{description}
\item[Platform independence] The Common GUI API needs to run on all
platforms (\ref{allspj}, \ref{allds}, \ref{allas}, \ref{allah}).
\footnote{Let the word platform denote an operating system with a
specific native API or toolkit.}
\item[Look-and-Feel] The Common GUI API shall enable the user to
create GUIs which adhere to the native look and feel of the platform
and its local style guide (\ref{lookwj}, \ref{lookwnn},
\ref{lookka}, \ref{lookah}, \ref{lookgc}, \ref{lookpa},
\ref{lookwt}). We cannot achieve native look-and-feel by using a
single cross-platform back-end (e.g. wxWindows) because adhering to
the local style guide has semantic implications that cannot be
abstracted away and which have to be addressed differently on each
platform (\ref{feelbk}, \ref{feeljm}, \ref{feelwt}). There is no
compromise between strictly adhering to native look-and-feel and
forcing a look-and-feel onto alien platforms. We opt for the former
because it can subsume the second (portability-only) approach
(\ref{dirtysbg}, \ref{dirtyka}).
\item[Extensibility] The common GUI library may not hinder the use of
native, non-portable functionality (\ref{hinderspj}, \ref{hinderas},
\ref{hindersk}, \ref{hindersm}, \ref{hinderdt}).
\item[Abstraction level] The Common GUI API will have a
medium\footnote{The notion medium here is meant to be the definition
from the Haskell web page, thus it refers to the language level:
imperative versus functional.} level API as its interface to the
user of the API (\ref{midsbg}, \ref{midjm}). It is not clear how a
high-level layer shall look like, thus defining one is not our goal
(\ref{highspj}, \ref{highsbg}, \ref{highah}, \ref{highac},
\ref{highpa}). A common low level veneer is doomed to become
platform specific and thus difficult to find (\ref{lowwj},
\ref{lowvnn}, \ref{lowsbg}, \ref{lowas}, opposition: \ref{lowka}).
\item[Intersection Approach] A portable API is a kind of intersection
of all its back-ends (\ref{interspj}, \ref{interkw}, \ref{interwt},
\ref{intersm}). Thus practical portability can only be achieved by
designing the API with all back-ends in mind (\ref{portka},
opposition: \ref{portpa}). We therefore have to restrict the set of
target platforms. The community has interest in bindings to these
platforms (and no more at this time):
\begin{itemize}
\item Win32
\item Aqua (Mac OS X environment)
\item Gtk (Gnome)
\item Qt (KDE)
\item wxWindows
\end{itemize}
\item[Evolutionary vs. Agreement Approach] There has been a debate on
how to define the Common API. On the one hand we can take an
existing set of functions (from either GIO, Object I/O, Yahu) and
change them with each mismatch we find when we implement the
functions on other back-ends (\ref{scratchspj}, \ref{scratchsk},
\ref{scratchdl}). On the other hand, we could start with a blank
sheet and scrutinize all functions which we add to the specification
(\ref{scratchvnn}, \ref{scratchas}). There is no clear consensus
here, but at least the core infrastructure (e.g. whether to have
\verb+set+ and \verb+get+ functions) probably has to be agreed upon.
Maybe the distinction is more blurred in practice anyway so that we
don't need a clear vote.
\item[non-goals] Due to the lack of enthusiasm, I assume these
proposals are overruled: Create a common API that can be used by
other languages as well (\ref{langwj}), use a document interface to
talk to the GUI (\ref{docvnn}).
\end{description}
\noindent I think this subsumes Simon Peyton-Jones summary from February 12th.
\section{Mission statement}
\subsection{Terminology}
The following terms are used throughout this document:
\begin{description}
\item[Common GUI API] The project name as well as the outcome of this
undertaking: A specification of an interface for GUI programming.
\item[back-end] A collection of GUI functions with which the Common GUI
API is implemented. A back-end can be (but does not have to be) tied
to one platform. Synonym: toolkit
\item[platform] One of Win32 (native back-end: Win32), Mac OS X
(native back-end: Aqua), Gnome (native back-end: Gtk), KDE (native
back-end: Qt). A platform has a native look-and-feel.
\item[look-and-feel] A set of layout conventions and semantics of a
GUI. The look-and-feel is tied to a particular platform. It is
usually defined in a Style Guide of that platform.
\item[widget] A user interface element. A button is an example for this.
\end{description}
The GUI task force agrees to the following design choices:
\subsection{Aim}
The goal of this project is to define an application program interface
(API) which enables a Haskell programmer to write applications with a
GUI in a portable, native-looking way.
\subsection{Subset approach}
The API will expose as many GUI elements from the different back-ends
as possible. GUIs expressed with the Common API shall have the native
look-and-feel of the platform the application runs on. Functionality
that cannot be implemented this way on all platforms shall not be
covered in this API. Specifically, platform dependent programs
(e.g.~Control Panel applications under Windows) will not be covered by
this API (but may well be possible to implement with the specific
back-end). Services that are not covered in the Style Guide of a
particular platform (e.g.~internationalization, localization, sound,
persistent configuration) shall use the native conventions only if
feasible.
\subsection{Extensibility}
Additional functionality that cannot be expressed with the native
look-and-feel can and should be provided by the different back-ends.
The Common API may not hinder these extensions.
\subsection{Structure}
The Common GUI API shall be a pure specification. It provides the
definition of a \emph{core} which describes an infrastructure to
modify stateful object. The \emph{functionality} of the API will be
accessible through this core. Different \emph{back-ends} will exhibit
additional functionality through the same core.
\subsection{The Core}
The core comprises the infrastructure with which GUI applications are
written. It will specify how attributes of objects are set and queried
and how to associate different objects with each other. The core has
to define how call-backs are handled.
\subsection{Coverage}
Within this project we will try to find common abstractions for
different aspects of GUIs and interfaces to the user in general. The
following list shall neither be exhaustive nor mandatory. More
important topics are listed first.
\begin{enumerate}
\item An application framework with menus, possible with different
complexity levels (single document interface (SDI) and multiple
document interface (MDI)).
\item A set of standard widgets.
\item A layout mechanism which abstracts away static and dynamic
arrangement of widgets.
\item A set of common dialogs.
\item Primitive drawing functionality on a canvas.
\item Configuration reading and writing, internationalization.
\item OpenGL rendering.
\item Invisible canvas and the ability to print it.
\item Sound support.
\end{enumerate}
\subsection{Back-ends}
The parties that are interested in providing an implementation to a
specific back-end are expected to contribute in the finding of this
specification. It is their duty to ensure that the agreed
specification can be implemented with the platform's native
look-and-feel on top of their particular back-end. The Common GUI API
shall be implemented on top of the back-ends given in Table
\ref{fig-backends}. The platform columns show on which platforms the
back-end is expected to deliver the native look-and-feel. Note that
this does not preclude other back-ends from running on platforms not
listed (e.g.~Gtk and Qt both run on Windows). As long as we have not
started to put forth any GUI functionality, we welcome people to
propose other back-ends and even platforms. To ensure progress, we
cannot alter functionality marked as stable for platforms added later
in the process.
\begin{table}
\begin{center}
\begin{tabular}{|l||c|c|c|c|c|}\hline
& \multicolumn{5}{c|}{Platforms}\\
Back-end & Win32 & Mac OS X & X11/Xt & KDE & Gnome \\ \hline
Win32 & X & & & &\\
Aqua & & X & & &\\
Athena & & & X & &\\
Motif & & & X & & \\
Qt+KDE extensions & & & & X & \\
Gtk+Gnome extensions & & & & & X \\
HToolkit & X & & & & X \\
wxWindows & X & X & & & X \\ \hline
\end{tabular}
\end{center}
\caption{\label{fig-backends} Targeted back-ends and their platforms}
\end{table}
\subsection{Target audience}
The API shall be expressive enough to enable professionals to write
GUI application. Although the Common API is restricted in the number
of GUI components to what is available on all platforms, the
functionality of the provided components shall be as exhaustive as
achievable. Simpler layers on top of the Common API for educational
purposes should not be hindered, but such a layer is not part of this
project. A user should be comfortable writing larger applications using
the Common GUI API without feeling the need to introduce new
abstraction layers. However, we shall not hinder high-level
abstractions if possible.
\subsection{Implementation language}
The definition of the Common API shall mainly be written in Haskell
98. Language extensions shall only be used when they seem sensible. We
will make use of hierarchical module names.
\section{The user's perspective}
A potential user who wants to write a GUI application might find
our approach confusing. These are guidelines we will give:
\begin{itemize}
\item If the extend of the application is rather small, the user might
find all necessary functionality in the specification of the Common
GUI API. In this case, (s)he can use any back-end to compile her/his
application and expect the native look-and-feel of the
platform. Ideally, even different back-ends for a certain platform
will create the same look and behavior.
\item Writing an application which cannot be expressed with the Common
GUI API alone will present the user with a set of choices which
imply different trade-offs between effort and professionality:
\begin{itemize}
\item If discrepancies in look-and-feel is not a big issue, the user
would choose a back-end like wxWindows which runs on all
platforms. This back-end might not give access to all functions
available on the different platforms and might introduce back-end
specific look-and-feel as a compromise between the platforms. The
big advantage is that no platform specific code has to be written.
\item If the user is only interested in the Gnome and Windows
platforms, HToolkit as back-end will give a native look-and-feel
for both of them without any code change. The expressiveness of
HToolkit is only slightly reduced since both platforms are quite
similar.
\item If the application is very demanding in terms of user
interface, a native back-end must be used. (Gtk and Qt have the
advantage that they run on other platforms which might be useful
for demonstrating.) In the long run, parts of the application
which are not implemented with the Common GUI API have to be
reimplemented for each native back-end. The result, however, will
be an application that feels native. All this is achieved with a
minimum of porting effort.
\end{itemize}
\end{itemize}
\section{Technical Discussion}
\subsection{Core functionality}
The term core functionality refers to the general problem of
connecting to a concurrent library with bidirectional flow of
control. The following orthogonal topics were discussed:
\subsubsection{Creation of Objects}
There are two techniques to create objects: One uses constructor functions as imperative object-oriented languages would do, the other one has a dedicated creation function which takes a description of the GUI as an algebraic data type.
\begin{enumerate}
\item Constructor Functions (e.g.: GIO, most low-level veneers)
\begin{enumerate}
\item (Daan) bad: not a first-class description
\item (Daan) bad: identification values only become available after creation
\item (Daan) good: only need actions to modify object's properties,
Object I/O needs constructors for all properties as well
\item (Daan) good: passing the parent to non-toplevel widgets during
construction is a way to prevent widgets from being inserted into
two hierarchies
\end{enumerate}
\item Generation of GUI through data type (e.g.: Object I/O)
\begin{enumerate}
\item (Daan) bad: easy to forget to associate an id value with an object
\item (Peter) bad: more type safety make this approach very complex
(e.g.~typed identifiers)
\item (Peter) good: setup using IDs is symmetric (i.e.~create
objects and IDs separately)
\item (Axel) good: checking for invalid layout is easier due to the
centralized creation function, alleviation (Krasimir): make each
non-toplevel widget take its parent as a mandatory argument (see
Section \ref{secParentAsParameter}).
\end{enumerate}
\end{enumerate}
\subsubsection{Configuration of Objects}
For convenience the user should be able to set properties of an object
when it is created. It is obvious that properties must be changeable
later on. (It might be less obvious that some properties may
only be specified at creation time and are to be considered constant.)
An example of how this might look like was given by Daan:
\begin{verbatim}
data Attr w a = Attr (w -> IO a) (w -> a -> IO ()) -- getter and setter
data Prop w = forall a. (:=) (Attr w a) a -- := is a constructor
set :: w -> [Prop w] -> IO ()
set w props
= mapM_ setProp props
where
setProp ((Attr getter setter) := x)
= setter w x
get :: w -> Attr w a -> IO a
get w (Attr getter setter)
= getter w
-- example of an attribute, works for any kind of (wxWindows) Frame
title :: Attr (Frame a) String
title
= Attr (\w -> w # frameGetTitle)
(\w x -> w # frameSetTitle x)
...
gui = do ...
set frame [title := "hi there"]
\end{verbatim}
Note that this particular approach is unlikely to be taken as it
involves existential types and a constructor which might become a
keyword in future versions of Haskell.
Another (slightly incomplete) example by Krasimir:
\begin{verbatim}
data Point = Point {x :: Int, y :: Int}
attrX :: StateAttr Point Int
attrX = StateAttr x (\v p -> p{x=v})
attrY :: StateAttr Point Int
attrY = StateAttr y (\v p -> p{y=v})
move :: Int -> Int -> State Point Int
move vx vy = do
x <- get attrX
attrX =: x+vx
y <- get attrY
attrY =: y+vy
\end{verbatim}
Sven suggested to define some more general set/get functionality,
maybe adding it to MonadState. Was there actually any discussion on
the library list?
Glynn would like to have a single create function for all widgets. He
admits that this leads to ambiguity when the result is not passed to a
function which expects a specific widget type.
Glynn: From Xt: Widgets should have names to change their attributes
from outside (resource files).
David votes to use a (the) GIO/Object IO style. I think we all agree
that we would like to have something slightly more abstract than
simple IO functions like gtk+hs, gtk2hs, wxhaskell, etc. offer (we all
agreed that CGA should be on a medium abstraction level).
Vincenzo welcomes comments on extending the GIO approach with standard
IO functions that don't take the attribute list (in case default
values apply for every attribute).
Summing up the conversation about the set and get functions, I posted
the following proposal.
\begin{verbatim}
-- An attribute is a property of a widget. It knows how to set the
-- and how to read the value of this property.
data WidgetClass w => Attr a w = <abstract>
-- The assignment operator joins an attribute with its value.
(=:) :: a -> Attr a w -> Setter w
-- Set and get can be used on every widget.
set :: WidgetClass w => w -> [Setter w] -> IO ()
get :: WidgetClass w => w -> Attr a w -> IO a
-- An example for a Button widget: The constructor has one
-- mandatory argument.
newButton :: Container -> [Setter Button] -> IO Button
-- The Button has at least this attribute.
label :: Attr String Button
-- This is one callback the Button provides. Note that you cannot
-- attach any function at construction time or with the set
-- function. The returned action is the unregister function.
onClicked :: ButtonClass b => b -> IO () -> IO (IO ())
\end{verbatim}
\subsubsection{\label{secParentAsParameter} Composition of Objects
(Layout)}
This topic did not receive much attention yet. But Krasimir mentioned
this and Glynn later wrote how layout is captured in Xt programming,
which captures the same idea: Each non-top-level widget has to specify
its parent at creation time. This seems to be the only approach that
enforces one widget to have at most one parent (like Object I/O's
widget tree description via an algebraic data type) and a unique
identification (the value returned from the create-function like in
GIO).
\subsubsection{Events versus Callbacks}
Quickly skimming the whole discussion about events and callbacks, it
seems that
\begin{itemize}
\item callbacks are close to most GUI libraries
\item events can be implemented on top of callbacks
\end{itemize}
As such, the essence of the discussion was that the event view may be
implemented on top of callbacks (hopefully via an additional library).
Vincenzo should interfere if something is added to the CGA which makes
stream based models of data flow difficult.
\subsection{Menu Bars}
\begin{enumerate}
\item Each application has exactly one menu bar.
\rationale{ This constraint stems from Aqua. It is not as radical as
it might seem at first since it is required by the Windows Style
Guide as well. Allowing an application which consists of a single
dialog violates the Style Guide of Windows, it is impossible under
Aqua. As such it should not be a severe restriction. }
Note that there are plug-in like applications which are part of a
bigger application (e.g. Control Panel under Windows, System
Preferences under Aqua, install wizards under Windows). These are
system dependent and thus not covered by the Common API.
\item The following menus are automatically added to menu bar: File
(always), Edit (only on Windows and Unix if a Preferences dialog is
specified), Help (only on Windows and Unix if an About dialog is
specified)
\rationale{ The reason for these requirements are the menu entries
Quit, Preferences and About which are located under the application
menu under Aqua. }
\item Each application has an entry to terminate the program.