• No results found

Using SICStus Objects in the Design of Graphical User Interfaces

N/A
N/A
Protected

Academic year: 2021

Share "Using SICStus Objects in the Design of Graphical User Interfaces"

Copied!
37
0
0

Loading.... (view fulltext now)

Full text

(1)

SICS T92:10

Using SICStus Objects in the

Design of Graphical User

Interfaces

Thomas Sjöland

SICS

August 1992

SICS Technical Report ISSN 1100-3154

Swedish Institute of Computer Science

Box 1263, S-164 28 Kista, SWEDEN

(2)

Using SICStus Objects in the Design of

Graphical User Interfaces

Thomas Sjöland

SICS, Box 1263, S-164 28 Kista, Sweden

tel: +46 8 752 1542

Electronic mail: [email protected]

Abstract

The functionalities of SICStus Objects, a system allowing object oriented

programming in SICStus Prolog are shown and an example is presented:

support software for building graphical user interfaces.

This text assumes a basic knowledge about Prolog programming in SICStus

Prolog and some intuition about object oriented programming.

SICStus Objects was implemented as an embedded language in SICStus

Prolog by Seif Haridi and Kent Boortz. SICStus Prolog is developed and

maintained by Mats Carlsson, Stefan Andersson and Kent Boortz at SICS with

support from Ellemtel Utvecklings AB.

(3)
(4)

Background

Some Prolog vendors supply their systems with possibilities for using object

orientation together with Prolog. Commercial systems known to us are Prolog++ from

Logic Programming Associates, Logical Object Systems (LOS) from Imperial College

[McCabe89] and ELSA from ELSA Software.

SICStus Objects, the system described here has a lot in common with LPA's

Prolog++ [Vasey, Spencer et.al.90], and with the systems described by Fromherz

[Fromherz91] and Moss [Moss90].

SICStus Objects

SICStus Objects provides the Prolog programmer with mechanisms for defining and

using objects as a programming paradigm together with SICStus Prolog.

• Prolog goals can be called from components in objects and messages can be sent to

objects from ordinary Prolog clauses.

• The language SICStus Objects is translated into Prolog. This gives the possibility of

using the Prolog compiler.

NB: The current implementation is fairly straightforward. E.g. it does not optimize

inheritance or updates of objects. This might limit the applicability of the system.

Terminology

Object oriented programs consist of definitions of data together with methods to

manipulate the data. Often the notion "class" is used when talking about a definition

and "object" is used when talking about an instance of the class which is created

during run-time. SICStus Objects follows the convention of LPA's Prolog++ using

"object" for the description and "instance" for objects created during the execution of

the program. This is motivated by the fact that an object in SICStus Objects can be

modified. Objects and instances behave similarly with the major difference that objects

can be compiled whereas instances cannot. Methods and data (attributes), are here

referred to as components. Components in compiled objects cannot be modified unless

declared dynamic. Regardless of these differences it is appropriate to use the term

"object" unless we are specifically talking about instances.

Compiling and running SICStus Objects

In SICStus Objects the user can freely mix SICStus Prolog code with the object

oriented code. This allows a great deal of flexibility. When a SICStus Objects program

(5)

is to be preprocessed or run you load the translator, the runtime system and the

definitions of the object object.

:- use_module(library(objects)).

The object oriented programs should be translated into Prolog. This is accomplished

by using a call of this form:

:- translate(myfile).

This call translates myfile into the Prolog source file myfile.pl, which can

subsequently be compiled (or loaded) by SICStus Prolog in the usual way.

A program in SICStus Objects consist of a set of object definitions. Outside the

definitions of objects you can write any ordinary clauses and directives in SICStus

Prolog. The syntax of Prolog is extended with operators for invoking the object

oriented system from Prolog.

The following operators are defined for SICStus Objects:

:- op(1200,fy,[open_object,close_object]).

:- op(800,xfx,['<-']).

:- op(600,xfx, [':=','+=','-=']).

Syntax

In SICStus Objects the Prolog syntax is used for definitions.

An object definition is bracketed thus:

open_object <ObjectName>.

…<definitions for hierarchy and components>

close_object <ObjectName>.

The syntax of components is that of Prolog clauses. The inheritance hierarchy is

specified by defining the component super/1. A link is specified by defining the

component link/2. The keyword dynamic is used to specify that a component

may be modified. Undefined components are considered as dynamic when added to an

object. Prolog goals are simply written in the body, while component access of

(6)

An example of an object definition

open_object my_object.

super(another_object).

dynamic(attribute/1).

attribute(value).

attribute(anothervalue).

method(X) :- prologgoal(X),

johnnys_object <- method(X).

method(X) :- myself <- attribute(X),

self <- inherited_method(X,X).

link(method_of_other_object/3,other_object).

close_object my_object.

SICStus Objects is a dynamic object system

A static object system cannot create objects during the execution. Therefore in a static

object system there is no need to distinguish between objects and instances. Each

object which is being used has its own definition and a unique set of components,

playing the role of state variables.

A dynamic object system allows the program to create objects in the system. SICStus

Objects is a dynamic object system.

Modifying the state

The idea of a state variable is alien to logic programming but it is practical in many

situations. State variables are implemented in SICStus Objects as components by using

the database features of SICStus Prolog. Therefore components can be added and

removed to/from objects as well as modified in addition to just being used.

Object definitions and object instances

An object definition which is written in the source code describes an object but also a

class of object instances. When object instances are created, the object is used as a

template. The object instance receives a name which can be used as a reference when

sending messages. In SICStus Objects messages can be sent to objects and to

instances. The distinction between objects and instances is that instances are not named

in the source code, but the instances are given unique names upon being created.

(7)

Components

An object is a collection of components. Components are known to the object and its

ancestors in the object hierarchy. The object hierarchy is specified with the component

super/1, defining the object(s) from which the current object automatically inherits

components which are not defined in the object itself. In SICStus Objects,

mechanisms for creating objects and instances as well as for sending messages to the

objects (instances) are provided.

A component of an object can be defined, accessed, modified and deleted. SICStus

Objects allows a component to be seen as a relation, i.e. several alternatives are

allowed. The access mechanism can backtrack upon failure just like in Prolog but

backtracking is limited to be only within the first found object which contains the

component.

Object hierarchies and inheritance mechanisms

When an object lacks a component the system can search for it in another object. By

making precise exactly which objects are higher than a given object and introducing an

object which is higher than any other object a semilattice of objects, an object

hierarchy, is formed. The highest object in the hierarchy is the object

object,which

has no defined component super/1. Specialisation of objects is achieved through

inheritance. When a component is not defined in an object it is looked for in the

objects that are higher. The immediately higher objects are defined in the component

super. Multiple inheritance is provided since an object may refer to several other

objects with the component super/1 by simply adding more declarations of the

component super/1.

Since the hierarchy links are components, explicit searches in the hierarchy can be

programmed with a large degree of freedom.

Shadowing

Shadowing (overriding inheritance) means that components which are found in objects

which are lower in the hierarchy hide components from higher objects.

In SICStus Objects a component is found in a unique object. Since SICStus Objects is

based on Prolog, alternatives are allowed which can be used for backtracking. The

alternatives are only searched in the chosen object, even if there are definitions in other

places in the object hierarchy. In LOS [McCabe89] there are two different

mechanisms for inheritance. Except for shadowing LOS uses the union of all

(8)

be avoided by using the component super/1 and including a clause to distribute

messages upwards in the hierarchy:

method(InData)

:-myself <- super(S), S <- method(InData).

Since multiple inheritance is provided, shadowing can be implemented in various

ways. In SICStus Objects the principle that is followed is this:

Inheritance as specialisation:

The object that is identified as the carrier of an inherited component is the leftmost one

which does not have a subobject in which the component occurs.

In figure 1, the principle used to resolve multiple inheritance is shown with a perhaps

somewhat contrived example. Consider four objects a,b,c and d where d has a, b and

c as

super and b and c have a as super. A component m is defined in a and c, a

component n is defined in a and b, and a component o is defined in b and c. In some

object oriented systems multiple inheritance is resolved by a left-to-right depth first

search upwards in the lattice. Such a search traverses first one branch and then

possibly the others, one at a time. An access to m from d would identify the m in a

via b rather than the more specialised version in c. Considering the component n on

the other hand it is clear that the problem cannot be resolved with a reordering of the

branches. In one of the cases a component will be found which should have been

shadowed by a specialized instance of it. Furthermore, since inheritance should be

regarded as specialisation, a breadth first search is not sufficient to implement the

principle (consider that d has a as a direct super which would give the m of a rather

than that of c).

By using the rule above implemented as a topological sort, d gets the n and the o of b

and the m of c.

(9)

a : m , n

b : n , o

c : m , o

d

Fig 1: Inheritance as specialisation, the principle used to

resolve multiple inheritance in SICStus Objects, gives

d the n and the o of b and the m of c.

Components can also be inherited from named objects without considering the

hierarchy. This explicit inheritance is provided by defining links.

It is essential to ensure that the design of the inheritance relation does not create loops,

i.e. the super relation should be a semi-lattice with object as the top element.

Polymorphism is achieved by using the same component name to define different

behaviours for different objects.

Encapsulation and abstraction

Since all objects are defined in parentheses (open_object, close_object) and

the components are unique to the object the components are encapsulated. In SICStus

Objects components can also be defined as private. Such components are not inherited.

Otherwise they are understood as public. Public is the default case.

The name of an object and the names of its public components are its abstraction.

Communication and control of the execution

The central operation for an object oriented system is transfer of messages. Message

transfer is essentially the same as goal resolution in Prolog using the inheritance

hierarchy to find the addressed component.

Messages are sent to objects and are of two types:

1) request for execution of a method or finding the value of a component, e.g.:

obj <- message(Hello)

(10)

2) request for modification of a component, e.g.:

obj <- update(attribute3(<new_value>))

obj <- retract(attribute3(_))

obj <- assert(attribute3(<new_value>))

self

and

myself

In order to use components from the current object even when inheritance is at play,

the keyword self can be used. self is used to refer to the object that used the

component. Another keyword, myself refers to the name of the object definition in

which the method definition is localized. In fact this usage means that myself is

redundant since you can always use the name of an object explicitely, but it is

introduced for convenience and to produce more readable code.

sender

provides selective component invocation

The keyword sender is used to refer to the object that requested the component. By

testing sender the access to components can be arbitrarily limited.

Operations on objects and object instances

Objects can be created based on other object definitions and also be removed. An

instance is normally considered to have as its super the object in respect to which it

was created. The method new/1, defined in the object object is used to create

instances of an object, e.g.:

my_object <- new(Reference)

Executing new/1 means that a new object is created which is considered as a

subobject (instance) of the object my_object. It has a unique set of components

which can be used for storing values.The components are inherited from

my_object.

If components have been defined as dynamic they can be added and deleted from an

object. Components which are not in the source code are considered to be dynamic.

The object

object

and its components

The top element of the object hierarchy is an object to which all other objects are

subobjects (instances), the object object. The components of object are available to

all objects in the system.

(11)

Systems for object oriented programming are often implemented together with an

interactive graphical programming environment. In this there are tools to inspect the

control structures (e.g. "object browsers") and to construct program code. Such tools

are yet to be implemented for SICStus Objects.

Standard

The combination of object oriented programming and logic programming in Prolog is

still a matter of research and early development. There is currently no standard

available.

An example:

gm objects

, interfacing to the graphics

manager

As an example of the use of SICStus Objects we choose an object oriented interface to

the graphics manager of SICStus Prolog, GM [AlAnFlFrNiSu91]. GM is written in

C++ using Interviews, a set of classes used to specify graphical interactors, visible

graphical "things" which have certain predefined behaviours. In order to make it

possible to extend the interface in such a way as to allow the programmer to define

new interactors with their own behaviour an object oriented approach is a significant

help. We will show how the basic interface is constructed in SICStus Objects, and

then we give some examples of how it can be extended to support a few new

interactors of the programmer's choice. The name gm objects will be used in

reference to the graphical subsystem.

In gm objects the object hierarchy of SICStus Objects is used to define methods

for constructing and manipulating graphical objects. The available graphical objects are

given by GM.

The components of

gm objects

Objects in gm objects have a set of components to manage the state of the

interface. The central idea of gm objects is to consider the "visible things" as

objects in SICStus Objects. The contents of a visible object are specified in the

component content/1. Some default operations for managing the visualisation of

the object are provided.

In order to create an object which is subordinated to gm_object you use the method

gmnew/1. When sent to an object which is subordinate to gm_object it will

create an object of this type, performing the appropriate procedures for setting up the

object and making it visible under Xwindows. The inheritance hierarchy is used to

enable the system to automatically choose the desired initiation method

(12)

intervention by the programmer. This makes it possible for the programmer to use gm

objects without considering the underlying GM package with its handling of

references to graphical objects. The references and properties needed to construct the

object are to be found as components in the object. By doing so the costly

communication in order to inspect the visual objects is avoided. In some cases this

enhances the functionality of the graphic system since GM does not provide access to

its internal state from the Prolog program. Composite objects may be constructed as

objects in gm objects without modifying the low level GM system.

(13)

The object hierarchy of gm objects

The inheritance relation (super) of gm objects is shown in figure 2 (except for

explicit links of particular components). The relation is interpreted thus: "when X is a

super of Y a component of Y which is not defined in Y itself can be found in X".

<fig 2 > The object hierarchy of gm objects

o b j e c t gm gm_object gm_window gm_windowcontent gm_active gm_view g m _ t e x t gm_input gm_slider gm_inactive gm_output gm_hbox gm_vbox gm_menu gm_button gm_graphic gm_line gm_ellipse g m _ f i l l e l l i p s e g m _ c i r c l e g m _ f i l l c i r c l e g m _ r e c t g m _ f i l l r e c t g m _ s t r i n g gm_bitmap gm_picture gm_fillpolygon gm_polygon

(14)

Visible objects in

gm objects

Some visible objects can be contained in other visible objects. A relation describing the

visible objects that may be contained within other visible objects is a natural way to

display this constraint.

gm_window : gm_hbox | gm_vbox | gm_view | gm_text

| gm_input | gm_output | gm_slider

| gm_button

gm_hbox : gm_vbox | gm_view | gm_text

| gm_input | gm_output | gm_slider

| gm_button

gm_vbox : gm_hbox | gm_view | gm_text

| gm_input | gm_output | gm_slider

| gm_button

gm_view : gm_menu | gm_line

| gm_ellipse | gm_fillellipse

| gm_circle | gm_fillcircle

| gm_rect | gm_fillrect

| gm_polygon | gm_fillpolygon

| gm_string | gm_bitmap |

gm_picture

gm_text : gm_menu

How to use

gm objects

gm objects hides the fact that GM requires that visible objects are constructed in a

particular order. The user specifies the content/1 components of the visible

objects. Thereafter (s)he should send the message gmnew/1 to the object specifying

the window. The methods for creating the content of a window will then look up the

content/1 components describing the layout of the window and creates an object

for each of the visible parts in the appropriate order. It is essential that recursive

objects are not specified since that will lead the construction method gmnew into an

infinite regress. (A tool to check whether a specification is circular, recursive, is a

good exercise in order to familiarize oneself with SICStus Objects and gm

(15)

Event handlers

An important aspect of GUI construction is the handling of events. It is important to be

able to construct a modeless interface, i.e. the interface should be so designed that it is

possible to get a response for any keyklick, selection or similar interaction which is

possible on the screen, rather than having the program wait for a particular input at any

given time. Sometimes, but more rarely, it is essential that the program awaits

particular inputs such as responses to queries etc. before accepting other input. This

later kind of interface is called moded interface and should also be provided, although

that issue is not tackled here. gm objects provides a method, run/0, which is

located in the object gm. The call:

gm <- run.

will start the event handling loop. This loop awaits action from the user. Upon

receiving a message it dispatches the messages to the object in which the event took

place. By specifying an eventhandler as a method of that object the system allows the

user to tailor the responses of the program based of the object hierarchy. The method

should be specified as eventhandle/1. Any programming technique of SICStus

Objects in combination with SICStus Prolog is available, but it is adviced that

responses programmed in the eventhandler are of a reasonably short duration. The

only method that should be allowed to go in an infinite loop is run/0 of the object

gm.

If the generic event handling loop, run/0, is inappropriate the event handling can be

programmed by using either

gm_object <- wait_event(E)

or

gm_object <- next_event(E)

which waits or polls the event queue for incoming events. Whenever the application

wants to treat a received event,

gm_object <- event_handle(E)

can be used. This call can also be used to mimick the reception of an event. If a

sequence of events is recorded, this could for instance be used in a later playback of a

sequence of events.

(16)

Object definitions in gm objects

compile_objects(File) :- gm <- end, object <- clean, translate(File), compile(File).

object_listing :- object_listing(object,0).

object_listing(O,Tab)

:-tab(Tab), write(O), nl, Tab1 is Tab+3,

findall(_,(O <- sub(Obj), object_listing(Obj,Tab1)),_).

full_object_listing :- full_object_listing(object,0).

full_object_listing(O,Tab)

:-tab(Tab), write(O), write('#'), nl, Tab0 is Tab+1,

findall(_,(O <- attribute(A),tab(Tab0),write(A),nl),_), Tab1 is Tab+3,

findall(_,(O <- sub(Obj), full_object_listing(Obj,Tab1)),_).

on(X, [X|_]).

on(X, [_|L]) :- on(X, L).

write_seq([]).

(17)

%---% gm. %---open_object gm. dynamic(host/1). host(hathor). dynamic(username/1). username(thomas).

start :- myself <- host(Host),

myself <- username(Username), (myself <- started -> myself <- end ; true), start.

start(Host) :- self <- update(host(Host)), start. start(Host,Username)

myself <- update(username(Username)), myself <- start(Host). started :- started.

end

bagof1(I,(gm_object <- instance(I), I <- delete),_), end, freeall. % event loop

run :- write_seq([self,'waiting for event']), nl, waitevent(E), write_seq([self,'received event',E]), nl, eventaddress(E,WindowObject), write_seq([self,'dispatching to',WindowObject]), nl, ((WindowObject <- eventhandle(E)) -> true ; write_seq([self,'failed eventhandle'(WindowObject,E)]), nl), ((\+ E=menu(_,quit)) -> self <- run).

close_object gm.

objref_to_name(Ref, Name) :- clause(gmlib:named_object(Name,Ref,_), _).

eventaddress(down(_Window,View,_,_),Ref) :- objref_to_name(View,Ref). eventaddress(button(Window,_),Ref) :- objref_to_name(Window,Ref). eventaddress(menu(Window,_),Ref) :- objref_to_name(Window,Ref).

(18)

eventaddress(return(_Window,Input),Ref) :- objref_to_name(Input,Ref). eventaddress(slider(_Window,Slider,_),Ref) :- objref_to_name(Slider,Ref). eventaddress(noevent,gm_object). %---% gm_object. %---open_object gm_object. % Attributes. % constructor(Constructor)

% contains current Constructor as defined in subclasses % gm_ref(GM-reference)

% contains current reference to GM-object gmnew(Ref) :- self <- new(Ref),

Ref <- gmcreate.

gmcreate :- write_seq([self,'gmcreate/0']), nl, self <- gmcreate(self).

gmcreate(T) :- T==[], !.

gmcreate(A) :- nonvar(A), A=[H|T], !, self <- gmcreate(H), self <- gmcreate(T).

gmcreate(Ref) :- self <- constructor(Constructor), GmRef=Ref,

(gmcreate(GmRef,Constructor) ->

self <- update(gm_ref(GmRef)) ;

write_seq(['prolog:gmcreate/2 failed for', GmRef,Constructor]),nl). gmsend(Message)

:-self <- gm_ref(GmRef), gmexist(GmRef),

gmsend(GmRef,Message). gmexist:- self <- gm_ref(GmRef),

gmexist(GmRef). % events (polling) nextevent :- nextevent(Event), self <- eventhandle(Event). % events (waiting) waitevent :- waitevent(Event),

(19)

self <- eventhandle(Event).

% local events to this object (polling)

nextevent(Event) :- self <- gmsend(nextevent(Event)).

% local events to this object (waiting)

waitevent(Event) :- self <- gmsend(waitevent(Event)).

eventhandle(button(Window,Eventname))

write_seq(['An unknown button was pressed', button(Window,Eventname)]), nl. eventhandle(menu(Window,Eventname))

write_seq(['An unknown menu was selected',

menu(Window,Eventname)]), nl. eventhandle(return(Window,Browser,LineNo)) write_seq(['An unexpected return event occurred',

return(Window,Browser,LineNo)]), nl. eventhandle(return(Window,Input))

write_seq(['An unexpected return event occurred', return(Window,Input)]), nl. eventhandle(down(Window,View,X,Y))

write_seq(['An unexpected down event occurred', down(Window,View,X,Y)]), nl. eventhandle(slider(Window,Slider,Value))

write_seq(['An unexpected slider release event occurred', slider(Window,Slider,Value)]), nl. eventhandle(noevent)

write_seq(['An unexpected noevent event occurred']), nl. close_object gm_object.

(20)

%---% gm_window.

%---% create subobjects to this class to describe different window types

% the field content(_) contains the object class name for the component(s) % which is (are) automatically created and put into the window created by % sending gmcreate to the window class.

% open_object gm_window. super(gm_object). % attributes: % content(Class) % contentref(Ref)

gmcreate :- self <- gmcreate_window(self). gmcreate_window(WindowTitle) self <- update(name(WindowTitle)), self <- content(Class), Class <- gmnew(ObjRef), ObjRef <- update(partof(self)), self <- update(contentref(ObjRef)), ObjRef <- gm_ref(GmRef), self <- update(constructor(window(WindowTitle,GmRef))), self <- gmcreate(self).

update :- self <- gmsend(close), self <- gmcreate(self). open :- self <- gmsend(open).

open(X,Y) :- self <- gmsend(open(X,Y)). close :- self <- gmsend(close),

self<- contentref(R), (R <- menuref(M) -> (M <- delete) ; true), R <- delete, self <- delete.

raise :- self <- gmsend(raise). lower :- self <- gmsend(lower). iconify :- self <- gmsend(iconify).

(21)

setcursor(Cursor) :- self <- gmsend(setcursor(Cursor)). getcursor(Cursor) :- self <- gmsend(getcursor(Cursor)).

%---eventhandle(menu(Window,quit)) :-write_seq(['Deleting window',Window]), nl, self <- close. %---close_object gm_window.

(22)

%---% gm_window_content. %---open_object gm_window_content. super(gm_object). % Attributes:

% partof(_) reference to a window. gmnewcontent(Ref) :-self <- content(C), (C=space -> Ref=space ; C=space(frame(O)) -> (O <- gmnew(Ref0),Ref=space(frame(Ref0))) ; C=frame(space(O)) -> (O <- gmnew(Ref0),Ref=frame(space(Ref0))) ; C=space(O) -> (O <- gmnew(Ref0), Ref=space(Ref0)) ; C=border -> Ref=border ; C=frame(O) -> (O <- gmnew(Ref0), Ref=frame(Ref0)) ; C=scroller(O) -> (O <- gmnew(Ref0), Ref=scroller(Ref0)) ; C <- gmnew(Ref) ) . close_object gm_window_content.

(23)

%---% gm_active.

%---open_object gm_active.

% for view, text, input and slider (and button) super(gm_window_content).

enable :- self <- gmsend(enable). disable :- self <- gmsend(disable). close_object gm_active. %---% gm_view. %---open_object gm_view. super(gm_active). % graphic(_)

% a set of names of subclasses of gm_graphic which are contained here %

% graphicref(_)

% a set of references to instances of gm_graphic which are in this view %---not called by user directly

---eventhandle(_,quit) :- self <- partof(Window), Window <- close.

%---gmcreate :- self <- gmcreate(200,100),

self <- enable. gmcreate(Xsize,Ysize) self <- update(constructor(view(Xsize,Ysize))), self <- gmcreate(self), bagof1((C,GraphicRef), (self <- graphic(C), C <- gmnewgraphic(self,GraphicRef), self <- assert(graphicref(GraphicRef))), _ ) , self <- setmenu.

line(X1,Y1,X2,Y2) :- self <- gmsend(line(X1,Y1,X2,Y2)). ellipse(X,Y,R1,R2) :- self <- gmsend(ellipse(X,Y,R1,R2)). fillellipse(X,Y,R1,R2) :- self <- gmsend(fillellipse(X,Y,R1,R2)). circle(X,Y,R) :- self <- gmsend(circle(X,Y,R)).

(24)

fillcircle(X,Y,R) :- self <- gmsend(fillcircle(X,Y,R)). rect(X1,Y1,X2,Y2) :- self <- gmsend(rect(X1,Y1,X2,Y2)). fillrect(X1,Y1,X2,Y2) :- self <- gmsend(fillrect(X1,Y1,X2,Y2)). polygon(Xedges,Yedges) :- self <- gmsend(polygon(Xedges,Yedges)). fillpolygon(Xedges,Yedges) :- self <- gmsend(fillpolygon(Xedges,Yedges)). string(X,Y,Text) :- self <- gmsend(string(X,Y,Text)).

bitmap(X,Y,Filename) :- self <- gmsend(bitmap(X,Y,Filename)). setcolors(Fgcolor,Bgcolor) :- self <- gmsend(setcolors(Fgcolor,Bgcolor)). setpattern(Pattern) :- self <- gmsend(setpattern(Pattern)).

setbrush(Pattern,Width) :- self <- gmsend(setbrush(Pattern,Width)). setfont(Font) :- self <- gmsend(setfont(Font)).

stringlength(Text,Length) :- self <- gmsend(stringlength(Text,Length)). batchmode :- self <- gmsend(batchmode).

batchmodeoff :- self <- gmsend(batchmodeoff). update :- self <- update.

setmenu :- self <- setmenu(gm_menu). setmenu(Menu)

:-Menu <- gmnew(:-MenuRef),

self <- update(menuref(MenuRef)), MenuRef <- gm_ref(MenuGmRef), self <- gmsend(setmenu(MenuGmRef)). clear :- self <- gmsend(clear).

zoom(Amount) :- self <- gmsend(zoom(Amount)). scrollto(X,Y) :- self <- gmsend(scrollto(X,Y)). scrollby(X,Y) :- self <- gmsend(scrollby(X,Y)). getcur(X,Y) :- self <- gmsend(getcur(X,Y)). link(setcursor/1,gm_window).

link(getcursor/1,gm_window). close_object gm_view.

(25)

%---% gm_text.

%---open_object gm_text.

super(gm_active).

gmcreate :- self <- gmcreate(12,40,5), self <- enable. gmcreate(Rows,Cols,Tab) self <- update(constructor(text(Rows,Cols,Tab))), self <- constructor(C), self <- gmcreate(self), self <- setmenu. gmcreate(Rows,Cols,Tab,Font) self <- update(constructor(text(Rows,Cols,Tab,Font))), self <- gmcreate(self), self <- setmenu.

readfile(File) :- self <- gmsend(readfile(File)). writefile(File) :- self <- gmsend(writefile(File)). link(setmenu/0,gm_view).

link(setmenu/1,gm_view).

insert(Text) :- self <- gmsend(insert(Text)). delete_text :- self <- gmsend(delete). delete_text(N) :- self <- gmsend(delete(N)). clear :- self <- gmsend(clear).

readonly :- self <- gmsend(readonly). readwrite :- self <- gmsend(readwrite). moveto(X,Y) :- self <- gmsend(moveto(X,Y)). moveby(X,Y) :- self <- gmsend(moveby(X,Y)). in(all,Text) :- self <- gmsend(in(all,Text)).

in(selection,Text) :- self <- gmsend(in(selection,Text)). in(line(LineFrom,LineTo),Text)

:-self <- gmsend(in(line(LineFrom,LineTo),Text)). in(word,Text) :- self <- gmsend(in(word,Text)).

forwardsearch(Text) :- self <- gmsend(forwardsearch(Text)). backwardsearch(Text) :- self <- gmsend(backwardsearch(Text)). close_object gm_text.

(26)

%---% gm_input.

%---open_object gm_input.

super(gm_active).

gmcreate :- self <- gmcreate_input(self), self <- enable.

gmcreate_input(Text) :- self <- update(constructor(input(Text))), self <- gmcreate(self).

gmcreate(Text,Font) :- self <- update(constructor(input(Text,Font))), self <- gmcreate(self).

in(Text) :- self <- gmsend(in(Text)). out(Text) :- self <- gmsend(out(Text)). close_object gm_input. %---% gm_button. %---open_object gm_button. super(gm_active).

gmcreate :- self <- gmcreate(self,self), self <- enable. gmcreate(Name,Message) :- self <-update(constructor(button(Name,Message))), self <- gmcreate(self). gmcreate(Name,Message,Attribute) :-self <-update(constructor(button(Name,Message,Attribute))), self <- gmcreate(self). close_object gm_button. %---% gm_slider. %---open_object gm_slider. super(gm_active).

gmcreate :- self <- gmcreate_slider(self), self <- enable,

self <- value(V),

self <- update(value(V)). gmcreate_slider(Name)

(27)

self <- gmcreate(self), self <- enable.

value(Val) :- self <- gmsend(value(Val)), self <- update(value(Val)). close_object gm_slider. %---% gm_inactive. %---open_object gm_inactive. super(gm_window_content). close_object gm_inactive. %---% gm_output. %---open_object gm_output. super(gm_inactive).

gmcreate :- self <- gmcreate_output(self).

gmcreate_output(Text) :- self <- update(constructor(output(Text))), self <- gmcreate(self).

gmcreate(Text,Font) :- self <- update(constructor(output(Text,Font))), self <- gmcreate(self).

out(Text) :- self <- gmsend(out(Text)). close_object gm_output.

%---% gm_hbox.

%---% create subobjects to this class to describe your different hboxes

open_object gm_hbox.

super(gm_window_content). gmcreate :- bagof1(ContentRef,

(self <- gmnewcontent(ContentRef)), ContentRefs), self <- update(contentref(ContentRefs)),

self <- gmcreate_hbox(ContentRefs).

gmcreate_hbox(Items) :- self <- update(constructor(hbox(Items))), self <- gmcreate(self).

close_object gm_hbox.

%---% gm_vbox.

(28)

%---% create subobjects to this class to describe your different hboxes

open_object gm_vbox. super(gm_window_content). gmcreate :- bagof1(ContentRef,(self <-gmnewcontent(ContentRef)),ContentRefs), self <- update(contentref(ContentRefs)), self <- gmcreate_vbox(ContentRefs). gmcreate_vbox(Items) :-self <- update(constructor(vbox(Items))), self <- gmcreate(self). close_object gm_vbox. %---% gm_menu. %---open_object gm_menu. super(gm_object).

gmcreate :- self <- gmcreate([quit],[quit]). gmcreate(Messages,Items) self <- update(constructor(menu(Messages,Items))), self <- gmcreate(self). close_object gm_menu. %---% gm_graphic. %---open_object gm_graphic. super(gm_object). % dynamic(in_view/1).

% tells in what gm_view object this graphic resides %

% graphicspec(Spec)

% specifies which graphic we are talking about gmnewgraphic(View,GraphicRef) :-self <- new(W), W <- graphicspec(S0), S0=..[Name|Args], S1=..[Name,GraphicRef|Args], View <- gmsend(S1), W <- update(in_view(View)),

(29)

W <- update(gm_ref(GraphicRef)). move(Dx,Dy) :- self <- in_view(W),

self <- gm_ref(R),

W <- gmsend(move(R,Dx,Dy)). moveto(Dx,Dy) :- self <- in_view(W),

self <- gm_ref(R),

W <- gmsend(moveto(R,Dx,Dy)). rotate(Ref,Angle) :- self <- in_view(W),

self <- gm_ref(R),

W <- gmsend(rotate(R,Ref,Angle)). scale(Xs,Ys) :- self <- in_view(W),

self <- gm_ref(R),

W <- gmsend(scale(R,Xs,Ys)). remove :- self <- in_view(W),

self <- gm_ref(R), W <- gmsend(remove(R)), self <- delete. close_object gm_graphic. %---% gm_line. %---open_object gm_line. super(gm_graphic). % graphicspec(line(X1,Y1,X2,Y2)). close_object gm_line. %---% gm_ellipse. %---open_object gm_ellipse. super(gm_graphic). % graphicspec(ellipse(X,Y,R1,R2)). close_object gm_ellipse. %---% gm_fillellipse. %---open_object gm_fillellipse.

(30)

super(gm_graphic). % graphicspec(fillellipse(X,Y,R1,R2)) close_object gm_fillellipse. %---% gm_circle. %---open_object gm_circle. super(gm_graphic). % graphicspec(circle(X,Y,R)) close_object gm_circle. %---% gm_fillcircle. %---open_object gm_fillcircle. super(gm_graphic). % graphicspec(fill_circle(X,Y,R)). close_object gm_fillcircle. %---% gm_rect. %---open_object gm_rect. super(gm_graphic). % graphicspec(rect(X1,Y1,X2,Y2)). close_object gm_rect. %---% gm_fillrect. %---open_object gm_fillrect. super(gm_graphic). % graphicspec(fillrect(X1,Y1,X2,Y2)). close_object gm_fillrect. %---% gm_polygon. %---open_object gm_polygon. super(gm_graphic).

(31)

% graphicspec(polygon(Xedges,Yedges)). close_object gm_polygon. %---% gm_fillpolygon. %---open_object gm_fillpolygon. super(gm_graphic). % graphicspec(fillpolygon(Xedges,Yedges)) close_object gm_fillpolygon. %---% gm_string. %---open_object gm_string. super(gm_graphic). % graphicspec(string(X,Y,Text)). newtext(Text) :- self <- gm_ref(R),

self <- in_view(W), W <- gmsend(newtext(R,Text)). close_object gm_string. %---% gm_bitmap. %---open_object gm_bitmap. super(gm_graphic). % graphicspec(bitmap(X,Y,Filename)). close_object gm_bitmap.

(32)

%---User defined objects based on gm objects

% Examples of user defined objects for gm objects, i.e. use of gm objects

call_me :- gm <- start, my_window <- gmnew(W), W <- open, gm <- run. %---% example of a window containing a possible object (only one NB)

%---open_object my_window. super(gm_window). content(my_vbox). close_object my_window. %---% example of a vertical box

%---open_object my_vbox. super(gm_vbox). content(my_hbox). content(frame(space(gm_button))). content(my_hbox). content(border). content(frame(my_view)). content(my_hbox). content(space(frame(gm_button))). close_object my_vbox. %---% example of a horizontal box

%---open_object my_hbox. super(gm_hbox). content(gm_slider). content(space). content(scroller(my_view)). content(scroller(my_text)). content(gm_output). content(gm_input). content(border). content(gm_button). close_object my_hbox.

(33)

%---% example of a text %---open_object my_text. super(gm_text). % to implement: ... content('my_textfile'). close_object my_text. %---% example of an input %---open_object my_input. super(gm_input). close_object my_input. %---% example of a view %---open_object my_view. super(gm_view). graphic(my_line0). graphic(my_line1). graphic(my_line2). graphic(my_line3). close_object my_view. %---% example of movable lines

%---open_object my_line0. super(gm_line). % in_view/1. % graphicspec(line(X1,Y1,X2,Y2)). graphicspec(line(0,0,100,100)). close_object my_line0. open_object my_line1. super(gm_line). % in_view/1. % graphicspec(line(X1,Y1,X2,Y2)). graphicspec(line(100,100,50,100)). close_object my_line1. open_object my_line2. super(gm_line).

(34)

% in_view/1. % graphicspec(line(X1,Y1,X2,Y2)). graphicspec(line(50,100,0,0)). close_object my_line2. open_object my_line3. super(gm_line). % in_view/1. % graphicspec(line(X1,Y1,X2,Y2)). graphicspec(line(25,50,75,50)). close_object my_line3.

Comments and conclusions

The object hierarchy defined above shows a natural way to utilize SICStus Objects in

the construction of graphical user interface software. Our conclusion is that the

readability, and thereby maintainability, of the code is increased by using SICStus

Objects for applications of this kind. The semantics of the event handling and object

construction is simplified compared to coding in Prolog directly. As usual issues of

this kind are to a large extent a matter of taste, but the example shows that object

orientation can help in clarifying the code of a user interface. The limitations of the

approach have to do with efficiency of component updates rather than expressibility,

something a better compiler might overcome. In the case of user interface design this

limitation is not crucial since there are many other sources of overhead in the user

interface software, such as X-windows.

Acknowledgements

The work presented here was done in the basic program of LPSlab, the Logic

Programming and Parallel Systems Laboratory at SICS, the Swedish Institute of

Computer Science. The basic program is funded by Ericsson Telecom, NobelTech

Systems AB, Televerket, FMV (the Defense Materiel Administration), Asea Brown

Boveri (ABB) and IBM Sweden together with the Swedish government's department

of industry.

The work leading to the implementation of SICStus Objects was made by Seif Haridi

while visiting the American University in Cairo, Egypt, under a contract from the

United Nations [Egy88]. SICStus Objects was later implemented by Seif Haridi and

Kent Boortz. A specification for a similar system was made by the author in [T92:01]

for the project Applied Logic Programming, hosted by LPSlab for Ellemtel

(35)

Utvecklings AB, a development company jointly owned by Ericsson and Televerket,

(the Swedish Telecom).

GM was developed as a part of the IT4-project ISP, Industrialisation of SICStus

Prolog, by Jan Sundberg and Claes Frisk under the supervision of the author. GM has

been further refined by Stefan Andersson and Kent Boortz.

The author wishes to acknowledge Dan Sahlin, Kent Boortz, Ulf Bilting, Stephen

Pope, Lennart E. Fahlén, Janusz Launberg and Per Kreuger for their help in making

this text readable. Mats Carlsson is the main designer of SICStus Prolog. Seif Haridi

initiated and supported the work reported here with many insightful comments in

particular regarding the mechanisms used for inheritance and shadowing in SICStus

Objects.

(36)

References

[ALPES90] J.A.S. Allegria, A. Natali, N. Preston, C. Ruggieri, ALPES Final

Report, Advanced Logic Programming Environments, (ESPRIT P973), CRIL

Frankrike, DEIS, Univ. of Bologna, Italy, ENIDATA, Italy, LRI, Univ. of Paris-Orly

och LSI, Univ. of Toulouse, France, Techn. Univ. of Munich, Germany,

Universidade Nova de Lisboa, Portugal, 1990

[AlAnFlFrNiSu91] J. Almgren, S. Andersson, L. Flood, C. Frisk, H. Nilsson, J.

Sundberg, SICStus Prolog Library Manual, SICS technical report T91:12B,

September 1991

[CaWiJAnSAnBoNiSj91] M. Carlsson, J. Widén, J. Andersson, S. Andersson, K.

Boortz, H. Nilsson, T. Sjöland, SICStus Prolog User's Manual , SICS technical

report T91:11B, September 1991

[Haridi91] S. Haridi, SICS, Expert Systems for Improved Crop Management, report

for the UN, Egy/88/024, September 1991

[Fromherz91] M. P. J. Fromherz, Explore/L An Object-Oriented Logic Language,

Institut für Informatik der Universität Zürich, Nr 91.06, June 1991

[KIWIS91] M. Ahlsén, A D'Atri, P Johannesson, E. Laenens, N. Leone, P. Rullo,

P. Rossi, F. Staes, L. Tarantino, L. Van Beirensdonck, F. van Cadsand, W. Van

Santvliet, J. Vanslembrouck, B. Verdonk, D. Vermeir (ed.), The KIWIS Knowledge

Base Management System, Report 91-23, Universitaire Instelling Antwerpen,

Belgium, March 1991

[McCabe89] F. G. McCabe, Logic and Objects, Ph.D. thesis, Dept. of Computing,

Imperial College of Science and Technology, 1989

[Moss90] C. Moss, An Introduction to Prolog++, Chris Moss, Res. rep. DOC 90/10

Imperial College of Science, Technology and Medicine, London, 1990

[Sahlin90] D. Sahlin, Jämförelse mellan Ada och C++, SICS, 1990, (in Swedish)

[Sjöland92] T. Sjöland, Objektorientering i SICStus Prolog, SICS technical report

T92:01, January 1992 (in Swedish)

(37)

[Shriver87] Eds. B.Shriver and P. Wegner, Research Directions in Object-Oriented

Programming, MIT Press 1987

[Vasey, Spencer et.al.90] P. Vasey, C. Spencer, D. Westwood, A. Westwood,

Prolog++, version 1.0 Programming Reference Manual, Logic Programming

Associates Ltd., London, England, 1990

[Vermeir et.al.89] E Laenens, Philips Applications & Software Services, Eindhoven,

The Netherlands, D. Vermeir, B. Verdonk, Dept. of Computer Science, Univ. of

Antwerp, Belgien, LOCO, a Logic-based Language for Complex Objects. I Proc. of

ESPRIT'89 Technical Conf., Project 2424, pp.604-616 , 1989

[Vermeir et.al.91a] D. Vermeir, Dept. of Mathematics and Computer Science, Univ.

of Antwerp, A simple interface from LOCO to X-Windows, report from ESPRIT

project 2424, 1991

[Vermeir et.al.91b] E. Laenens, D. Vermeir, Univ. of Antwerp, Belgien, N. Leone,

P. Rullo, CRAI Italien, Efficient query evaluation in a language combining

References

Related documents

nRHO-1  induces the release of the neurotransmitter ACh from syn- aptic vesicles [18] but, ACh release is also stimulated in dgk-1 mutants [ 18] and pkc-1(gf) animals [61] neither

B)Now, we often think of such people with a sense of awe and respect as if they were somehow different from us -- better, smarter, more saintly, or more courageous.Sometimes

We have to reflect upon God’s wisdom that places this command within the bounds of a marriage covenant between a man and a woman who have deep love for each other

Using data collected from the Maryland Violent Death Reporting System (MVDRS), this study describes violent death among homeless people in Maryland from 2003 through 2011 in order

• Retrieve your federal loan information from NSLDS • To find other student loans access your credit report. • Pay particular attention to scholarship

Where possible, we offer compliance meetings at no cost to advisors, including at the Spring Symposium.. • Raffle at Symposium to ING Conference – A raffle is held at the

In short, based on the preliminary research above, this research would identify teacher’s types of questions that commonly used in excellent class at MAN Mojokerto and the