1. Trang chủ
  2. » Công Nghệ Thông Tin

Concepts, Techniques, and Models of Computer Programming - Chapter 10 pps

26 245 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 26
Dung lượng 165,71 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

This chapter gives an approach to building graphical user interfaces GUIsthat combines a declarative base together with a selected set of procedural con-cepts including objects and threa

Trang 1

Specialized Computation Models

Trang 3

Graphical User Interface

Programming

“Nowadays the growth of a graphic image can be divided into two

sharply defined phases The process begins with the search for a

visual form that will interpret as clearly as possible one’s train of

thought [ ] After this, to my great relief, there dawns the second

phase, that is the making of the graphic print; for now the spirit can

take its rest while the work is taken over by the hands.”

– The Graphic Work of M.C Escher, M.C Escher (1898–1972)

This chapter shows a particularly simple and powerful way to do graphical userinterface (GUI) programming We combine the declarative model together withthe shared-state concurrent model in an approach that takes advantage of thegood properties of each model To introduce the approach, let us first summarizethe existing approaches:

• Purely procedural The user interface is constructed by a sequence of

graph-ics commands These commands can be purely imperative, as in tcl/tk,object-oriented, as in the Java AWT (Abstract Window Toolkit) package orits extension, the Swing components, or even functional, as in Haskell fud-gets The object-oriented or functional style is preferable to an imperativestyle because it is easier to structure the graphics commands

• Purely declarative The user interface is constructed by choosing from a set

of predefined possibilities This is an example of descriptive declarativeness,

as explained in Section 3.1 A well-known example is HTML (HyperTextMarkup Language), the formatting language used for Web pages

• Using an interface builder The user interface is constructed manually by

the developer, using a direct manipulation interface A well-known example

is Microsoft Visual Studio

Trang 4

The procedural approach is expressive (anything at all can be done at run time)but is complex to use The declarative approach is easy to use (a few simpledeclarations suffice to create an interface) but lacks expressiveness The interfacebuilder approach is easy to use and gives immediate feedback on the interface,but it lacks expressiveness and the interface is hard to change at run time None

of these approaches is satisfactory In our view, this is because each is limited to

a single computation model

This chapter gives an approach to building graphical user interfaces (GUIs)that combines a declarative base together with a selected set of procedural con-cepts including objects and threads We provide a user interface toolkit that isboth expressive and easy to use In the context of the book, this has two goals:

• To present the ideas underlying a practical tool for GUI design that gives

the user a high level of abstraction It turns out that the combination ofdeclarative and non-declarative (i.e., procedural) techniques is particularlyappropriate for graphical user interface design

• To give a realistic example that shows the advantages of programming with

concepts instead of programming in models We start from the declarativeprogramming techniques of Chapter 3 and add state and concurrency ex-actly where it is needed This is a practical example of combining severalcomputation models

To a first approximation, our user interface specifications are just data structures,which can be calculated at run time The declarative model makes it easy tocalculate with symbolic data structures such as records and lists This meansthat we can easily define and manipulate quite sophisticated user interfaces Forexample:

• We build a context-sensitive clock widget, that changes its shape and

pre-sentation depending on an external parameter, which is the window size.Other widgets and external parameters are just as easily programmed

• We show how to generate user interfaces quickly starting from program

data It requires just a few simple data structure manipulations

The ideas in this chapter are embodied in the QTk module, which is part of theMozart system [65] QTk (“Quick Tk”) is a full-featured GUI design tool based

on the declarative approach [66, 67] QTk is implemented as a front end to thetcl/tk graphics package It has been used to build GUIs for real applications.All the examples we give can be run directly with QTk This chapter gives most

of the key ideas underlying QTkbut only shows a small fraction of the availablewidgets

Structure of the chapter

The chapter consists of four sections:

Trang 5

• Section 10.1 introduces the basic concepts underlying declarative and

pro-cedural approaches and how we propose to combine them

• Section 10.2 gives an introduction to the principles of QTk and how to use

it to build user interfaces

• Section 10.3 gives four case studies to progressively illustrate different

as-pects of the approach: a simple progress monitor, a calendar widget, the

automatic generation of a user interface from a data set, and a

context-sensitive clock

• Section 10.4 says a few words about how QTkis implemented

10.1 Basic concepts

What are the relative merits of the declarative and procedural approaches to

specifying user interfaces? The trade-off is between manipulability and

expres-siveness:

• The declarative approach defines a set of possibilities for different attributes.

The developer chooses among this set and defines a data structure that

de-scribes the interface A purely declarative approach makes it easy to

formal-ly manipulate the user interface definitions, e.g., to translate raw data into

a user interface or to change representations However, the expressiveness

is limited because it is only possible to express what the designers initially

thought of

• The procedural approach gives a set of primitive operations and the ability

to write programs with them These programs construct the interface A

purely procedural approach has no limits on expressiveness, since in its

general form it defines a full-fledged programming language However, this

makes it harder to do formal manipulations on the user interface definitions,

i.e., to calculate the user interface

This trade-off is not a temporary state of affairs, to be solved by some ingenious

new approach It is a deep property of computation models As a language

becomes more expressive, its programs become less amenable to formal

manipu-lation This is illustrated by the Halting Problem.1

However, this trade-off is not as bad as it seems on first glance It is still

possible to define a model that is both manipulable and expressive We can do it

by combining the declarative and procedural approaches We use the declarative

1Assume a language as expressive as a Turing machine, i.e., it is based on a general-purpose

computer with potentially unbounded memory Then it is impossible to write a program that,

when given an input program, determines in finite time whether or not the input program will

halt.

Trang 6

approach in those areas where manipulability is important but a limited siveness is sufficient We use the procedural approach for those areas whereexpressiveness is essential To be precise, for each window we define four partsdeclaratively:

expres-• The static structure of the window as a set of nested widgets, where a widget

is a primitive component of a graphical user interface

• The widget types.

• The initial states of the widgets.

• The resize behavior of the window, i.e., how the widgets change size and

relative position when the window size changes

We define two parts procedurally:

• Procedures that are executed when external events happen These dures are called actions Events are external activities that are detected by

When designing a graphical user interface, we recommend to use the ative approach as the primary approach, and to supplement it with proceduralaspects to increase expressiveness exactly where it is needed There is a recentstandard for Web design, Dynamic HTML, that also makes it possible to combinethe declarative and procedural approaches [61] It uses character strings instead

declar-of records for the declarative part It is not as tightly integrated with a gramming language as the approach of this chapter At the time this book waswritten, the performance of the declarative part was not yet adequate to supportthe design approach we recommend

pro-10.2 Using the declarative/procedural approach

As much of the interface as possible is defined declaratively as record values.

Records are a good choice for two reasons: they are very general data structures

and it is easy to calculate with them The GUI consists of a set of widgets, where

each widget is specified by a record Specifying a GUI is done not by defining anew mini-language, but by using records in the existing language Programming

a complex GUI then becomes a simple matter of doing calculations with recordsand lists Since both are strongly supported by the declarative model, thesecalculations are easy to specify and efficient

Trang 7

User interface description: recordcontaining action procedures andunbound variables (for handler objects)

Window on screen

Build user interface

Actions and handler objects

(interpret description to create handler objects and event thread)

Data to be displayed

Calculate user interface description

ApplicationHuman user

Figure 10.1: Building the graphical user interface

10.2.1 Basic user interface elements

The GUI model of this chapter has five basic elements:

• Windows and widgets A window is a rectangular area of the screen that

contains a set of widgets arranged hierarchically according to a particular

layout A widget is a GUI primitive that is represented visually on the screen

and that contains an interaction protocol, which defines its interactions with

a human user A widget is specified by a record, which gives its type, initial

state, a reference to its handler, and some of the actions it can invoke (see

below) An interaction protocol defines what information is displayed by

the widget and what sequences of user commands and widget actions are

acceptable

• Events and actions An event is a well-defined discrete interaction by the

external world on the user interface An event is defined by its type, the

time at which it occurs, and possibly some additional information (such as

the mouse coordinates) Events are not seen directly by the program, but

only indirectly by means of actions An event can trigger the invocation of

an action An action is a procedure that is invoked when a particular event

occurs

• Handlers A handler is an object with which the program can control a

widget Each widget can have a corresponding handler

Trang 8

Figure 10.2: Simple text entry window

10.2.2 Building the graphical user interface

Figure 10.1 shows how a graphical user interface is built It starts with the data

to be displayed This data is manipulated to create a record data structure, the

user interface description This description defines the logical structure of the

interface as a nested record The record contains embedded action proceduresand unbound variables which will become references to handler objects Therecord is passed to a procedure QTk.build, which interprets it and builds theinterface QTk.builddoes two things

• It builds a window using its underlying graphics package.

• It sets up an internal mechanism so that the application can interact with

the window For this, it creates one handler object per widget and onethread per window It registers the action procedures with the widgetsand the events they are triggered on The action procedures are executedsequentially in the thread as window events arrive

An example

The easiest way to see how this works is by means of an example Here is a simpleuser interface description defined as a record:

D=button(text:"Click this button")

The record D defines a widget of button type and the content of the textfieldgives the initial text in the button Other widgets follow the same conventions.The record label denotes the widget type, the field names denote widget param-eters, and the field contents denote either the parameters initial values or theprocedural parts of the interface (actions or handlers)

Some of the widgets are able to contain other widgets By using these, thecomplete user interface is a nested record that defines all the widgets and theirlogical organization on the screen For example, here is a simple interface fordoing text entry (see Figure 10.2):

D=td(lr(label(text:"Type your name:")

entry(handle:H))

button(text:"Ok" action:proc {$} {W close} end))

Trang 9

Figure 10.3: Function for doing text entry

Figure 10.4: Windows generated with thelr and tdwidgets

The tdwidget organizes its member widgets in top-down fashion The lrwidget

is similar, but goes left to right This example has one action, proc {$} {W

close} end, and a handle, H, which we will explain later At this point, both

H and W are still unbound variables Create the window by passing D to the

QTk.build procedure:

W={QTk.build D}

This creates a window, a window objectWthat represents it, and a handler object

H Now we display the window:

{W show}

The user can type text in this window At any time, the text in the window can

be read by calling the handler H:

T={H get($)}

This is usually done when the window is closed To make sure it is done when

the window is closed, we can put it inside the action procedure

To complete this example, let us encapsulate the whole user interface in a

function called GetText Figure 10.3 shows the resulting code Calling GetText

will wait until the user types a line of text and then return the text:

{Browse {GetText "Type your name:"}}

Note that GetText does a {W wait} call to wait until the window is closed

before returning Leaving out this call will return immediately with an unbound

variable that is bound later, when the user clicks the button

Trang 10

Figure 10.5: Window generated with newlineand continuecodes

In addition to the widgets themselves, there are two other aspects of a windowthat are defined declaratively: the geometric arrangement of its widgets and thebehavior of its widgets when the window is resized We describe each in turn Thegeometric arrangement of widgets is defined by means of three special widgetsthat can contain other widgets:

• Thelrandtdwidgets arrange their member widgets left-right or top-down.Figure 10.4 shows the two windows that are displayed with the followingtwo commands:

D=lr(label(text:"left")label(text:"center")label(text:"right"))W1={QTk.build D}

{W1 show}

E=td(label(text:"top")label(text:"center")label(text:"down"))W2={QTk.build E}

{W2 show}

• Theplaceholderwidget defines a rectangular area in the window that cancontain any other widget as long as the window exists The placeholder’scontent can be changed at any time during execution A placeholder may beput inside a placeholder, to any level of recursion In the following example,the window alternatively contains a label and a pushbutton:

placeholder(handle:P)

Trang 11

n

s

Figure 10.6: Declarative resize behavior

• The lr and td widgets support the special codes newline, empty, and

continue, which allows to organize their member widgets in a grid

struc-ture with aligned rows and columns of the same size (see Figure 10.5) The

codenewline makes the subsequent contained widgets jump to a new row

(for lr) or column (for td) All the widgets in the new row or column are

aligned with the widgets in the previous row or column The empty

spe-cial code leaves an empty box the size of a widget The continue special

code lets the previous widget span over an additional box The following

description:

lr(button(text:"One" glue:we)

button(text:"Two" glue:we)button(text:"Three" glue:we) newlinebutton(text:"Four" glue:we)

button(text:"Five" glue:we)button(text:"Six" glue:we) newlinebutton(text:"Seven" glue:we)

button(text:"Eight" glue:we)button(text:"Nine" glue:we) newlineempty button(text:"Zero" glue:we) continue)

gives the window of Figure 10.5

10.2.4 Declarative resize behavior

When the size of a window is changed, the interface has to define how the internal

widgets rearrange themselves This is called the resize behavior The resize

behavior is dynamic, i.e., it defines a behavior over time But it is a sufficiently

restricted kind of dynamic behavior that we can define it using a descriptive

declarative model

Trang 12

Figure 10.7: Window generated with the glueparameter

We define the resize behavior of a widget by an optional glue parameter, whose

value is an atom made up of any combination of the letters n, s, w, and e Theglue parameter places constraints on how the widget is placed and how it resizes

As Figure 10.6 illustrates, a widget W is always placed inside a rectangular areaand has a “natural” size defined by its contents One can choose for the widget

to occupy its natural size in either direction (horizontally or vertically) or to beexpanded to take as much space as possible in either direction For the left-right direction, the w value, when present, will attach the widget to the left side(“west”) The same for the e value (“east”) and the right side If w and e arepresent simultaneously, then the widget is expanded Otherwise, it takes up justits natural size For the top-down direction, the n and s values play the sameroles (“north” and “south”) For example, the description:

lr(label(text:"Name" glue:w) entry(glue:we) glue:nwe)

gives the window of Figure 10.7

The dynamic behavior of widgets is defined by means of action procedures andhandler objects Look again at the example of Section 10.2.2:

declare E D W in

D=td(lr(label(text:"Type your name:")

entry(handle:E))button(text:"Ok" action:toplevel#close))W={QTk.build D}

{W show}

The action toplevel#closeis part of the button; when the button is clickedthen this causes the window to be closed Generally, actions are zero-argumentprocedures, except that short-cuts are given for a few common actions such asclosing the window The handle E is an object that allows to control the textentry widget For example, here’s how to set the value of the widget’s text entryfield:

Trang 13

{E set("Type here")}

Here is how to read and display the value of the field:

{Browse {E get($)}}

Actions can also be attached to events such as mouse clicks:

proc {P} {Browse ´clicked with third mouse button!´} end

{E bind(event:"<3>" action:P)}

The event "<3>" means a click of the third mouse button Attaching it to E

means that the button has to be clicked when the mouse is over E’s widget A

complete list of possible events is given in the QTk documentation in the Mozart

system

10.3 Case studies

We present four case studies that show different techniques of user interface

de-sign:

• The first is a simple progress monitor This example has no special features

except to show how simple it is to build a custom display for a particular

purpose

• The second builds a simple calendar widget It is based on an lr widget

with gridding ability It shows the flexibility of the gridding It also shows

how to use a placeholder and how state can be introduced to optimize

execution of what is originally a purely declarative calculation

• The third derives two different GUIs by transforming one data model into

two GUI specifications The user can switch between the two at any time

This shows the advantage of tightly integrating the GUI tool with the

lan-guage, since different data models can be represented with the same data

structures (e.g., records and lists) and transformed with the same

opera-tions

• The fourth defines a clock with an interface that adapts itself according to

an external condition The best view of the clock data is chosen dynamically

depending on the window size Because of the mixed declarative/procedural

approach, each view can be completely defined in just a few lines of code

The second through fourth case studies were originally written by Donatien

Gro-laux

We start by defining the simple interface that we used in Section 5.5.1 to monitor

the progress of a message-passing program The interface has a check button

Ngày đăng: 14/08/2014, 10:22