• No results found

Generic Graphical User Interfaces

N/A
N/A
Protected

Academic year: 2021

Share "Generic Graphical User Interfaces"

Copied!
17
0
0

Loading.... (view fulltext now)

Full text

(1)

PDF hosted at the Radboud Repository of the Radboud University

Nijmegen

The following full text is an author's version which may differ from the publisher's version.

For additional information about this publication click this link.

http://hdl.handle.net/2066/60466

Please be advised that this information was generated on 2017-12-06 and may be subject to

change.

(2)

Generic Graphical User Interfaces

P e te r A chten, M arko van Eekelen, an d R inus P lasm eijer

D epartm ent of Software Technology, University of Nijmegen, The Netherlands p eter8 8 @ cs.k u n .n l, m arko@ cs.kun.nl, rin u s@ cs.k u n .n l

A b s tr a c t. It is im portant to be able to program GUI applications in a fast and easy manner. Current GUI tools for creating visually attractive applications offer limited functionality. In this paper we introduce a new, easy to use method to program GUI applications in a pure functional language such as Clean or Generic Haskell. The method we use is a refined version of the model-view paradigm.

The basic component in our approach is the Graphical Editor Component (G E Ct ) th a t can contain any value of any flat data type t and th a t can be freely used to display and edit its value. G E Ct s can depend on others, but also on themselves. They can even be mutually dependent. W ith these components we can construct a flexible, reusable and customizable editor. For the realization of the components we had to invent a new generic implementation technique for interactive applications.

1

In tr o d u c tio n

M aking an a ttra c tiv e G rap h ical U ser Interface (GUI) for an ap p lic atio n is n o t an easy task . O ne can of course use th e GUI lib ra ry offered by th e o p eratin g system (Windows, Mac, Linux). T hese GUI libraries are pow erful (th e y d eterm in e w h at is possible on a p a rtic u la r O S), b u t th e offered level of a b stra c tio n is in general ra th e r low. T herefore, m ost people will prefer to use a visual ed ito r as offered by m a n y com m ercial p rogram m ing environm ents. Such tools are very user friendly a t th e expense of offering lim ited functionality. O ne still has to com bine th e graphical elem ents m ade w ith th e visual ed ito r w ith th e p ro g ram code for h an d lin g th e a c tu al GUI events. Inherently, graphical rep resen ta tio n s th a t d e p en d on ru n -tim e d a ta can n o t b e draw n in advance. Sum m arizing, a visual e d ito r is a good tool for c e rtain sim ple GUI applications, b u t for m ore com plicated ones one still has to struggle w ith low level p rogram m ing code.

For dealing w ith m ore com plicated ap p licatio n s in a sim pler way, we w ant to define GUIs on a higher level of ab stra c tio n . M odern, pu re functional p ro g ram ­ m ing languages enable th e definition an d c o n stru c tio n of high a b stra c tio n levels. T he Object I/O lib ra ry [1] is p ro b a b ly th e largest GUI lib ra ry available for pure functional languages. GUI ap plications can be defined in Object I/O in a p la t­ form in d ep en d en t way. T he Object I/O lib ra ry has been defined in Clean an d is cu rre n tly available for Windows an d MacOSX. A subset has been p o rte d to Linux [11]. Object I/O has been p o rte d to Haskell by P e te r A chten an d Sim on P ey to n Jones [2] an d K rasim ir Angelov [4]. Recently, it has becom e possible to com bine

(3)

Haskell program s w ith Clean p ro g ram s [12,10]. Hence, in various ways Object I/O is now adays available for a large co m m unity of pu re functional program m ers.

In Clean, im pressive GUI ap plications have been m ade using Object I/O: e.g. th e Clean ID E (including a te x t ed ito r an d a p ro je c t m an ag er), 2D -platform gam es, an d th e p ro o f a ssistan t Sparkle. T he la tte r ap p licatio n in p a rtic u la r d em o n stra te s th e expressive pow er of Object I/O .

We have experienced th a t GUI elem ents such as dialogs, m enus, an d sim ple windows are relativ ely easy to define on a high level of ab stra c tio n . A n applica­ tio n like th e p ro o f a ssistan t Sparkle requires m uch m ore knowledge of th e Object I/O prim itives. In Sparkle [9], an action in one w indow (e.g. th e com pletion of th e p ro o f of a theorem ) has m an y consequences for th e in fo rm atio n displayed in th e o th er window s (e.g. th e list of com pleted th eo rem s). Sparkle in th is respect resem bles th e behavior of ap p licatio n s th a t are m ade w ith th e well-known m o d el­ view p arad ig m [18]. T he m essage passing prim itives of Object I/O can handle such a com plicated in fo rm atio n flow. However, th e learning curve to p ro g ram such com plicated m u tu a l influences is ra th e r steep.

Clearly, we need b e tte r tools to c o n stru c t GUI ap p licatio n s on a high level of ab stra c tio n . However, we require th a t th ese tools are n o t as restrictiv e as s ta n ­ d a rd GUI builders. F u rth erm o re, we w ant to be able to c reate GUI ap plications in a versatile way. O n th e one h a n d it m u st be easy to com bine s ta n d a rd com ­ p o n en ts and on th e o th er h a n d these co m ponents should be easily custom ized to a d a p t to our wishes.

In th is p a p e r we fulfill th is need by in tro d u cin g a new way for c o n stru ctin g GUI elem ents th a t resp o n d to th e change of o th e r GUI elem ents. P ro p e r cus­ to m iza tio n requires a rigid se p a ratio n of value versus visualization, an d has lead to a refined version of th e m odel-view p arad ig m (b u t n o te th a t a t th is m om ent only one view is su p p o rte d ). T he basic idea is th e concept of a G raphical E d ito r C om ponent (a G E CT) w ith w hich one can display an d ed it values of a n y fla t1 ty p e t . A ny change in a value is d irectly passed to all o th e r G E Cs th a t d epend on th e changed value. U sing generic pro g ram m in g techniques, a G E C T for a con­ crete (user defined) ty p e t can be g en erated au tom atically. A p a rt from defining th e d a ta ty p e an d c u sto m izatio n definitions alm ost no ad d itio n al p rogram m ing effort is needed. For ap p licatio n s in w hich th e p a rtic u la r look is less of an issue, it is even sufficient to provide only th e d a ta ty p e. T his m akes it an excellent to o l for

rapid p ro to ty p in g . All low level com m unication th a t is req u ired to accom plish th e in fo rm atio n flow betw een th e graphical elem ents, is ta k e n care of by th e system . T he proposed technique is u n iv ersa l, cu sto m iza b le an d co m p o sitio n a l. M oreover, it is a novel ap p licatio n of generic pro g ram m in g [13, 8].

In Sect. 2 we p resen t th e basic idea of a G E CT. Sect. 3 shows how these

G E Ct s can be com bined to c o n stru c t m ore com plicated GUIs. In Sect. 4 we re­ veal how a G E Ct is im plem ented using generic pro g ram m in g techniques. Sect. 5 explains how a G E C T can be custom ized to display its com ponents in an a lte rn a ­ tive way. T h ere after, we will discuss re lated work. Finally, we draw conclusions and p o in t o u t fu tu re work.

(4)

2

T h e c o n c e p t o f a G ra p h ica l E d ito r C o m p o n e n t

We w ant to b e able to m ake com plicated GUI ap p licatio n s w ith m inim al p ro g ram ­ m ing effort. T h e basic building block of our m e th o d is a custom izable G raphical E d ito r C om ponent ( G E CT), w hich we can g en erate a u to m a tic a lly for an y flat ty p e t . M ore precisely, a G E C T is a g en erate d function th a t contains a value of ty p e t and creates a visual com ponent th a t:

1. can be used by a p ro g ram m er to a u to m a tic a lly display a n y value of ty p e t ; 2. can be used by th e ap p licatio n user to view and ed it a value of ty p e t ;

3. can be custom ized by a p ro g ram m er such th a t its elem ents can be displayed in an alte rn a tiv e way;

4. can com m unicate any value change m ade by th e user or by th e p ro g ram to any o th e r com ponent th a t d epends on th a t change.

It is im p o rta n t to n o te th a t a G E C T is a very general com ponent: in languages such as Clean an d Haskell, every expression re p resen ts a value of a c e rta in type. Since a G E C T can display any value of ty p e t, it can also b e used to display any o b ject (expression) of th a t ty p e. E ach G E C T is com pletely tailo red to its ty p e

t. It g u aran tees th a t each value ed ited is w ell-typed.

2.1

Interactive functional program m ing

Before continuing, we have to m ake a few rem ark s for people unfam iliar w ith functions th a t perform I /O in Clean. (G eneric pro g ram m in g in Clean is explained in Sect. 4.1.) Object I/O uses an explicit environm ent passing style [1] su p p o rte d by th e uniqueness ty p e system [5] of Clean. C onsequently, any function th a t does som ething w ith I /O (like mkGEC in Sect. 2.2) is an explicit s ta te tra n sitio n function w orking on a p ro g ram s ta te (P S t s t ) re tu rn in g a t least a new pro­ g ram s ta te . (In th is p a p e r th e identifier env will be a value of th is ty p e.) T he uniqueness ty p e system of Clean will ensure single th re a d e d use of such a sta te . In th e Haskell v arian t of Object I/O , a s ta te m o n ad is used in stead . U niqueness ty p e a ttrib u te s th a t a c tu ally ap p e a r in th e ty p e sig n atu res are n o t show n in th is p ap er, in o rd er to sim plify th e p resen tatio n .

2.2

C reating G E C Ts

In th is section we explain in general te rm s w h a t th e generic function to create

G E Cts, mkGEC, does. In th e n e x t section we will show how mkGEC can b e used to connect different G E C Ts.

In o rd er to cre ate a G E C T one only has to a p p ly th e generic function mkGEC w hich has th e following type:

g e n e ric mkGEC t :: [GECAttribute] t (C allB ackFunction t (PSt p s )) (PSt ps) -> 2 (GEC t (PSt p s ) , PSt ps) 2 The Clean type a b -> c is equivalent to the Haskell type a -> b -> c.

(5)

CallBackFunction t env :== t -> env -> env

Hence, in o rd er to call mkGEC th e following arg u m en ts have to be provided:

— a G E C A ttrib u te list controlling behavioral aspects. In th is p a p e r we restric t it to tw o d a ta co n stru cto rs: O u tp u tO n ly and B elow Prev,

— an in itial value of ty p e t ,

— a call-back function defined by th e p ro g ram m er th a t will be called a u to m a t­ ically each tim e th e value of ty p e t is ed ited by th e user or by th e program , — th e c u rre n t unique s ta te of th e program .

T he function mkGEC re tu rn s

— a record (GEC) containing m eth o d s th a t can be used to h andle th e new ly cre a te d G E C t com ponent for ty p e t , and

— th e new unique p ro g ram s ta te (as usual for I /O h an d lin g functions in Clean).

:: GEC t env = { gecGetValue :: env -> (t,e n v ) , gecSetV alue :: t -> env -> env }

T he GEC record th a t is re tu rn e d contains several o th e r useful m e th o d s for a p ro g ram th a t are n o t show n above. T hese are m eth o d s to open an d close th e cre­ ate d G E C T or to show or hide its ap p earan ce. For ap p licatio n pro g ram m ers th e m eth o d s g e c G e tV a lu e and g e c S e tV a lu e are th e m ost in terestin g . T he m eth o d g e c G etV a lu e can be used to o b ta in from th e G E C T com ponent th e cu rre n tly sto red value of ty p e t. T he m e th o d g e c S e tV a lu e can b e used to s e t a new value in th e corresponding G E CT.

W h en th e user of th e ap p licatio n changes th e co n ten t of a G E CT, th e cor­ responding call-back function will be a u to m a tic a lly called w ith th e new value. T his call-back function can be used to store new values in o th e r G E CTs using th e g e c S e tV a lu e m e th o d of these G E CTs as will be d e m o n stra te d in Sect. 3.

T he ap p ea ran ce of a s ta n d a rd G E C T is illu stra te d by th e following exam ple. A ssum e th a t th e p ro g ram m er has defined th e ty p e T re e a as show n below and consider th e following ap p lic atio n of mkGEC:

:: Tree a = Node (Tree a) a (Tree a) | Leaf

mkGEC [] (Node Leaf 1 Leaf) i d e n t i t y 3 env

T his defines a w indow co ntaining th e G E C Tree Int displaying th e in d icated initial value (see Fig. 1). T he ap p licatio n user can ed it th is in itial value in any desired order th u s p ro d u cin g new values of ty p e T re e I n t . E ach tim e a new value is c reated , th e call-back function i d e n t i t y is called au tom atically. In th is exam ple th is has no effect (b u t see Sect. 3). T he shape an d lay-out of th e tree

(6)

I E T re e ■- - M i |Node w 1 ¡Node _^J (Leaf

|l_eaf z l h

j Leaf “ 3

F i g . 1. The initial Graphical Editor Component for a tree of integers (Left) and a changed one (Right: with the pull-down menu the upper Leaf is changed into a Node).

being displayed ad ju sts itself au tom atically. D efault values are m ade u p by th e ed ito r w hen needed.

N otice th a t a G E C T is stro n g ly ty p ed . O nly w ell-typed values of ty p e t can

be created w ith a G E CT. T herefore, w ith a G E C Tree Int th e user can only create values of ty p e T re e I n t . If th e user m akes a m istake, for in stan ce by ty p in g an a rb itra ry strin g in to th e integer box, th e previous displayed integer value is restored. A ny create d e d ito r also includes m an y o th e r features for free, such as: a u to m a tic scroll facilities, an a u to m a tic h in t box showing th e ty p e of any displayed item , an d th e o p tio n to hide and show any p a r t of a d a ta stru c tu re . All of th is is g en erated com pletely given a ty p e t .

3

C o m b in in g G ra p h ica l E d ito r C o m p o n e n ts

In th is section we will give som e sm all exam ples how G E CTs can b e com bined. A sim ple com bination schem e is th e following. If one G E C T B d epends on a change m ade in a G E C a A , th e n one can pass G E C T B to th e call-back function of A .

E ach tim e A is changed, its call-back function is called a u to m a tic a lly an d as a reactio n it can set a new value in B by applying a function of ty p e a ^ t. Below,

conform th is scheme, tw o such G E CTs are cre a te d in th e function apply2GECs such th a t th e call-back function of GEC_A em ploys GEC_B.

apply2GECs :: (a -> b) a (PSt ps) -> (PSt ps) apply2GECs f va env

#4 (GEC_B, env) = mkGEC [] (f va) id e n t i t y env # (GEC_A, env) = mkGEC [OutputOnly,BelowPrev] va ( s e t GEC_B f) env = env

s e t 5 :: (GEC b (PSt p s )) (a -> b) a (PSt ps) -> (PSt ps) s e t gec f nva env = gec.gecSetV alue ( f nva) env

3 In several examples i d e n t i t y will be used as a synonym for const id.

4 The #-notation of Clean has a special scope rule such th a t the same vari­ able name can be used for subsequent non-recursive #-definitions.

(7)

W ith these definitions, apply2GECs to B a la n c e d T re e [ 1 , 5 , 2 , 8 , 3 , 9 ] env, resu lts in tw o G E C Ts. O ne for a [ I n t ] , an d one for a T re e I n t . A ssum ing th a t to B a la n c e d T r e e is a function th a t tra n sfo rm s a list in to a balan ced tree, any change m ade by th e user to th e displayed lis t6 will a u to m a tic a lly result in to a corresponding re-balanced tree being displayed (see Fig. 2). In o rd er to em phasize th e functional depen d en cy of th e tre e editor, it can n o t be ed ited by th e user (controlled by th e G E C A ttrib u te O u tp u tO n ly .)

Node Node Leaf

5

9

Leaf 8 Leaf

Node Node Leaf

2 3 Leaf Leaf •i Leaf |_Cons d i ' |_Cons 3 |2 |_Cons 3 [3 |_Cons (9 [Si 3

F ig. 2. A window th a t contains a non-editable G E C Tiee int which shows the effect of applying the function toB alancedTree after any user editing performed on GEC[Int].

As th is exam ple d e m o n strates, com bining G E CTs is very easy. O ne G E C T

can have an effect on a rb itra ry m an y G E CTs including itself! C onsider: selfGEC :: (a -> a) a (PSt ps) -> (PSt ps)

selfGEC f va env = new_env

where7 (thisGEC,new_env) = mkGEC [] ( f va) ( s e t thisGEC f ) env

Initially, th is function displays th e effect of applying a given function f to a given value v a of ty p e a. A ny change a user m akes using th e ed ito r a u to m atically causes a re-evaluation of f to th e new value th u s created . C onsequently, f has to be a function of ty p e a ^ a. For exam ple, one can use selfG E C to display and ed it a balan ced tree. Now, each tim e th e tre e is edited, it will re-balance itself.

H B a la n ce d T

6 A Clean list is internally represented with the constructors _Nil and _Cons. 7 The #-notation can not be used here since the definition of selfGEC is recursive.

(8)

N otice th a t, due to th e explicit environm ent passing style, it is triv ia l in Clean to connect a G E C T to itself. In Haskell’s m onadic I /O one needs to tie th e knot w ith f ix I O .

In a sim ilar w ay one can define m u tu a lly d ep en d en t G E C Ts. Take th e fol­ lowing definition of mutualGEC.

mutualGEC :: a (a -> b) (b -> a) (PSt ps) -> (PSt ps) mutualGEC va a2b b2a env = env2

where (GEC_B,env1) = mkGEC [] (a2b va) ( s e t GEC_A b2a) env (GEC_A,env2) = mkGEC [BelowPrev] va ( s e t GEC_B a2b) env1

T his function displays tw o G E C Ts. It is given an in itial value v a of ty p e a, a function a2b : : a ^ b, an d a function b 2 a :: b ^ a. T he GEC A ini­ tia lly displays va, while GEC B in itia lly displays a2b va. E ach tim e one of th e

G E C Ts is changed, th e o th e r will be u p d a te d autom atically. T he order in which changes are m ade is irrelevant. For exam ple, th e ap p licatio n mutualGEC { e u ro s = 3 .5 } to P o u n d s to E u r o s will resu lt in an ed ito r th a t calculates th e exchange betw een p o u n d s an d euros (see Fig. 3) an d vice versa.

exchangerate = 1.4

:: Pounds = {pounds :: Real} :: Euros = {euros :: Real} toPounds :: Euros -> Pounds

toPounds {euros} = {pounds = euros / exchangerate}

toEuros :: Pounds -> Euros

toEuros {pounds} = {euros = pounds * exchangerate}

F ig. 3. M utually dependent G E C Pounds and G E C Euros in one window.

T he exam ple of Fig. 3 m ay look a b it like a tin y sp read sh eet, b u t it is es­ sentially different since s ta n d a rd sp read sh eets d o n ’t allow m u tu a l dependencies betw een cells. N otice also th e se p a ra tio n of concerns: th e w ay G E CTs are coupled is defined com pletely se p a ra te from th e a c tu al functionality.

4

Im p le m e n ta tio n D e sig n o f

G E C

s

A lthough th e im p lem e n tatio n of th e system is n o t very big (1800 loc for th e im p le m e n tatio n m odules, including com m ents an d tra c in g sta te m e n ts) it is n o t possible to describe all relevant im p lem en ta tio n aspects in th is p ap er. We restric t ourselves to th e key aspects of th e design.

(9)

4.1

G eneric Functions

Recently, generic functions have been ad d e d to Clean [3]. A generic function is an u ltim a te reusable function th a t allows reflection on th e stru c tu re of any d a ta in a ty p e safe way. It is n o t a single function, b u t a c tu ally a special kind of overloaded function. O ne m ight be te m p te d by th e idea to design som e su itab le universal ty p e, an d define generic functions on values of th is ty p e, an d convert th e changed value back to th e ac tu a l ty p e. However, it is a fu n d am en tal p ro p e rty of th e language th a t (w ith o u t some kin d of reflection) th e re can n o t exist a single universal ty p e w ith w hich values of any ty p e can be represented.

In stead , th e ty p es used by generic function definitions ap p ro x im ate th e u n i­ versal ty p e idea. T h ey do n o t c o n stitu te a single ty p e b u t a fa m ily o f types. E ach concrete user defined ty p e is rep resen ted by a different com b in atio n of m em bers of th is generic ty p e family. Such a p a rtic u la r rep re se n ta tio n by itself has a ty p e th a t dep en d s on th e com b in atio n of values of th e generic ty p es th a t is used.

Hence, to define a generic function, in stan ces have to be defined for a finite n u m b er of types, th e g e n e ric types, o u t of w hich any value of any ty p e in th e language can be co n stru cted .

:: U nit = U nit

:: E ith e r a b = L e ft a | Right b :: P a ir a b = P a ir a b

:: TypeCons a = TypeCons InfoT a :: DataCons a = DataCons InfoC a

T he generic ty p es consist of th e basic ty p es (B ool, I n t , R e a l, . . . , which are used to rep resen t them selves), U n it (to rep resen t a zero a rity d a ta con­ s tru c to r), P a i r (p ro d u ct ty p e, used to com bine arg u m en ts of d a ta co n stru c ­ to rs), an d E i t h e r (th e sum ty p e to in d icate w hich d a ta c o n stru c to r of a certa in ty p e is used). F u rth erm o re, th ere are two special ad d itio n al ty p es TypeCons and D ataC ons. T h ey co n tain ad d itio n al in fo rm atio n (in In fo T an d In fo C ) a b o u t th e nam e a n d a rity of th e original ty p e an d d a ta co n stru cto rs. T h is is useful for m aking generic functions th a t can p arse or p rin t. We will need th e m to display th e values in our graphical editor.

W ith a collection of generic types, values of any user-defined ty p e can be rep ­ resented, e.g. [ 1 ] : : [ I n t ] is rep resen ted by TypeCons _ L is t ( L e f t (D ataC ons _Cons ( P a i r 1 (TypeCons _ L is t R ig h t (D ataC ons _N il U n i t ) ) ) ) ) , see also Fig. 4 on page 10.

O nce defined by th e p rogram m er, a generic function can be applied to values of any concrete (user defined) ty p e. T he com piler will a u to m a tic a lly ad d con­ version functions (b im a p s) th a t will tra n sfo rm th e concrete ty p e to th e corre­ sponding com b in atio n of generic types. F u rth erm o re, th e generic ty p es re tu rn e d by th e generic function are converted back again to th e ac tu a l ty p e dem anded.

In o rd er to be able to deal w ith (m u tu al) recursive types, it is v ita l th a t these tra n sfo rm a tio n s are done in a lazy way (see [14] and [3]).

G eneric functions are very useful for defining work of a general n a tu re . Be­ cause generic functions can be specialized for any specific concrete ty p e as well,

(10)

th e y can also be custom ized easily. So far, th e technique has been successfully used to define functions like equality, m ap, foldr, as well as for th e c o n stru ctio n of various p arsers an d p re tty p rin ters. Also, generic p rogram m ing techniques play an im p o rta n t role in th e im p lem en tatio n of a u to m a tic te s t system s [17]. T h e use of generic p rogram m ing techniques for th e c reatio n of GUI applications has to our know ledge never been done before.

4.2

C reating a G E C T w ith generic functions

A G E Ct com ponent basically is an in terac tiv e ed ito r for d a ta of ty p e t, which can b e e d ited in any order. A special p ro p e rty of such an ed ito r is th a t all d a ta elem ents have to be visualized and still have to be m odifiable as well.

For ou r kin d of in teractiv e program s generic functions can n o t be used in th e sta n d a rd w ay (in w hich a user ty p e is converted lazily to th e generic rep resen ta ­ tio n after w hich th e generic function is applied an d th e resu lt is converted back again). We need a v arian t in w hich th e generic re p re se n ta tio n is n o t discarded b u t p ersists somehow, such th a t in teractio n s (an d corresponding conversions to th e user types) can tak e place.

C onsequently, we have to create a fam ily of o b jects of different ty p es to ac­ com m o d ate th e generic rep rese n tatio n . O ne solution m ight be to create a fam ily of functional heaps (like Haskell MVars [19]). T h is fam ily of heaps should th e n be used to create th e req u ired com m unication in fra stru c tu re . In ste a d we have used

receiver objects [1], a facility of Object I/O . A receiver o b ject (or, in sh o rt, re­ ceiver) has an in tern a l s ta te in th e sam e w ay as functional heaps do, b u t th e y are m ore flexible because one can a tta c h an a rb itra ry n u m b er of m eth o d s to th e m th a t also have access to th e w orld environm ent. In th is way, receivers enable an o b ject-o rien ted style of program m ing. W ith these m e th o d s we have im plem ented th e com m unication in fra stru c tu re .

T he m eth o d s of a receiver th a t ‘m a n ag es’ a t value are invoked via Ob­ ject I/O m essage passing functions. T hese require an identification value of ab­ s tra c t ty p e (GECId t ) . T hese are g en erated w ith th e function openGECId :: (P S t p s ) ^ (GECId t , P S t p s ) . For th e earlier m entioned g e c G e tV a lu e and g e c S e tV a lu e m eth o d s of th e GEC record corresponding functions have been defined th a t h andle th e d eta ils of m essage passing. T hese are g e c G e tV a lu e ' :: (GECId t ) (P S t p s ) ^ ( t , P S t p s ) an d g e c S e tV a lu e ' : : (GECId t ) t (P S t p s ) ^ (P S t p s ) respectively. T h e GEC record m eth o d s are sim ply curried ap plications of these m essage passing functions.

U sing receivers, we can create a fam ily of o b jects th a t store th e corresponding values of th e generic ty p e family, th a t com m unicate w ith th e ir children using th e ir ty p e d identifiers, and th a t com m unicate w ith th e ir p a re n t using th e call­ back interface. T he topology of th e receiver ob jects is sim ilar to th e generic rep resen tatio n .

In Fig. 4 we show th e o b jects th a t are cre ate d to rep resen t th e value [1] generically. N otice th e sim ilarity betw een th e generic rep re se n ta tio n an d th e topology of th e receiver o b jects created. For th is p a rtic u la r value, 11 receiver o b jects are initially created. T he figure reveals th a t, com pared to th e generic

(11)

F ig . 4. The representation of [1] using generic types (Left), and the topology of the created receiver objects (see page 9) representing the same expression (Right).

rep resen ta tio n , tw o ad d itio n al (inactive) receivers (in d icated by d ark grey boxes, one m arked N il : : an d one m arked Cons : : ) have been created . T h e reason is th a t in ord er to allow a u ser to change a c o n stru c to r to a n o th e r one, th e in fra stru c tu re to h an d le th a t o th e r co n stru c to r m u st already be available.

In general, a lot of com m unication takes place w hen th e ap p licatio n user o p era tes th e editor. F or in stance, w hen a leaf value in th e tre e of receivers is changed, all spine receiver o b jects th a t d ep en d on it will be inform ed. T h e re­ q u ired un d erly in g com m unication in fra stru c tu re is far from triv ial, b u t we only have to define it once. E ach receiver o b ject of a c e rta in (generic) ty p e fu rth e r­ m ore requires a view to display an d ed it a value of th a t type. How th is view can be a d a p te d , is explained in Sect. 5.

O nce th e e d ito r is c reated for a c e rtain ty p e an d th e corresponding views have been created , th e ap p licatio n user can use th e views to ed it th e value. For th e im p le m en tatio n th is m eans th a t receivers have to be c rea ted dynam ically as well. If th e ap p lic atio n user m akes a larg er s tru c tu re (e.g. [ 1 ,2 ] ) o u t of a sm aller one (e.g. [ 1 ] ) , we have to increase th e n u m b er of receivers accordingly. It is possible th a t a receiver is n o t needed anym ore because th e user has chosen som e o th e r value. Receivers are only deleted w hen th e w hole e d ito r is closed. U n til th e n we m a rk unused receivers as in activ e b u t rem em ber th e ir values. We sim ply close th e views of th ese in activ e receivers an d reopen th e m w hen th e user reg rets his decision. In th is way th e ap p licatio n user can quickly sw itch from one value to a n o th e r an d backw ards w ith o u t being forced to re ty p e inform ation.

W h en a user sw itches from one d a ta c o n stru c to r to an o th er, we have to create d efault values. For in stance, if a N il is changed in to a Cons using an e d ito r for a list of integers, we will g en erate a d efau lt integer (0) an d a d efault list of integers (N il). W e use a generic function to m ake u p such a d efault value. A p ro g ram m er can easily change th is by specializing th is generic d efault function for a p a rtic u la r type.

(12)

5

C u sto m iz in g G ra p h ica l E d ito r C o m p o n e n ts

5.1

T he counter exam ple

No p a p e r a b o u t GUIs is com plete w ith o u t th e co u n ter exam ple. To m ake such a co u n ter we need an integer value and an up-dow n b u tto n . T he co u n ter has to be increased or decreased each tim e th e corresponding b u tto n is pressed. Notice th a t our ed ito rs only re a c t to changes m ade in th e displayed d a ta stru c tu re . C onsequently, if th e ap p licatio n user chooses Up tw o tim es in a row, th e second Up will only be n o ticed if its value was n o t Up before. T herefore, we need a th re e s ta te b u tto n w ith a n e u tra l po sitio n ( N e u tr a l) th a t can be changed to eith er Up or Down. A fter being pressed it has to be reset to th e n e u tra l position again. T he co u n ter can be cre a te d a u to m a tic a lly by applying selfG EC u p d C n tr

( 0 , N e u t r a l ) , using th e concise definitions in Fig. 5.

:: UpDown = Up | Down | N eu tral :: Counter :== (Int,UpDown)

updCntr :: Counter -> Counter updCntr (n,Up) = (n+ 1,N eutral) updCntr (n,Down) = (n -1 ,N e u tra l) updCntr any = any

F ig . 5. Two GBCcounters. The standard one (on top) and a customized one.

T he definition of th e counter, th e m odel, is in tu itiv e and straig h tfo rw ard . T he gen erated G E C Counter works as inten d ed , an d we get it for free. U nfortunately, its view is a counterexam ple of a good-looking counter (b o tto m w indow in Fig. 5). In th is case we w ant to hide th e tu p le d a ta c o n stru c to r editor, an d place th e integer box n e x t to th e b u tto n editor. A nd finally we prefer to display ±1 in stead of lNeut[al 3 th a t we g en erate as default ed ito r for values of th e ty p e UpDown.

5.2

Full custom ization

O ne of th e goals in th is p ro je c t was to o b ta in fully custom izable GUI editors. Here, we explain how th is can be done.

E ach receiver o b ject th a t is generically c reated by th e in stan ces of mkGEC requires a graphical ed ito r definition th a t will tell how a value of th a t ty p e can be displayed a n d edited. T h is is done by a set of ‘m irro r’ functions th a t takes two a d d itio n al p aram eters. T hese are a fresh receiver identification value, an d a view definition function. Below th is is show n for th e generic P a i r case, th e o th er generic cases proceed analogously:

(13)

g e n e ric mkGEC t :: [GECAttribute] t (C allB ackFunction t (PSt p s )) (PSt ps) -> (GEC t (PSt p s ) , PSt ps) mkGEC{|Pair|} gx gy as v f env

# (p a irId ,e n v ) = openGECId env

= pairGEC p a ir I d (pairGUI p a ir I d ) gx gy as v f env

T he view definition function is of ty p e (P S t p s ) ^ (GECGUI t (P S t p s ) , P S t p s ) : an environm ent based function in order to allow it to allocate th e necessary resources. Hence, th e view of a G E C t is defined by a GECGUIt . A GECGUIt on an environm ent env is a record w ith th e following functions:

1. g u iL o c s reserves GUI screen space for th e su b co m p o n en ts of t . I t is a func­ tio n th a t re tu rn s a list of GUI locations8, given its own location. For th is reason it has ty p e L o c a tio n ^ [ L o c a tio n ] .

2. guiO pen creates th e view and th e reserved GUI screen e state, given its own location. Hence, it m u st be an action. I t has ty p e L o c a tio n ^ env ^ env. 3. g u iU p d a te defines how a new value set from th e o u tsid e9 has to be displayed.

It has th e obvious ty p e t ^ env ^ env.

4. g u iC lo s e closes th e view (usually a triv ial Object I/O close action, w hich is th e inverse o p eratio n of 2 above). It has th e action ty p e env ^ env.

For each in stan ce of th e generic fam ily one such ‘m irro r’ function a n d cor­ responding view definition has been predefined. For any (user defined) type, an ed ito r is co n stru c te d au to m a tic a lly by com bining these generic editors. T h e spe­ cialization m echanism of Clean can be used to change any p a rt of a G E C T since a specialized definition for a c e rta in ty p e overrules th e d efau lt ed ito r for th a t type. T herefore, to create a good-looking co u n ter one only has to redefine th e ed ito r for ( , ) an d UpDown. B ecause th e UpDown ed ito r behaves as a basic value editor, its definition uses th e m irro r function for basic types, w hich is basicGEC: mkGEC{|UpDown|} as v f env

# (updownId,env) = openGECId env

= basicGEC updownId (updownGUI (gecS etV alue' updownId)) as v f env

T he a c tu a l definition of updownGUI is 50 loc. H alf of th e code is ‘o rd in a ry ’ Object I/O code to im plem ent th e guiO pen function. T he o th e r functions are one-liners (th is is typical).

To show th e effect of th e custom ized rep resen tatio n , we c o n stru c t a slightly m ore com plicated exam ple. Below, in th e record stru c tu re D o u b le C o u n te r we store tw o counters and an integer value, w hich will always display th e sum of th e two counters. N otice th a t th e p ro g ram m er can specify th e w anted b ehavior ju s t by applying u p d C n tr on each of th e counters. T he sum is calcu lated by ta k in g th e su m of th e resu ltin g co u n ter values. O ne o b ta in s a very clear specification w ith o u t any w orry a b o u t th e graphical re p re se n ta tio n or ed it functionality. All

8 The number of elements is actually dependent on the kind: zero for *, one for * ^ *,

two for * ^ ^ * etc.

(14)

one has to do is to ap p ly selfG EC u p d D o u b leC n tr to th e in itial value { c o u n t e r l = ( 0 , N e u t r a l ) , c o u n te r 2 = ( 0 , N e u t r a l ) , sum = 0}. :: DoubleCounter = { c o u n te rl :: Counter , counter2 :: Counter , sum :: I n t }

updD oubleCntr::D oubleCounter -> DoubleCounter updDoubleCntr c n tr

= { c o u n te rl = new counterl , counter2 = newcounter2

, sum = f s t newcounter1 + f s t newcounter2 }

where newcounter1 = updCntr c n tr.c o u n te r1 newcounter2 = updCntr c n tr.c o u n te r2

F ig. 6. An editor with two counters and a resulting sum.

For large d a ta s tru c tu re s it m ay be infeasible to display th e com plete d a ta s tru c tu re . C u sto m izatio n c an be used to define a G E C T th a t creates a view on a finite su b set of such a large d a ta s tru c tu re w ith b u tto n s to brow se th ro u g h th e rest of th e d a ta s tru c tu re . T h is sam e technique can also b e used to create G E CTs for lazy infinite d a ta stru c tu re s. For these infinite d a ta s tru c tu re s custom ization is a m u st since clearly th e y can never be fully displayed.

6

R e la te d W ork

T he sy stem described in th is p a p e r is a refined version of th e well-known m o d el­ view p a rad ig m [18], in tro d u ced by Trygve R eenskaug in th e language Smalltalk (th en n am ed as th e m o d e l-v ie w -c o n tro lle r p arad ig m ).

In our app ro ach th e d a ta ty p e plays th e m o d el role, an d th e view s are de­ rived au to m a tic a lly from th e generic decom position of values of th a t ty p e. T he

c o n tro lle r role is d e a lt w ith by b o th th e a u to m a tic a lly derived com m unication in fra stru c tu re an d th e views (as th e y need to handle user actions). Because views are derived autom atically, a p ro g ram m er in our sy stem does n o t need to explicitly ‘re g iste r’ nor p ro g ram views. Views can b e custom ized via overruling in stan ce d eclaratio n s of a rb itra ry types.

A d istinguishing feature of our ap p ro ach is th e d istrib u te d n a tu re of b o th th e m odel an d th e views. T he m odel is d istrib u te d using th e generic decom position of th e m odel value. T he subvalues are sto re d in th e receivers. T h is im plies th a t it should be relativ ely easy to d istrib u te th is fram ew ork over a collection of d istrib u te d in teractiv e processes. T he view is d is trib u te d as well, as each view of a generic com ponent is responsible for showing th a t p a rtic u la r generic instance only. Its fu rth e r responsibility is to define GUI space for th e subcom ponents.

(15)

Fram ew orks for th e m odel-view p a ra d ig m in a functional language use a sim ­ ilar value-based app ro ach as we do (C laessen e t al [7]), or an event-based version [15]. In b o th cases, th e p ro g ram m er needs to explicitly h andle view re g istratio n and m an ip u latio n . In our fram ew ork, th e inform ation-flow follows th e stru c tu re th a t is derived by th e generic decom position of th e m odel value. T h is suggests th a t we could have used a stream -b a sed solution such as F u D G E T S [6]. However, stre a m b ased approaches are know n to im pose a m uch to rigid coupling betw een th e stre a m based com m unication an d th e G U I s tru c tu re resu ltin g in a severe loss of flexibility and m ain tain ab ility . For th is reason, we have chosen to use a call-back m echanism as th e interface of our G E C T com ponents.

T he Vital p ro je c t [16] has sim ilar goals as ou r p ro ject. Vital is an in terac­ tive graphical environm ent for d irect m a n ip u la tio n of Haskell-like scripts. Shared goals are: d irect m a n ip u la tio n of functional expressions (Haskell expressions vs. flat values), m a n ip u la tio n of cu sto m types, views th a t d ep en d on th e d a ta ty p e

(d a ta type sty le s), guarded d a ta ty p es (we use selfG E C ), an d th e ab ility to work w ith infinite d a ta stru c tu re s. Differences are th a t our system is com pletely im ­ p lem ented in Clean, while th e Vital system has been im plem ented in Java. T his im plies th a t our system can handle, by co n stru ctio n , all flat C lean values, and all values are obviously w ell-typed. In ad d itio n , th e p u rp o se of a G E C T is to edit values of ty p e t, while th e p u rp o se of a Vital session is to ed it Haskell scripts.

7

C o n c lu sio n s an d F u tu re W ork

G raphical E d ito r C om ponents are b u ilt on to p of th e Object I/O GUI library. T he Object I/O lib ra ry offers a lo t of fu n ctio n ality (e.g. one can define m enus, draw objects, m ake tim ers, e tcete ra) an d it is also very flexible, b u t a t th e expense of a steep learning curve. G rap h ical E d ito r C om ponents offer a m ore lim ited functionality: a custom izable view an d ed ito r for any type. T he custom ization abilities m ake it possible to in co rp o rate th e fu n ctio n ality of Object I/O . I t does n o t exclude Object I/O; it is fully in te g ra te d w ith it. O ne can still use windows, dialogs, m enus, tim ers, an d so on. T he a b stra c tio n layer offered by th e G raphical E d ito r C om ponents is m uch higher. T he learning curve is sh o rt an d flat because one basically has to learn only th e mkGEC function in ste a d of ap p ro x im ate ly 500 Object I/O functions. T he arg u m en ts of mkGEC are sim ilar to m ost Object I/O functions. T he m ost im p o rta n t advantages are:

— for any value of any flat ty p e one gets an ed ito r for free;

— th e ed ito r can be used to give ty p e safe in p u t to th e application; — any o u tp u t or in term ed iate resu lt can be displayed;

— v isualization is se p a ra te d from th e value in fra stru c tu re an d is custom izable by redefining th e com ponents th a t need to be displayed differently;

— ed ito rs can be com bined including m u tu a lly d ep en d e n t editors.

T he p resen ted m e th o d offers a good se p a ratio n of concerns. T he specifica­ tio n of th e w an ted fu n ctio n ality of a com ponent is com pletely se p a ra te d from th e

(16)

specification of its graphical rep resen ta tio n . O ne even o b tain s a d efau lt g rap h i­ cal re p re se n ta tio n for free. T his m akes it an excellent to o l for ra p id p ro to ty p in g . Also one can a b s tra c t from th e way co m ponents are connected. As a resu lt, com ­ p licated in teractiv e ap p licatio n s can be created w ith o u t a lo t of u n d e rsta n d in g of graphical I /O handling.

E d ito rs can be used for pro g ram m in g GUI objects, from sim ple dialogs to com plicated sp readsheets. T h ey can also be used for tra c in g an d debugging.

T he a u to m a tic g en eratio n of com ponents was only possible th a n k s to th e generic pro g ram m in g facilities of Clean. T he in teractiv e n a tu re of th e com po­ n en ts caused som e in te restin g im p lem en tatio n problem s. We h a d to store th e generic rep re se n ta tio n in special o b jects (Object I/O receivers). We also h it on a d istu rb in g lim ita tio n of th e c u rre n t im p lem en tatio n in Clean: one ca n n o t over­ load generic functions in th e ir generic type. For th is reason we in tro d u ced th e ‘m irro r’ functions in Sect. 5. We in ten d to solve this.

We p la n to ex ten d th e system w ith su p p o rt for non-flat types. T h is will require th e ab ility to deal w ith function types. A n in terestin g d irectio n of re­ search seems to be to use th e E sther shell of th e exp erim en tal o p e ra tin g system Famke, which deals w ith creatin g and com posing functions in an in teractiv e and d ynam ically ty p e d way. T h is shell is w ritte n in Clean as well [20].

F u rth erm o re, we will investigate th e expressive pow er of our graphical ed ito r com ponents by co nducting experim ents an d case studies.

A c k n o w le d g e m e n ts

T he a u th o rs would like to th a n k A rjen van W eelden, P ie te r K oopm an, R onny W ichers Schreur a n d th e anonym ous referees for th e ir valuable com m ents.

R e fer e n c es

1. P. Achten and R. Plasmeijer. Interactive Functional Objects in Clean. In Clack, Hammond, and Davie, editors, The 9th International W orkshop on the Im plem en­ ta tio n o f Functional Languages, IF L 1997, Selected Papers, volume 1467 of L N C S,

pages 304-321. St.Andrews, UK, Springer, 1998.

2. Achten, Peter and Peyton Jones, Simon. Porting the Clean Object I/O Library to Haskell. In M. Mohnen and P. Koopman, editors, The 12th International W orkshop on the Im plem en ta tio n o f F unctional Languages, IF L 2000, Selected Papers, volume 2011 of L N C S, pages 194-213. Aachen, Germany, Springer, 2001.

3. A. Alimarine and R. Plasmeijer. A Generic Programming Extension for Clean. In T. Arts and M. Mohnen, editors, The 13th International workshop on the I m ­ plem entation o f Functional Languages, I F L ’01, Selected Papers, pages 168-186. Alvsjo, Sweden, Sept. 2002.

4. Angelov, Krasimir Andreev. ObjectIO for Haskell. Description and Sources at www.haskell.org/O bjectIO /, Applications at /free.top.bg/ka2_m ail/, 2003. 5. E. Barendsen and S. Smetsers. Handbook o f Graph Gram mars and Com puting by

Graph Transform ation, chapter 2, Graph Rewriting Aspects of Functional Pro­ gramming, pages 63-102. World Scientific, 1999.

(17)

6. M. Carlsson and T. Hallgren. F u D G E T S - a graphical user interface in a lazy functional language. In Proceedings o f the A C M Conference on Functional Pro­ gram m ing and C om puter Architecture, F P C A ’93, Kopenhagen, Denmark, 1993. 7. K. Claessen, T. Vullinghs, and E. Meijer. Structuring Graphical Paradigms in

TkGofer. In Proceedings o f the 1997 A C M S IG P L A N International Conference on Functional Programming (IC F P ’97), volume 32(8), pages 251-262, Amsterdam, The Netherlands, 9-11 June 1997. ACM Press.

8. D. Clarke and A. Löh. Generic Haskell, Specifically. In J. Gibbons and J. Jeuring, editors, Generic Programming. Proceedings o f the IF IP TC 2 W orking Conference on Generic Programming, pages 21-48, Schloss Dagstuhl, July 2003. Kluwer Aca­ demic Publishers. ISBN 1-4020-7374-7.

9. M. de Mol, M. van Eekelen, and R. Plasmeijer. Theorem proving for functional programmers - Sparkle: A functional theorem prover. In T. A rts and M. Mohnen, editors, Selected Papers fro m the 13th International W orkshop on Im plem entation o f Functional Languages, IF L 2001, volume 2312 of LN C S, pages 55-72, Stockholm, Sweden, 2001. Springer.

10. Divinszky P. Haskell - Clean Compiler. ELTE, Budapest, 2003. Software at aszt.inf.elte.hu/~fun_ver/2003/software/HsCleanAll2.0.2.zip.

11. Fulgham, Brent. The Clean ObjectIO Library under Linux (G tk+). Descrip­ tion at people.debian.org/~bfulgham/clean_examples, May 2003. Sources at people.debian.org/~bfulgham /clean/objectio-linux.tar.gz.

12. Hegedus H. Haskell to Clean Front End. M aster’s thesis, ELTE, Budapest, Hun­ gary, 2001.

13. Hinze, Ralf. A new approach to generic functional programming. In The 27th A nn u a l A C M S IG P L A N -S IG A C T Sym posium on Principles o f Programming L an­ guages, pages 119-132. Boston, Massachusetts, January 2000.

14. Hinze, Ralf and Peyton Jones, Simon. Derivable Type Classes. In G. Hutton, edi­ tor, 2000 A C M S IG P L A N H askell Workshop, volume 41(1) of E N T C S . Montreal, Canada, Elsevier Science, 2001.

15. W. Karlsen, Einar and S. Westmeier. Using Concurrent Haskell to Develop Views over an Active Repository. In Im plem entation o f Functional Languages, S e­ lected Papers, volume 1467 of L N C S, pages 285-303, St.Andrews, Scotland, 1997. Springer.

16. K eith Hanna. Interactive Visual Functional Programming. In S. P. Jones, editor,

Proc. In tn l Conf. on Functional Programming, pages 100-112. ACM, October 2002. 17. P. Koopman, A. Alimarine, J. Tretmans, and R. Plasmeijer. Gast: Generic Auto­ m ated Software Testing. In R. Pena and T. Arts, editors, The 14th International

Workshop on the Im plem en ta tio n o f Functional Languages, IF L ’02, Selected Pa­ pers, volume 2670 of L N C S, pages 84-100. Springer, 2003.

18. G. Krasner and S. Pope. A cookbook for using the Model-View-Controller user interface paradigm in Smalltalk-80. Journal o f Object-Oriented Programming,

1(3):26-49, August 1988.

19. S. Peyton Jones, A. Gordon, and S. Finne. Concurrent Haskell. In 23rd A C M Sym posium on Principles o f Programming Languages (P O P L ’96), pages 295-308, St.Petersburg Beach, Florida, 1996. ACM.

20. A. van Weelden and R. Plasmeijer. Towards a strongly typed functional operating system. In R. Pena and T. Arts, editors, The 14th International W orkshop on the Im plem entation o f Functional Languages, IF L '02, Selected Papers, volume 2670 of

References

Related documents

However, theories of social practice can be further developed through an explicit focus on corporeality, recognizing that environmentally responsible behaviors involve new forms

Objective of this study focused on the efficacy of different concentrations of peroxyacetic acid (PAA) to the firmness (N), peroxide value (meq/kg), total plate

does viagra stop after ejaculation types viagra pills. Este aceite est demostrando ser una gran ayuda para los que sufren de largo plazo tipo inflamaciones artrticas, ya que ayuda

Based on the results of research and discussion presented here, the proposed HOTS instruments can be used to measure HOTS of high school students in mathematics instruction,

In practice, this process is undertaken by cross-class(fying labour by proxies for skill, such as educational alfainment and experience. The relative skill levels of

objective of this paper is to analyse consumers’ perceptions about the risk and quality attributes of food consumption; and to evaluate the incidence of these factors when

W hile students' choice behavior is affected by variables like parents' income, parents' college selectivity, and private high school attendance, many other background differences

We are constantly trying to ensure that we provide the best possible service to our business partners and in doing this have identified a compatibility issue between Internet