CGLIB
A
Constraint-based Graphics Library for B-Prolog
(Version 6.5)
By Neng-Fa Zhou
Copyright © Afany Software,
2000-2003
The widespread use of window systems has made a graphics package
indispensable for any programming languages. Prolog is not an exception,
although graphics is not part of the ISO standard. Some efforts have been made
to introduce graphics programming into Prolog. One widely used approach is to
adopt an external language interface with a language that supports graphics
programming. For example, JIPL is an interface developed by KLS Inc. that
bridges Prolog and Java bi-directionally. A Prolog system that adopts an interface like this will be able to access the graphics library of Java. This approach is
not satisfactory for the following two reasons. First, you have to write code in two languages. This is especially daunting when there
are interactions involved. Second, the graphics library in the adopted
language, whether it is C, C++, Java, VB, or Tcl/Tk, is at such a low level
that it does not match well with a high-level language like Prolog. Prolog, and
CLP (Constraint Logic Programming) languages in general, should have a graphics
library that provides high-level abstraction for specifying the states,
layouts, and behaviors of graphical objects.
Motivated by the observations, we designed and implemented a high-level
and constraint-based graphics library, called CGLIB, for B-Prolog. The
library provides primitives on graphical objects and provides various kinds of
constraints that facilitate the specification of layouts of graphical objects.
The constraint solver of B-Prolog serves as a general-purpose layout manager
that is significantly more flexible than the special-purpose layout managers
used in Java and Tck/Tk. The library adopts a construct called action rules available in B-Prolog for
programming interactions. An action rule consists of a pattern for agents, a
pattern for events that can activate the agents, and an action the agents carry
out when activated. Agents can communicate with each other through logical
variables or global variables. Agents can behave concurrently and sequentially
as well.
CGLIB
enables you to use the Java graphics package without the need to write any code
in Java. CGLIB, however, is not just another syntactical sugar for Java’s
graphics package. It has a significantly higher abstraction level and is much
easier to learn and use than Java’s graphics package. One of prominent features
of CGLIB is the use of constraints in the specification of layouts. In graphics languages such as PostScript and
Tex, you have to
specify every single detail about the graphical objects, including their sizes
and positions. In languages such as Java and Tcl/Tk, the layout managers help
determine the layouts of objects for certain applications, but the layout
algorithms lack flexibility and are difficult to learn and use. The use of
action rules to describe event handling is another feature of CGLIB. Action
rules can be used to describe sophisticated and dynamic behaviors of graphical
objects in a simple and straightforward manner.
CGLIB
can be used in many areas such as drawing editors, interactive user interfaces,
animation, information visualization, intelligent agents, and games. This manual describes the library and its usage. More
example
programs are available at www.probp.com.
1.3 Start and quit B-Prolog with CGLIB
1.4 Draw graphics and
clean windows
2.4 Menu bars, menus and
menu items
3.3 Grid and table
constraints
4.1 Packing and Showing
Objects
4.2 Altering and Moving
Objects
Agent ConditionSeq {Event} => ActionSeq
8.3 Drawing a diagram of Java AWT’s classes
8.6 Demonstrating a geometry theorem on quadrilaterals
Appendix-I. Built-in Components
Appendix-III. Built-ins for Testing Key Codes
Let us start with the following program to taste
the flavor of CGLIB:
go:- cgButton(B,“Hello World”), (1)
handleButtonClick(B), (2) cgShow(B). (3) handleButtonClick(B),{actionPerformed(B)} => abort.
The call cgButton(B,“Hello
World”) in line
(1) creates a button B with
the label “Hello World”. Line (2) creates an event
handler, which will be activated when the button B is clicked. The call cgShow(B) in line (3) packs the button, i.e.,
determines the size and position of the button, and shows the button in the
default window. In our example, nothing is mentioned about the color and font
of the text, the size of the button and the position of the button in the
window. The system will determine the attribute values for us either by using
the constraints we provided or by using the default values. The rule
handleButtonClick(B),{actionPerformed(B)} => abort.
defines the event handler handleButtonClick(B). The term enclosed in the pair of braces, actionPerformed(B), is called an event, and the right hand side of the rule, abort, is called an action. When an event actionPerformed(B)is posted, i.e, when the button B is clicked, the program execution terminates. In
general, an action can be any sequence of sub-goals.
Currently
CGLIB runs on Windows only. To install the system, follow the following steps:
1.
Make
sure that Java is installed already. The library was tested with J2SDK1.4.1.
2.
Download
the package bp6x_win.zip and save it the directory c:\.
3.
Extract
the files from the archive by using jar in
JSDK as
jar xfv bp6x_win.zip
4. Add the following settings
to C:\autoexec.bat:
set BPDIR=c:\BProlog
set
path=%BPDIR%;%path%
set
CLASSPATH=.;%BPDIR%\plc.jar;%BPDIR%\cg.jar
On Windows 2000/NT/XP, you need to open Control Panel,
click on "system", then "details", and then
"environment variables" to add the setting.
5.
Restart
your computer.
Notice that the environment
variable BPDIR must be reset correctly if
the system is installed in a directory other than c:\.
To start B-Prolog with CGLIB, double click the
file bpp.bat in the folder c:\BProlog\bin. You can use the predicate chdir to change the working directory. For example,
chdir(‘c:\BProlog\examples\cg’).
You can use the predicate system to execute an OS command. For example,
system(‘dir *.pl’).
Another way to start B-Prolog is to open an MS-DOS terminal and type bpp in the command line. After the system is started, it responds with
the prompt |?- and is ready to accept Prolog queries.
To quit the system, use the query:
halt
or simply enter ^D
(control-D) when the terminal has the focus.
To open a window, type the
command:
?- cgWindow(W),cgShow(W)
cgWindow(W) creates a window and cgShow(W) shows the window. There is a default window
to which all graphical objects will be sent if the window is not specified
explicitly. To open the default window, type:
?-
cgDefaultWindow(W),cgShow(W)
or
?-
cgShowDefaultWindow
A
window has the default
title “UntitledWindow” if no title is given explicitly. A window can be given a title. For
example, the following command shows a window with
the title “MyWindow”.
?- cgWindow(W,“MyWindow”),cgShow(W)
To close a window W, simply use the primitive cgClose(W). For example, the following command opens a window and closes it
immediately.
?-
cgWindow(W),cgShow(W),cgClose(W)
The primitive cgCloseDefaultWindow closes the default window.
There are primitives for creating and showing
various kinds of graphical objects. The following command draws a five-point
star whose outer circle is 100 pixels wide.
?-cgStar(S),S^width #= 100,S^n #=
5,cgShow(S)
The default size for each object is 20 by 20 pixels and the default position is left-upper corner of the window, i.e., (0,0). So, if the constraint S^width #= 100 were missing, the star would be covered by the window’s title bar.
The constraint S^n #= 5 states that the number of points in the star is five. The default value for the attribute n of a star is 5. So, the following command has the same effect:
?-cgStar(S),S^width #= 100,cgShow(S)
The area of the star is filled with the default color, which is black. To draw a star with a different color or other attribute values, you have to specify so by using constraints. For example,
?-cgStar(S),S^width #= 100,S^fill #=
0,cgShow(S)
draws an unfilled 5-point star, and
?-cgStar(S),S^width #= 100,S^color #=
red,cgShow(S)
draws a filled red star.
If no window is given, then all objects will be drawn on the default window. The following command draws a star on a designated window.
?-cgWindow(W), cgStar(S), S^window #= W,
cgShow(S)
The constraint S^window #= W specifies the window to which the star is to be sent. When the system draws an object on a window, it automatically opens the window.
If multiple objects are drawn on the same window and the objects overlap, then part of the previously drawn objects will be overwritten by the objects drawn later. So, the following command
?-cgCircle([C1,C2]),cgShow([C1,C2]).
draws two circles, but only one will be visible. Constraints can be used to restrict the layout for objects. For example, the following command draws two circles that do not overlap.
?-cgCircle([C1,C2]),cgNotOverlap([C1,C2]),cgShow([C1,C2]).
To clean a window, use the primitive cgClean(W). For example, the following command draws a star on a window and then cleans the window immediately.
?-cgWindow(W),cgStar(S),S^window #=
W,cgShow(S),cgClean(W)
To clean the default window, use the primitive cgCleanDefaultWindow. The following command cleans the default window before drawing a star onto it.
?-cgCleanDefaultWindow, cgStar(S), cgShow(S)
Each
object is represented
as a structure
of Prolog. Each object has a certain number of attributes and each attribute
has a name and a domain. There are two kinds of attributes, namely constrainable
and non-constrainable. Constrainable attributes can be referenced by the
notation O^attr
where O is
an object and attr is
the name of an attribute. Constrainable attributes can occur in constraints.
For example, the equality constraint O1^x
#= O2^x enforces the two objects O1 and O2 to
have the same x coordinate, and the inequality constraint O^width #> 20
ensures that the width of O is greater than 20 pixels. Notice that in other contexts this notation is treated just
as a normal
Prolog term! Non-constrainable attributes must be accessed and
updated by using get and set primitives. For example, the primitive
·
cgGetBackground(O,Color)
succeeds
if the background color of O is Color, and the primitive
·
cgSetBackground(O,Color)
sets
the background color of O to
be Color. Updates of attribute
values through the set primitive are destructive and will not be undone upon
backtracking.
Objects are classified into
the following different types:
·
Attribute
objects
·
Windows
·
Graphical
objects
·
Menus
and menu items
·
File
dialogs
Attribute objects such
as fonts and points serve as attribute values of other objects. Windows and graphical
objects are treated in a different way in the sense that every graphical object
has a window as its container but a window does not have a container.
The following object types
are introduced to facilitate constraining the attribute values of graphical
objects: dimension, point, font, and color.
·
cgDimension(D): Create or test a dimension object or a
list of dimension objects D. A dimension object has two
constrainable attributes,
namely, width and height.
· cgPoint(P): Create or test a point object or a list of point objects P. A point object has two constrainable attributes, namely, x and y.
·
cgFont(F): Create or
test a font object
or a list of font objects F. A font object has three constrainable
attributes:
·
name: A font name may be one of
the following:
[“Dialog”,”TimesRoman”,”Helvetica”,”DialogInput”,
“ZapfDingbats”]
·
size: An integer greater than 6.
The default size
is 10.
·
style: The domain is:
[plain, bold, italic,
bold_italic].
·
cgColor(C): Create or test a RGB object or a list of RGB objects. A RGB object has the following three constrainable attributes:
·
red: The redness of the color, which is an integer from 0 to 255.
·
green: The greenness of the color, which is an integer from 0 to 255.
·
blue: The blueness of the color, which is an integer from 0 to 255.
A window has the following constrainable
attributes:
·
x: The x-coordinate of the
top-left corner of the window on the screen.
·
y: The y-coordinate of
top-left corner of the window on the screen.
·
width: The width of the window.
·
height: The height of the window.
·
leftMargin: The
width of the left margin. No objects will be placed by the packer in the
margins unless the x-coordinates are set explicitly.
·
topMargin : The
height of the top margin.
·
color: The color
of the window.
The domains of the
integer attributes are non-negative.
The
following primitives are provided for accessing and updating non-constrainable
attributes: title, visible, and
menuBar.
·
cgGetTitle(W,Title):
The title of the window W is Title.
·
cgSetTitle(W,Title):
Set the title of the window W to Title.
·
cgIsVisible(W): Window W is
visible.
·
cgSetVisible(W,OneOrZero):
Show or hide the window W
where OneOrZero must be either 1 or
0.
·
cgSetMenuBar(W,MenuBar): Set the menu bar of the window W to MenuBar
(see menu bar below).
In addition to the get and
set primitives, the following primitives
are
available on windows:
·
cgWindow(W): Create or test a window or a list of windows.
·
cgWindow(W,Title): Create a window W with a title.
·
cgShow(W): Show the window W.
·
cgClose(W): Close the window W. No object in a window can be re-shown once the
window is closed.
·
cgClean(W): Clean the window W by removing all the components from the window.
·
cgCleanDrawing(W): Clean the window W by removing all the graphics components from the
window. Control components (see below) are not removed.
For example, the following
command creates a 100 by 100 window:
?-cgWindow(W),W^width
#= 100, W^height #= 100,cgShow(W)
The default window is
created when the system is started. To access it, use the primitive
·
cgDefaultWindow(W)
The following primitives
manipulate the default window without explicitly referencing
it.
·
cgShowDefaultWindow
·
cgCloseDefaultWindow
·
cgCleanDefaultWindow
The following primitives are
provided for creating and testing various kinds of graphical objects:
· cgArc(O)
·
cgButton(O)
· cgCheckbox(O)
· cgChoice(O)
· cgCircle(O)
· cgImage(O)
· cgLabel(O)
· cgLine(O)
· cgList(O)
· cgOval(O)
· cgPolygon(O)
· cgRectangle(O)
· cgRoundRectangle(O)
·
cgScrollbar(O)
·
cgSquare(O)
·
cgStar(O)
·
cgString(O)
·
cgTextArea(O)
·
cgTextBox(O)
·
cgTextField(O)
·
cgTriangle(O)
Where O is a variable, an object, a
list of variables, or a list of objects. For example, cgArc(A) creates an arc A and cgArc([A1,A2,A3])creates a list of arcs A1, A2, and A3. Figure
1 shows how each object type looks like.
Each
object has the following constrainable
attributes:
·
window: The containing window of
the object.
·
x: The x-coordinate of the
top-left corner of the object. Let LM be the left margin of the
enclosing window. The value of this attribute is no less than LM.
·
y: The y-coordinate of
top-left corner of the object. Let TM be the top margin of the
enclosing window. The value of this attribute is no less than TM.
·
width: The width of the object.
The domain of this attribute is the set of positive integers.
·
height: The height of the object.
The domain of
this attribute is the set of positive integers.
·
color: The value is a color object created by cgColor or one of the following constants.
[black, blue, cyan, darkGray, gray, lightGray, magenta, orange, pink, red, white, yellow]
For object types such as Button, List, TextArea, and TextField, the color attribute
indicates the foreground color. The primitives cgGetBackground and cgSetBackground can be used to access and update the
background color.
The
object types Button,
Checkbox,
Choice,
Label,
List,
String, TextField, TextBox, and TextArea have the
following attributes in addition to the attributes listed above:
·
font: The font used for the
text.
·
fontName: For each object O, O^font #= F, O^fontName #= F^name.
·
fontSize: For each object O, O^font #= F,
O^fontSize #= F^size.
·
fontStyle: For each object O, O^font #= F,
O^fontStyle #= F^style.
The following
attributes, called virtual attributes, are provided to facilitate the
description of object layouts.
·
size: For each object
O,
O^size #= D, D^width #=
O^width, D^height #= O^height.
·
centerX: For each object O, O^centerX #= O^x+O^width//2, where the operator // indicates integer division.
·
centerY: For each object O,
O^centerY #= O^y+O^height//2.
·
rightX: For each object O,
O^rightX #= O^x+O^width.
·
bottomY: For each object O,
O^bottomY #= O^y+O^height.
·
center:
For each object
O,
O^center #= P, P^x #= O^centerX, P^y #= O^centerY.
·
leftTopPoint: The left-top point.
·
leftBottomPoint: The left-bottom point.
·
rightTopPoint: The right-top point.
·
rightBottomPoint: The right-bottom point.
These attributes
are constrainable. They are called virtual since they are derived from the base
attributes x, y, width,
and height. Virtual attributes are created on the fly when they are
accessed. For instance, when the attribute centerX
of an object O is accessed, the
system creates a variable V as
the value of the attribute and generates the constraint
V #= O^x+O^width//2.
Virtual attributes
cannot be destructively updated by the operator #:= (see below).
Figure 1. Primitive graphical objects.
Each object has a
non-constrainable attribute, called visible,
which can be tested by using the primitive cgIsVisible(O) and updated by using the primitive cgSetVisible(O,OneOrZero).
In addition to the
get and set primitives for non-constrainable attributes, the following
primitives are provided on all graphical objects:
·
cgShow(O): Show O, which can be a graphical object or a list of
graphical objects.
·
cgPack(O): Pack O, i.e.,
determine the attribute values of O based
on the constraints on O.
·
cgClean(O): Remove
O from its window.
The following types
of objects are called AWT control components: Button, Checkbox, Choice,
List, Scrollbar, TextField,
and TextArea. These types of objects have the following two
additional non-constrainable attributes: enabled
and cursor. The following primitives are provided for
accessing and updating the attribute values:
·
cgSetEnabled(O,OneOrZero):
Enable the component if OneOrZero is
1 and disable it if 0. Only enabled control components can post events.
·
cgIsEnaled(O):
The component O is
enabled.
·
cgSetCursor(O,Cursor):Set the current cursor to Cursor when the component has the focus, where Cursor must be one of the following:
o crosshair_cursor
o default_cursor
o e_resize_cursor
o hand_cursor
o move_cursor
o n_resize_cursor
o ne_resize_cursor
o nw_resize_cursor
o s_resize_cursor
o se_resize_cursor
o sw_resize_cursor
o text_cursor
o w_resize_cursor
o wait_cursor
·
cgGetCursor(O,Cursor):The current cursor set to the component O is Cursor.
Each object type has some additional attributes and primitives as described in the following. The complete specification
of attributes and primitives is given in Appendix I.
Constrainable attributes
·
fill:
Filled
if 1 and unfilled if 0.
·
startAngle: The
starting angle
of the arc. O^startAngle
in 0..360.
·
arcAngle: The size of angle. O^arcAngle in 0..360.
Get and set primitives
·
cgSetText(O,Text):
Set the text to be shown on the button O to
be Text, which must be a string. Notice
that a string in Prolog is represented as a list of codes of the characters in
the string. For example, “123”, “hello”, and [98,97]
are valid
strings.
·
cgGetText(O,Text):
The text shown on the button O is Text.
Other primitives
·
cgButton(O,Text): Create
a button and set its text to be Text.
·
cgButton([O1,...,On],[T1,...,Tn]):
Create a list
of buttons whose ith button has Ti as the text.
Get and set primitives
·
cgSetText(O,Text):
Set the text of the checkbox O to
be Text.
·
cgGetText(O,Text):
The text of the checkbox O is Text.
·
cgSetState(O,OneOrZero):
Set the state of the checkbox O to
be checked if OneOrZero is
1 and to be unchecked if OneOrZero is
0.
·
cgGetState(O,State):
The state of the checkbox O is
State.
Other primitives
· cgCheckbox(O,Text): Create a checkbox with the text Text.
· cgCheckbox([O1,...,On],[T1,...,Tn]): Create a list of checkboxes with the texts T1,..., and Tn, respectively.
· cgCheckboxGroup([O1,…,On]):The checkboxes O1,…,On form a group in which only one can be checked.
Constrainable attributes
· count: The number of items in the choice.
·
item(I): The Ith item, where I must be an integer between
1 and the count.
Other primitives
· cgChoice(O,[T1,…,Tn]): Create a choice with a list of items where T1,…,Tn must be strings .
· cgAdd(O,T): Add a string or a list of strings to the choice object O.
· cgAdd(O,T,Index): Add a string to the choice object O at the specified position.
· cgRemove(O,T): Remove an item or a list of items from the choice object.
· cgSelect(O,T): Set the selected item to be T.
· cgSelectedItem(O,T): The selected item of choice O is T.
Constrainable attributes
·
fill:
Filled
if 1 and unfilled if 0.
·
diameter: O^width #= O^height and O^diameter #= O^width.
Constrainable attribute
·
name: The name of the image
file.
Get and set primitives
·
cgGetText(O,Text):
The text of the label O is Text.
·
cgSetText(O,Text):
Set the text of the label.
·
cgGetAlignment(O,Align):
The current alignment of the label O is Align.
·
cgSetAlignemnt(O,Align):
Set the alignment of the label O to Align, which must be left, center, or
right.
Other primitives
·
cgLabel(O,Text):
Create a label with the text Text.
·
cgLabel([O1,...,On],[T1,...,Tn]): Create a list of labels
with specified texts.
Constrainable attributes
·
point1,
point2: The starting and ending points.
·
x1,y1,x2,y2: The
coordinates of the starting and ending points.
O^x1 #>=
O^x, O^y1 #>= O^y,
O^x1 #=< O^rightX, O^y1 #=< O^bottomY.
The same constraints are also imposed on x2 and y2.
·
thickness: Thickness of the line.
·
arrow1: There is an arrow at point1 if 1
and none otherwise.
·
arrowLength1: The length of the arrow at point1.
·
arrowThickness1: The thickness of the arrow at point1.
·
arrow2: There is an arrow at point2 if 1
and none otherwise.
·
arrowLength2: The length of the arrow at point2.
·
arrowThickness2: The thickness of the arrow at point2.
Constrainable attribute
·
count: The number of items in the list.
·
item(I): The Ith item, where I must be an integer between
1 and the count.
Other primitives
· cgList(O,[T1,T2,...,Tn]): Create a list O and then add T1,T2,...,Tn to the list as items.
· cgAdd(O,T): Add a string or a list of strings to O.
· cgAdd(O,T,Index): Add a string to the list object O at the specified position.
· cgRemove(O,T): Remove an item or a list of items from the list O
· cgSelect(O,T): Set the selected item to be T.
· cgSelectedItem(O,T): The selected item of list O is T. T is bound to [] if no item or multiple items are selected.
· cgSelectedItems(O,T): T is the list of selected items of list O.
Constrainable attribute
·
fill:
Filled
if 1 and unfilled if 0
.
Constrainable attributes
·
fill:
Filled
if 1 and unfilled if 0.
·
n: The number of points.
·
x(I): The x-coordinate of the Ith
point (1
#=< I, I #=< O^n).
·
y(I): The y-coordinate of the Ith
point (1
#=< I, I #=< O^n).
·
point(I): The Ith point (1 #=< I, I #=< O^n).
Constrainable attributes
·
fill:
Filled
if 1 and unfilled if 0.
·
RoundRectangle
Constrainable attributes
·
fill:
Filled
if 1 and unfilled if 0.
·
arcWidth: The width of the round angle.
O^arcWidth
#>=0, O^arcWidth #=< O^width/2.
·
arcHeight: The height of the round angle.
O^arcHeight
#>=0, O^arcHeight #=< O^height/2.
·
Scrollbar
Get and set primitives
·
cgGetBlockIncrement(O,Val): The block
increment of the scroll bar O is Val.
· cgSetBlockIncrement(O,Val): Set the block increment of the scroll bar O to be Val.
·
cgGetMaximum(O,Max): The maximum
value of the scroll bar O is Min.
·
cgSetMaximum(O,Max): Set maximum
value of the scroll bar O to be Min.
·
cgGetMinimum(O,Min): The minimum value of
the scroll bar O is Min.
·
cgSetMinimum(O,Min): Set the minimum value of
the scroll bar O to be Min.
·
cgGetOrientation(O,Orient): The orientation
of the scroll bar O is Orient.
·
cgSetOrientation(O,Orient): Set the
orientation of the scroll bar O to be Orient, which must be either horizontal or vertical.
·
cgGetUnitIncrement(O,Val): The unit
increment of the scroll bar O is Val.
·
cgSetUnitIncrement(O,Val): Set the unit
increment of the scroll bar O to be Val.
·
cgGetValue(O,Val): The current
value minimum value of
the scroll bar O is Val.
·
cgSetValue(O,Val): Set the
current value minimum value of
the scroll bar O to be Val.
·
cgGetVisibleAmount(O,Val): The visible
amount of the scroll bar O is Val.
·
cgSetVisibleAmount(O,Val): Set the
visible amount of the scroll bar O to be Val.
Other primitives
·
cgScrollbar(O,Orient): Create a
scrollbar that has the orientation Orient, which must be either horizontal or vertical.
·
cgScrollbar(O,Orient,Value,VisibleAmount,Min,Max): Create a new
scroll bar with the specified orientation, initial value, page size, and
minimum and maximum values.
· Square
Constrainable attributes
·
fill:
Filled
if 1 and unfilled if 0.
Constrainable attributes
·
fill:
Filled
if 1 and unfilled if 0.
·
n: The number of points. O^n #>=0.
·
x0,y0: The coordinate of the first
point.
·
angle0: The angle between the x-axis and
the line going from the center of the star to the first point.
·
innerDiameter: The diameter of the inner circle.
·
String
Get and set primitives
·
cgSetText(O,Text):
Set the text of the string.
·
cgGetText(O,Text):
The text of the string O is Text.
·
cgSetAlignemnt(O,Align):
Set the alignment of the string O to Align, which must be left, center, or
right.
·
cgGetAlignment(O,Align):
The current alignment of the string O is Align.
Other primitives
·
cgString(O,Text): Create a string object with the text Text. A string object is similar to a label but is
drawn by using drawString in Java.
·
cgString([O1,...,On],[T1,...,Tn]): Create a list of string
objects with specified texts.
· TextArea
Get and set primitives
·
cgSetText(O,Text):
Set the text of the area.
·
cgGetText(O,Text):
The text of the text area O is Text.
·
cgSetRows(O,NumOfRows):
Set the number of rows of the the area.
·
cgGetRows(O,NumOfRows):
The number of rows of the the area is NumOfRows.
·
cgSetColumns(O,NumOfColumns):
Set the number of columns of the the area.
·
cgGetColumns(O,NumOfColumns):
The number of columns of the the area is NumOfColumns.
·
cgSetEditable(O,OneOrZero):
Set the flag that determines whether or not the text area is editable.
·
cgIsEditable(O):
The text area O is
editable.
Other primitives
· cgTextArea(O,T): Create a text area with text T in it.
·
cgAppend(O,T):
Append the string T to
the end of the current text of the text area O.
·
cgInsert(O,T,Pos):
Insert the text T into the text area at the specified position.
Get and set primitives
·
cgSetText(O,Text):
Set the text of the text box.
·
cgGetText(O,Text):
The text of the text box O is Text.
·
cgSetAlignemnt(O,Align):
Set the alignment of the text box O to Align, which must be left, center, or
right.
·
cgGetAlignment(O,Align):
The current alignment of the text box O is Align.
Other primitives
·
cgTextBox(O,Text): Create a text box with the text Text. A text box is similar to a string but it is
surrounded by a rectangle.
·
cgTextBox([O1,...,On],[T1,...,Tn]): Create a list of text
boxes with specified texts.
·
TextField
Get and set primitives
·
cgSetText(O,Text):
Set the text of the area.
·
cgGetText(O,Text):
The text of the text area O is Text.
·
cgSetColumns(O,NumOfColumns):
Set the number of columns of the text field.
·
cgGetColumns(O,NumOfColumns):
The number of columns of the text field is NumOfColumns.
·
cgSetEditable(O,OneOrZero):
Set the flag that determines whether or not the text field is editable.
·
cgIsEditable(O):
The text field O is
editable.
Other primitives
· cgTextField(O,T): Create a text field with text T in it.
·
Triangle
Constrainable attributes
·
fill:
Filled if 1 and unfilled if 0.
·
point1,point2,point3: The three points.
·
x1,y1,x2,y2,x3,y3: The xy-coordinates of the three
points.
Each window has a menu bar to which menus can be
attached. Each menu contains a list of menu items which themselves can be
menus.
·
Menu items
A menu item has a name. A menu item with the name “-“
will serve as a separator. Menu items can be created and tested by the
following primitives:
· cgMenuItem(I): Create or test a menu item or a list of menu items.
·
cgMenuItem(I,Text): Created a menu item named Text.
· cgMenuItem([I1,...,In],[T1,...,Tn]): Create a list of menu items with specified names.
·
cgSetText(I,Text):
Set
the text of the menu item I to Text.
·
cgGetText(I,Text):
The
text of the menu item I is Text.
·
Checkbox menu
items
A checkbox menu item is a menu item, and can be checked or unchecked.
· cgCheckboxMenuItem(I): Create or test a checkbox menu item or a list of checkbox menu items.
·
cgCheckboxMenuItem(I,Text): Create a checkbox menu item named Text.
· cgCheckboxMenuItem([I1,...,In],[T1,...,Tn]): Create a list of checkbox menu items with the specified names.
·
cgSetText(I,Text):
Set
the text of the checkbox menu item I to Text.
·
cgGetText(I,Text):
The
text of the checkbox menu item I is Text.
·
cgSetState(I,OneOrZero):
Set
the state of the checkbox menu item to checked if OneOrZero is 1 and to unchecked if 0.
·
cgGetState(I,State):
State is 1 if the state of the checkbox menu item is
checked and 0 if unchecked.
·
Menus
A menu is a menu item to which other menu items can be added.
·
cgMenu(M): Create or test a menu or a list of menus.
·
cgMenu(M,Text): Create a menu with a specified name.
·
cgMenu([M1,...,Mn],[T1,...,Tn]): Create a list of
menus with
the specified names.
·
cgSetText(I,Text):
Set
the text of the menu to Text.
·
cgGetText(I,Text):
The
text of the menu is Text.
· cgAdd(Menu,Items) : Add Items, a list of menus or menu items, to Menu.
· cgRemove(Menu,Items) : Remove Items, a list of menus or menu items, from Menu.
·
Menu bars
The primitive cgSetMenuBar(Win,MenuBar) sets the menu bar MenuBar to the window Win. The following
primitives are available on menu bars.
·
cgMenuBar(B): Create or
test a menu bar B.
·
cgMenuBar(B,Menus): Create
a menu bar B with the list of menus Menus.
· cgAdd(MenuBar,Items) : Add Items, a list of menus, to MenuBar
· cgRemove(MenuBar,Items) : Remove Items, a list of menus, from MenuBar
Example
The following program builds the menu shown in Figure 2.
go:-
cgMenuItem([Iopen,Iprint,Ijpeg,Igif,Sep],
["Open","Print","JPEG","GIF","-"]),
cgMenu([Mfile,Medit,Mhelp,Msave],["File","Edit","Help","Save"]),
cgCheckboxMenuItem(Icheck,"Checkme"),
cgAdd(Msave,[Ijpeg,Sep,Igif]),
cgAdd(Mfile,[Iopen,Msave,Iprint,Icheck]),
%
cgDefaultWindow(Win),
cgSetMenuBar(Win,MB),
cgAdd(MB,[Mfile,Medit,Mhelp]),
cgShow(Win).
A file dialog is a window
that allows you to input file names. To create a file dialog, use the
primitive:
·
cgFileDialog(F): Create or test a file
dialog F.
A file dialog has the following attributes:
·
parent: the parent window of the
dialog, which will be the default window if no window is explicitly given.
·
mode: the value is
either save or load.
The following primitives
are available on file dialogs:
·
cgSetTitle(F,Title): Set
the title of the file dialog to Title.
·
cgGetTitle(F,Title): The
current title of the file dialog is Title.
·
cgGetFile(F,File): The
file name input by the user is File.
·
cgGetDirectory(F,Directory): The
directory the file resides is Directory.
As we have already seen, we
can use the notation O^a to access constrainable
attributes of objects and use equality (#=), disequality (#\=), and inequality (#>, #>=, #<, #=<) constraints to constrain
the values of attributes. In addition to these constraints, there are symbolic
constraints that can be used to constrain attributes of objects without referencing
the attributes directly.
Constraints in this group
restrict the relative positions of objects.
·
cgInside(O1,O2): O1 is located inside O2.
·
cgOutside(O1,O2): equivalent to cgInside(O2,O1).
·
cgLeft(O1,O2): O1 is located to the left of O2.
·
cgRight(O1,O2): equivalent to cgLeft(O2,O1).
·
cgAbove(O1,O2): O1 is placed above O2.
·
cgBelow(O1,O2): equivalent to cgAbove(O2,O1).
The argument O1 or O2 can be one object or a list of objects.
Constraints in this group
force a list of objects to have the same value for a constrainable attribute.
·
cgSame(L,AttributeName): The values of AttributeName of the objects in list L are all the same.
·
cgSame(L,AttributeName,Value): The values of AttributeName of the objects in list L are all the same as Value.
For example, the constraint cgSame([O1,O2,O3],size) enforces the three objects O1,O2, and O3 to have the same size.
The grid and table
constraints may be the most powerful constraints in CGLIB. The grid constraint
enforces objects to be placed on a grid board where all the grid cells are of
the same size. The table constraint is not as restrictive as the grid
constraint. It forces objects to be placed in a tabular form where each row or
each column may have a different size from the others.
·
cgGrid(L,PadX,PadY):
L must be a list of lists of objects in the form:
[[O11,...,O1m],[O21,...,O2m],...,[On1,...,Onm]]
or
a two-dimensional array in the form of:
$array($array(O11,...,O1m),$array(O21,...,O2m),...,$array(On1,...,Onm))
where
each Oij is an object. This
constraint ensures that the objects are placed on an n by m (n rows and m columns) grid board and the object Oij occupies the grid cell at <i,j>. PadX and PadY specify the size of the
space between each two neighboring objects. Both of them can be variables.
Notice that an object
may occur multiple times in L. In that case, the object will cover all the corresponding grid cells.
For example, the following constraint
cgGrid([[B1,B2],[B3,B3],[B4,B5]],0,0)
ensures that B1 and B2 occupy the first row, B3 occupies the second row,
and B4 and B5 occupy the third row (see
Figure 3).
Another nice feature of the grid constraint is that it accepts dummy objects,
i.e., dummy variables of Prolog.
This makes it unnecessary in certain circumstances to create objects just for
layout purposes. For instance, consider the dominos in Figure 4. Let S1,S2,S3,S4,
and S5
be the squares that contain, respectively, 1, 2, 3, 4, and 5 circles. The
layout of the five squares can be specified by using one grid constraint as
follows:
cgGrid([[_,
S1,_],
[S2,S3,S4],
[_, S5,_]])
The grid constraint can also be used to specify the layout of the circles in each of the domino. For example, consider the domino with five circles. Let C1, C2, C3, C4, and C5 be the circles. The layout must satisfy the following constraint:
cgGrid([[C1,
_, C2],
[ _,C3,
_],
[C4, _, C5]])
Notice that you must make sure each object has the size of one or multiple grid cells. For objects that do not fit in squares, cgTable should be used.
·
cgGrid(L): equivalent to cgGrid(L,0,0).
·
cgTable(L,PadX,PadY): Similar to cgGrid(L,PadX,PadY) but two different rows may
be of different heights and two different columns may be of different widths.
·
cgTable(L): equivalent to cgTable(L,0,0).
The tree constraint, which
takes the following form, is useful for arranging components into tree
structures.
·
cgTree(Tree,Type,DisX,DisY,Centered)
where
·
Tree is a term in the form node(Node,Children) where Node is a graphical component
and Children is a list of sub-trees in the same form as Tree.
·
Type indicates how the tree
grows. It can be one of the following: top_down, left_right, bottom_up, and right_left.
·
Centered:
·
centered: the root of each sub-tree is placed in the middle
of its children
·
itemized: the children are itemized.
·
DisX is the x-distance between two leaves or the x-distance between a root
and its children depending on the type of the tree.
·
DisY is the y-distance between two leaves or the y-distance between a root
and its children depending on the type of the tree.
Figure 5 shows eight different
ways to visualize the following term where each node is a square:
node(C0,[node(C1,[node(C3,[]),
node(C4,[])]),
node(C2,[node(C5,[]),
node(C6,[])])]).
Figure 5. Eight different ways to
visualize a tree.
·
cgNotOverlap(L): Ensures that the list of objects do not overlap
each other.
Without this constraint, you would have to implement the
constraint by using the built-in constraints provided by B-Prolog. For example,
to ensure that two objects O1 and O2 do not overlap each other, you would have to give the
following constraints:
(O1^rightX
#=< O2^x #\/
O1^x
#>= O2^rightX #\/
O1^bottomY
#=< O2^y #\/
O1^y #>=
O2^bottomY)
The description is not only
lengthy but also inefficient.
One may need some knowledge about the packing
algorithm in order to help the algorithm pack objects efficiently. The
algorithm determines the attributes in the following order:
· fonts: for those objects that have texts on them such as buttons and labels, the fonts are determined first. The justification for this strategy is that the preferable sizes for objects with texts can only be known after the fonts are known.
· sizes: the sizes of objects are determined next. Objects that have the largest preferable sizes are selected first.
· positions: the positions are determined after the sizes are fixed. Large objects are selected before small objects.
· others: the final phase is to determine the values for the remaining attributes such as colors, fill, etc.
The primitive cgShow(O) calls cgPack(O)to pack O before showing it. One may wonder, if cgShow(O) packs O automatically, why do we need cgPack(O). cgPack is provided to let you have some control over what objects need be packed and when objects should be packed. Packing is an NP-hard problem in general and may take a long time if objects are not packed in an appropriate order. It is always a good practice to determine the layout areas for objects before fixing the objects. For instance, recall the dominos shown in Figure 4. It is fast to first pack the squares and then pack the circles inside the squares.
A special operator, #:=, is
provided to update constrainable attributes of objects. Let O be an
object, Attr be an attribute, the following resets the attribute value to NewValue:
O^Attr #:= NewValue
The update is destructive and is not undone upon backtracking.
CGLIB also provides primitives for scaling and moving objects. Rotation is not yet supported.
·
cgScale(O,F): scale the object or list of objects O by the factor F. The top-left corner of the
objects will serve as the reference point. In addition to the change of sizes,
the positions of the objects will also change proportionally. Figure 6 illustrates
this operation. The rectangle in thick lines is the original one and the
rectangle in dotted lines is the one obtained after scaling the original one by
a factor of ½ . Notice that the top-left corner remains unchanged.
·
cgResize(O,Width,Height): resize the object or list of objects O such that the object or list of objects can be covered by a rectangle
of size Width by Height. Just as for cgScale, the top-left corner of the objects will serve as the reference point.
·
cgMove(O,X,Y): Move the object or list of objects O to the position (X,Y), which will become the new
top-left corner of the object.
Currently, only finite-domain constraints are
supported and no constraints can be optional or approximate. A solution must
satisfy all given constraints. A set of constraints may appear to be
satisfiable but not. For example, the following set of constraints
{104*W #= 53*H ,H #=<100, H#>0}
is not satisfiable. This may be a source of frustration to you. Sometimes it is fast to give a relaxed
specification of a layout and then alter it to make it satisfactory.
An animation is a sequence of images that
are rendered along a time line. Animation is better than text or static image
for presenting many kinds of materials because of its dynamic nature.
To construct animations, we not only need to
construct the static images but also need to decide the order in which the
images are rendered and the rate at which changes of images take place. To
suspend an image for a certain time, use the following primitive:
·
cgSleep(T): Suspend T milliseconds before continuing the execution.
With this primitive, it is
very easy to construct animations. The following shows how to render a list of
objects in an animated fashion.
animate([],_).
animate([O|Os],[T|Ts]):-
cgCleanDefaultWindow,
cgShow(O),
cgSleep(T),
animate(Os,Ts).
An animation may consists of
thousands of frames. It would be very space consuming if we construct all
frames first, and then show them. In most cases, when we show a frame, the
previous frame will become useless and thus can be discarded. Therefore, it is
suggested that the following scheme be used to construct animations.
repeat,
construct the
next frame Frame,
determine
the time T for the frame,
cgCleanDefaultWindow,
cgShow(Frame),
cgSleep(T),
fail.
In this way, backtracking
will reclaim all the space taken by the previous frame and only space that is
big enough for storing one frame is needed. You must make sure that all the
calls between repeat and fail leave no choice point, otherwise execution will backtrack to
that choice point rather than to repeat.
There are demands for images or animations that
can be embedded in Web. In CGLIB, it is
possible to record the graphics into a Java applet. The following primitives
are provided for this purpose.
·
cgStartRecord(Name): Turn the recorder on. All the objects shown
after this call will be sent to the recorder. Name is the file name for the Java applet to be
generated when cgStopRecord is executed.
·
cgStartRecordAnimation(Name): The same as cgStartRecord(Name), but the generated Java applet will show the
recorded objects repeatedly.
·
cgStopRecord: Stop the recorder and generate two files, one
called Name.java and
the other Name.html where Name is the file name given by cgStartRecord
or cgStartRecordAnimation. The file named Name.java is a Java applet that shows the recorded
objects.
Here is an example.
go:-
Circles=[C1,C2,C3,C4,C5],
cgCircle(Circles),
cgSame(Circles,width,100),
Colors=[red,black,green,blue,gray],
setColor(Circles,Colors),
cgStartRecordAnimation(animateCircles),
member(Circle,Circles),
cgCleanDefaultWindow,
cgShow(Circle),
cgSleep(1000),
fail.
go:-
cgStopRecord.
setColor([],[]).
setColor([Circle|Circles],[Color|Colors]):-
Circle^color #= Color,
setColor(Circles,Colors).
The generated applet animateCircles.java repeatedly shows the five circles of different colors. If cgStartRecord were used rather than cgStartRecordAnimation, then the applet would show the circles at the speed of one second each and stop after the last circle.
The specification of
responsive objects is important for building interactive user-interfaces. CGLIB
provides a new language construct, called action
rules that can be used to program interactions.
An action rule takes the
following form:
where Agent is an atomic formula that
represents a pattern for agents, ConditionSeq is a sequence of conditions
on the agents, Event is a pattern for events
that can activate the agents, and ActionSeq is a sequence of actions
the agents perform when activated.
Recall the action rule in
our first example:
handleButtonClick(B),{actionPerformed(B)} => abort.
There is no condition
specified on the agent handleButtonClick(B). When an event actionPerformed(B)is posted, i.e., when the
button B is clicked, the action halt will be executed, which
terminates the execution.
There is no primitive for
killing agents. For an agent, if the condition of an action rule in its definition
is not satisfied, the next alternative rule will be tried. If that rule does
not contain an event, then the agent will be killed automatically after the
action is executed. For example,
handleButtonClick(B,Flag),var(Flag),{actionPerformed(B)}
=>
Flag=1.
handleButtonClick(B,Flag)
=> true.
The agent haddleButtonClick(B,Flag)will disappear after the
button B is clicked once. Notice
that the second rule is necessary here. Without it, the agent would fail after
the Flag becomes non-variable.
An agent can be defined by
multiple action rules, but the second rule will be tried only after the
condition of the first one fails. Therefore, for the following definition,
handleButtonClick(B),{actionPerformed(B)}
=> p(B).
handleButtonClick(B),{actionPerformed(B)}
=> q(B).
the second rule will never
be tried because the condition for the first rule always succeeds. To let both
of the actions p(B) and q(B) be executed when B is clicked, one has to either put these two actions into
one rule or create two agents, one executing p(B) and the other executing q(B) when the button is clicked.
Each rule can handle one
event. To handle multiple events on a component, one has to create one agent
for each of the events.
Each time when an event is
posted, all the agents that are waiting for the event will be activated. If
there are multiple agents waiting for one event, then the agent generated first
will be activated first.
Appendix II summarizes all
the events. An event is a structure with one or two arguments. The first
argument is the source component from which the event originates. The second
argument, if there is any, contains some supplementary information about the
event. For example, the following rule
handleMouseEvent(O),{mousePressed(O,E)}
=>
E^x
#= X, E^y #= Y,
write((X,Y)),nl.
handles mouse button
presses. Each time a mouse button is pressed, it prints out the location of the
event.
The
following describes all the events CGLIB can handle.
·
actionPerformed(O) This event occurs on buttons, menu items, and
text fields. If O is a button, it is posted when O is clicked. If O is a menu
item, the event is posted when the item is selected. If O is a text field, the
event is posted when the enter key is typed on the text field.
·
focusGained(O)
·
focusLost(O)
These two events occurs when O gains or loses the focus. O can be any window or
any component that has the enabled attribute (i.e., Button,
Choice, Checkbox, List ,
Scrollbar, TextField, and TextArea).
·
keyPressed(O,E)
·
keyReleased(O,E)
·
keyTyped(O,E)
These three kinds of events are posted when a key is pressed, released, and
typed, respectively, while O has the focus. O can a window or an
AWT control component. E has the
following attributes:
· code: the code of the pressed key. For printable key C, the notation 0’C tells the code. For instance, the code for ‘A’ is 0’A, and the code for ‘1’ is 0’1. For non-printable keys such as arrow and function keys, built-in predicates are provided to test their codes. For example, the call vk_F1(Code) succeeds if Code is the code of the F1 key. See Appendix III for the complete list of the built-ins.
· char: the char of the typed key. Notice that this attribute is meaningful only for the event keyTyped and the typed key corresponds to a printable character.
· modifiers: an integer that tells the supplementary information about the key stroke, e.g., whether the shift key is pressed. You should consult the Java’s API for the meaning of this field. The following primitives are provided to facilitate the access of this field:
·
cgShiftIsDown(E)
·
cgControlIsDown(E)
·
cgMetaIsDown(E)
·
cgAltIsDown(E)
·
mousePressed(O,E)
·
mouseReleased(O,E)
·
mouseEntered(O,E)
·
mouseExited(O,E)
·
mouseClicked(O,E)
·
mouseDragged(O,E)
·
mouseMoved(O,E)
These mouse events occur on windows. The argument E has the following
attributes:
· x,y : the location at which the mouse event occurs.
· count: number of mouse clicks
· modifier: An integer that conveys more information about the event., e.g., which mouse button is pressed. The following primitives are provided to facilitate the use of this field:
·
cgIsLeftButton(E)
·
cgIsRightButton(E)
·
windowClosing(O)
·
windowOpened(O)
·
windowIconified(O)
·
windowDeiconified(O)
·
windowClosed(O)
·
windowActivated(O)
·
windowDeactivated(O)
These events occurs on windows.
·
componentResized(O,E)
·
componentMoved(O,E)
These two events occur when window O is resized or moved. E has the following
attributes:
·
x, y, width,
height: The new position and size of the window.
·
itemStateChanged(O,E)
This event occurs on checkbox menu items, checkboxes, lists, and choices. The
event object E has the following attributes:
·
index: the index of the item that
was selected or deselected
·
state: the new state of the item
·
adjustmentValueChanged(O,E)
This
event occurs on scrollbars. The event object E has the following attributes:
·
value: the
current value of the scrollbar
·
adjustmentType:
The type of the adjustment which
caused the value change. The returned type is one of the following: unit_increment,
unit_decrement, block_decrement, block_increment, and track.
·
textValueChanged(O,E)
This event occurs on text fields and text
areas.
·
time(T)
This
event is posted after the time interval of the timer T
elapses. See B-Prolog’s manual for the description of timers.
CGLIB
can be used in many areas such as drawing editors, interactive user interfaces,
animation, information visualization, intelligent agents, and games. This chapter describes the following list of
sample programs:
· Drawing the flag of Antigua and Barbuda
· Drawing binary trees
· Drawing a diagram of Java AWT’s classes
· Building a calculator
· Building a digital clock
·
Demonstrating
a geometry theorem on quadrilaterals
These examples illustrate the use of most of
the constraints and events. More examples can be found at the web site www.probp.com.
We
consider as the first sample program how to write a program to draw the flag of
Antigua and Barbuda as shown in Figure 7. The
flag is composed of a red rectangle, a black triangle, a yellow 16-pointed
star, a blue triangle and a white triangle. The order in which components are
shown is very important. When two components overlap, the component shown later
will overwrite the one shown earlier. So, for the flag, the red rectangle must
be shown first and the white triangle must be shown last.
go:-
antiguabarbuda(Os),
%create the list of components Os
cgWindow(Win,"antiguaAndBarbuda"), %create a window with a
title
cgSame(Os,window,Win), %the containing window of Os is Win
cgShow(Os).S
antiguabarbuda([R,TR1,S,TR2,TR3]):-
cgRectangle(R), R^color
#= red, 2*R^width #= 3*R^height,
cgTriangle(TR1),
TR1^color #= black,
TR1^point1 #=
R^leftTopPoint,
TR1^point2 #=
R^rightTopPoint,
TR1^x3 #= R^centerX,
TR1^y3 #= R^bottomY,
cgStar(S), S^color #=
yellow, S^n #= 16,
S^centerX #=
R^x+R^width/2,
35*S^diameter #=
24*R^height,
7*S^innerDiameter #=
2*R^width,
cgTriangle(TR2),
TR2^color #= blue,
210*(TR2^x1-R^x) #=
41*R^width,
28*(TR2^y1-R^y) #=
11*R^height,
TR2^y1 #= S^centerY,
210*(TR2^x2-R^x) #=
169*R^width,
TR2^y2 #= TR2^y1,
TR2^point3 #=
TR1^point3,
cgTriangle(TR3),
TR3^color #= white,
10*(TR3^x1-R^x) #=
3*R^width,
28*(TR3^y1-R^y) #=
17*R^height,
10*(TR3^x2-R^x) #=
7*R^width,
TR3^y2 #= TR3^y1,
TR3^point3 #= TR1^point3.
In this
example, we build a binary tree of some depth and use the tree constraint to
visualize it. Figure 8 shows a complete binary tree of seven levels. The tree
constraint
cgTree(Tree,top_down,1,5,centered),
states that the tree grows from top down, the x-distance between each two neighboring leaves is 1 pixel, the y-distance between each level is 5 pixels, and the root is in the middle of its children along the x-axis.
Figure 8. A compelete binary tree.
go:-
cgWindow(Win,"binaryTree"),
N=6, %depth of the tree
generateTree(Tree,N,Os,[],Ls,[]), %Os -
nodes, Ls - lines
cgTree(Tree,top_down,1,5,centered), %use
the tree constraint
cgSame(Os,window,Win),
cgSame(Ls,window,Win),
cgShow(Os), cgShow(Ls).
generateTree(node(C,[]),0,[C|OsR],OsR,Ls,Ls):-!,node(C).
generateTree(node(Root,[C1,C2]),N,[Root|Os],OsR,[L1,L2|Ls],LsR):-
node(Root),
N1 is N-1,
cgLine([L1,L2]),
generateTree(C1,N1,Os,Os1,Ls,Ls1),C1=node(Circle1,_),
generateTree(C2,N1,Os1,OsR,Ls1,LsR),C2=node(Circle2,_),
L1^point1 #= Root^centerPoint,
L1^point2 #= Circle1^centerPoint,
L2^point1 #= L1^point1,
L2^point2 #= Circle2^centerPoint.
node(C):-cgCircle(C),C^color
#= red,C^width #= 5.
This program draws the
diagram (see Figure 9) that depicts the hierarchy of the Java AWT’s
classes. The diagram is a tree where each node is a text box and the root of
each sub-tree is centered with respect to its children. The tree constraint
cgTree(Tree,left_right,20,0,centered),
specifies this layout. The
root of each sub-tree is connected to its children by line segments. As the
positions for the lines depend on the text boxes, it is important to lay out
the text boxes first.
Figure 9. Java AWT's class hierarchy.
go:-
cgWindow(Win,"java awt’s
classes"),
generateNodes(Tree,Os),
connectTree(Tree,Ls,[]),
cgTree(Tree,left_right,10,2,centered),
cgSame(Os,window,Win),cgSame(Ls,window,Win),
cgShow(Os),cgShow(Ls).
generateNodes(Tree,Os):-
Os=[Object,Component,Button,Canvas,Checkbox,CheckboxMenuItem,
Choice,Container,Dialog,FileDialog,Frame,Label,List,
MenuComponent,Menu,MenuBar,MenuItem,Panel,Applet,PopupMenu,
Scrollbar,ScrollPane,TextArea,TextComponent,TextField,Window],
Labs=["Object","Component","Button","Canvas","Checkbox",
"CheckboxMenuItem","Choice","Container","Dialog",
"FileDialog","Frame","Label","List","MenuComponent",
"Menu","MenuBar","MenuItem","Panel","Applet",
"PopupMenu","Scrollbar","ScrollPane",TextArea",
"TextComponent","TextField","Window"],
cgTextBox(Os,Labs),
Tree=node(Object,
[node(Component,
[node(Button,[]),
node(Canvas,[]),
node(Checkbox,[]),
node(Choice,[]),
node(Container,
[node(Window,
[node(Frame,[]),
node(Dialog,
[node(FileDialog,[])])]),
node(Panel,
[node(Applet,[])]),
node(ScrollPane,[])]),
node(Label,[]),
node(List,[]),
node(Scrollbar,[]),
node(TextComponent,
[node(TextArea,[]),
node(TextField,[])])]),
node(MenuComponent,
[node(MenuBar,[]),
node(MenuItem,
[node(Menu,[node(PopupMenu,[])]),
node(CheckboxMenuItem,[])])])]).
connectTrees([],Ls,LsR):-Ls=LsR.
connectTrees([C|Cs],Ls,LsR):-
connectTree(C,Ls,Ls1),
connectTrees(Cs,Ls1,LsR).
connectTree(node(Box,[]),Ls,LsR):-!,Ls=LsR.
connectTree(node(Box,Children),[Vl,Hl|Ls],LsR):-
getFirst(Children,node(FirstC,_)),
getLast(Children,node(LastC,_)),
cgLine(Vl),
Vl^y1 #= FirstC^centerY, Vl^y2 #=
LastC^centerY,
Vl^x1 #= Vl^x2, Vl^x1 #= Box^rightX+4,
%
cgLine(Hl),
Hl^x1 #= Box^rightX, Hl^x2 #= Vl^x1,
Hl^y1 #= Box^centerY, Hl^y2 #= Hl^y1,
%
connectChildren(Vl,Children,Ls,Ls1),
connectTrees(Children,Ls1,LsR).
getFirst([X|Xs],X).
getLast(L,X):-
reverse(L,RL),
getFirst(RL,X).
connectChildren(Line,[],Ls,LsR):-Ls=LsR.
connectChildren(Line,[node(C,_)|Cs],Ls,LsR):-
cgLine(L),
Ls=[L|Ls1],
L^x1 #= Line^x1, L^x2 #= C^x-2,
L^y1 #= C^centerY, L^y2 #= L^y1,
connectChildren(Line,Cs,Ls1,LsR).
In this example, we consider how to build a
working calculator with the interface as depicted in Figure. The calculator consists of a display and a keyboard.
The display is a text field, which is a built-in component. The keyboard
consists of several keys. The layout of the keys are specified by the grid
constraint given in Figure 10.
cgGrid([[Bc,Bdiv,Bmul,Bsub], [B7,B8,
B9, Badd],
[B4,B5, B6, Badd],
[B1,B2, B3, Beq],
[B0,B0, Bdot,Beq]],1,1),
Figure 10. The interface of the
calculator and the constraint.
This example illustrates a
nice feature of the grid constraint: a component can occupy multiple grid
squares. In this example, the keys labeled “=” (Beq), “+” (Badd), and “0” (B0)
are twice as big as the other keys.
To carry out calculation,
the calculator has to memorize the accumulated result and the operator to be
applied. After each operation is applied, the display should show the current
result. When you continue to type the next operand, the display should turn to
show the operand. For this purpose, the calculator should also memorize whether
the number on display is a result or an operand. We use a structure to represent all the information that has to
be memorized:
cal(Display, Acc, Op, OnDisplay)
where Display is the text field, Acc is the accumulated result, Op is the operator to be
applied next, and OnDisplay tells whether the number on display is a result or
an operand.
Prolog is not an
object-oriented language, but this does not prevent us from writing programs in
the object-oriented style. A graphical user interface usually generates many
handlers each of which carrries the objects it manipulate when activated. In
the calculator, there is an event handler, defined as follows, for each key on
the keyboard.
keyInput(Key,Cal),{actionPerformed(Key)}
=>
Key^text #= KeyLab,
process(KeyLab,Cal).
The handler takes the object
Cal
and updates it when activated. The predicate process(KeyLab,Cal) processes a click of the
button labeled KeyLab . Different actions are
taken according to the types of keys. For example, when a digit key is clicked,
if the number on display is a result, then the calculator cleans the display
and shows the digit as part of the next operand; if the number on display is an operand,
then the calculator appends the digit to the end of the operand.
go:-
calculator(Display,Os),
cgWindow(Win,"calculator"),Win^topMargin
#= 30, Win^leftMargin #= 10,
handleWindowClosing(Win),
cgSame(Os,window,Win),
cgJava(calculator,Os).
handleWindowClosing(Win),{windowClosing(Win)}
=> cgClose(Win).
calculator(Display,Os):-
% components
cgTextField(Display), Display^fontSize #=
16,
cgSetEditable(Display,0),
%
Buttons=[B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,Bc,Bdiv,Bmul,Bsub,Badd,Beq,Bdot],
Ts=["0","1","2","3","4","5","6","7","8","9","C","/","*","-","+","=","."],
cgButton(Buttons,Ts),
Display^width #= B0^width*2,
B0^width #>50,
%
cgFont(F),F^size#=20,F^style#=bold,
cgSame(Buttons,font,F),
cgAbove(Display,Bc),
cgGrid([[Bc,Bdiv,Bmul,Bsub],
[B7,B8, B9, Badd],
[B4,B5, B6, Badd],
[B1,B2, B3, Beq],
[B0,B0, Bdot,Beq]],1,1),
%
Cal=cal(Display,0,"+",result_is_on),
handleButtons(Buttons,Cal),
Os=[Display|Buttons].
%%
handleButtons([],Cal).
handleButtons([B|Bs],Cal):-
handleButton(B,Cal),
handleButtons(Bs,Cal).
handleButton(B,Cal),{actionPerformed(B)}
=>
cgGetText(B,Text),
catch(handleButtonAction(Text,Cal),_,true).
handleButtonAction("C",Cal):-!,
Cal=cal(Display,_Acc,_Op,_OnDisplay),
setarg(2,Cal,0), % acc
setarg(3,Cal,"+"), % op
setarg(4,Cal,result_is_on), % result on
display
cgSetText(Display,""),
cgShow(Display).
handleButtonAction(Op,Cal):-operator(Op),!,
(Cal=cal(_Display,_Acc,_Op,operand_is_on)->applyOperation(Cal);true),
setarg(3,Cal,Op).
handleButtonAction("=",Cal):-!,
applyOperation(Cal).
handleButtonAction(X,Cal):-
appendInput(X,Cal).
%% operations on Cal
appendInput(X,Cal):-
Cal=cal(Display,_Acc,_Op,result_is_on),!,
% result is on display
cgSetText(Display,""),
setarg(4,Cal,operand_is_on),
appendInput(X,Cal).
appendInput(".",Cal):-
Cal=cal(Display,_Acc,_Op,OnDisplay),
cgGetText(Display,Operand),
member(0'.,Operand),!. %0'.=X -> [X]="0"
appendInput([D],Cal):-
Cal=cal(Display,_Acc,_Op,OnDisplay),
cgGetText(Display,CurText),
append(CurText,[D],NewText),
cgSetText(Display,NewText),
cgShow(Display).
applyOperation(Cal):-
Cal=cal(Display,Acc,Op,OnDisplay),
cgGetText(Display,String),
number_codes(Operand,String),
applyOperation(Op,Acc,Operand,NewAcc),
number_codes(NewAcc,NewString),
cgSetText(Display,NewString),
setarg(2,Cal,NewAcc),
setarg(4,Cal,result_is_on),
cgShow(Display).
operator("+").
operator("-").
operator("/").
operator("*").
applyOperation("+",Op1,Op2,Res):-Res
is Op1+Op2.
applyOperation("-",Op1,Op2,Res):-Res
is Op1-Op2.
applyOperation("*",Op1,Op2,Res):-Res
is Op1*Op2.
applyOperation("/",Op1,Op2,Res):-Res
is Op1/Op2.
An animation is a sequence of frames of objects that
change along a time line. Animation is better than static graphics for
presenting many kinds of data because of its dynamic nature. In this example,
we consider how to build the digital clock as shown in Figure 11.
The display shows three integers separated by colons that represents respectively the hour, minute, and second of the current time. Both the integers and the colons are drawn as labels. In order to let the packer determine the sizes of the labels, the program initializes integer labels to “00”. The predicate tick(Hour,Minute,Second) repeatedly updates the time and shows it every one second. Notice that whenever a graphical component is shown, its previous image is cleaned automatically. Therefore, the program does not need to clean the display before showing the next clock time.
Figure 11. A digital clock.
go:-
cgWindow(Win,"clock"), Win^topMargin
#= 30, Win^leftMargin #= 10,
cgLabel([Hour,Minute,Second,Sep1,Sep2],["00","00","00",":",":"]),
cgSame([Hour,Minute,Second,Sep1,Sep2],fontSize,36),
cgTable([[Hour,Sep1,Minute,Sep2,Second]]),
cgSame([Hour,Minute,Second,Sep1,Sep2],window,Win),
cgPack([Hour,Minute,Second,Sep1,Sep2]),
cgShow([Sep1,Sep2]),
handleWindowClosing(Win,Flag),
tick(Hour,Minute,Second,Flag).
handleWindowClosing(Win,Flag),{windowClosing(Win)}
=>
Flag=1,
cgClose(Win).
tick(Hour,Minute,Second,Flag):-
timer(T,1000), % create a timer
timer_start(T),
tick(T,Hour,Minute,Second,Flag).
tick(Timer,Hour,Minute,Second,Flag),var(Flag),
{time(Timer)}
=>
time(H,M,S), %get the current time
number_codes(H,HString), addZero(HString,HString1),
cgSetText(Hour,HString1),
number_codes(M,MString),
addZero(MString,MString1),
cgSetText(Minute,MString1),
number_codes(S,SString),
addZero(SString,SString1),
cgSetText(Second,SString1),
cgShow([Hour,Minute,Second]).
tick(Timer,Hour,Minute,Second,Flag)
=> true.
addZero([D],String1):-!,String1=[0'0,D].
addZero(String,String1):-String1=String.
This example program
demonstrates the following geometry theorem on quadrilaterals: The
quadrilateral formed by the four edges that connect the middle points of the
edges of another quadrilateral is always a parallelogram. Figure
12 shows two
snapshots. You can move any point of the outer quadrilateral by dragging it. Wherever
the outer point moves, the four points of the inner quadrilateral always stay
at the middle points of the four edges of the outer quadrilateral.
Figure
12. Demonstrating a geometry
theorem.
The program generates and
shows two quadrilaterals, and generates three agents that handle mouse events
and maintain the constraints. Let Q be the outer and P be the inner
quadrilaterals. The agent handleMouseDown is triggered when the mouse is pressed. It
detects whether a point of Q is selected. The agent handleMouseUp is triggered when the mouse
is released. It deselects the point selected if any. The agent handleMouseDrag is activated when a point
is dragged. If the mouse drag occurs while a point is selected, the agent moves
the point and re-computes Q’s points. The three agents are defined in Figure 13.
All the of three agents share the window Win
and an object O that is a Prolog term of the following structure:
quadrilaterals(Q,P,Selected)
where Q and P are two polygons, and Selected takes
for the form of pointSelected(I)
where I is the
index of the selected point (0 if no point of Q is selected). The predicate selectPoint(X,Y,O) in line (3) sets Selected to I if the Ith point of Q is close enough to <X,Y>. The predicate deselectPoint(O) in line (5) sets Selected to 0. The predicate selectedPoint(O,I) in line (7) succeeds if I is the selected point. The
predicate updatePoint(O,I,X,Y)in line (10) updates the Ith point of Q to <X,Y>, which is defined as
follows:
updatePoint(O,I,X,Y):-
O=quadrilaterals(Q,P,Selected),
Q^xs(I) #:= X,
Q^ys(I) #:= Y.
The notation Q^xs(I) refers
to the Ith element of the attribute xs
of O, which is an array.
The predicate recomputeP(O) in line (11) re-computes the points of the
quadrilateral P such that the points remain at the middles of the edges of Q. After the attributes of an
object are updated, it is drawn again. When drawing an object that is already
on a window, the system automatically cleans the object before re-drawing it.
|
Figure 13. Definitions of mouse event handlers.
go:-
cgWindow(Win,"geometryTheorem"),
Win^topMargin #= 100, Win^leftMargin #=
100,
handleWindowClosing(Win), Win^width
#>600, Win^height #> 700,
cgRectangle(R),R^fill #=0,R^window #= Win,
R^width #= 400, R^height #= 500,
cgPack(R),
cgPolygon(Q), Q^n #= 4, Q^fill #= 0,
Q^point(1) #= R^leftTopPoint,
Q^point(2) #= R^leftBottomPoint,
Q^point(3) #= R^rightBottomPoint,
Q^point(4) #= R^rightTopPoint,
cgPolygon(P),P^n #= 4,P^fill #= 0,
cgSame([P,Q],window,Win),
cgPack(Q),
middle(P,Q),
State=pointSelected(0),
handleChange(Win,Q,P,State),
cgShow([P,Q]).
handleWindowClosing(Win),{windowClosing(Win)}
=> cgClose(Win).
middle(P,Q):-
middle(P,Q,1,2),
middle(P,Q,2,3),
middle(P,Q,3,4),
middle(P,Q,4,1).
middle(P,Q,I,J):-
P^xs(I) #:= (Q^xs(I)+Q^xs(J))//2,
P^ys(I) #:= (Q^ys(I)+Q^ys(J))//2.
handleChange(Win,Q,P,State):-
handleMouseMove(Win,Q),
handleMouseDown(Win,Q,P,State),
handleMouseUp(Win,Q,P,State),
handleMouseDrag(Win,Q,P,State).
handleMouseMove(Win,Q),{mouseMoved(Win,E)}
=>
E^x #= X, E^y #= Y,
((closeEnough(X,Y,1,Q);
closeEnough(X,Y,2,Q);
closeEnough(X,Y,3,Q);
closeEnough(X,Y,4,Q))->
changeCursor(Win,move_cursor);
changeCursor(Win,default_cursor)).
handleMouseDown(Win,Q,P,State),{mousePressed(Win,E)}
=>
critical_region(selectPoint(E,Q,State)).
handleMouseUp(Win,Q,P,State),{mouseReleased(Win,E)}
=>
setarg(1,State,0).
handleMouseDrag(Win,Q,P,State),{mouseDragged(Win,E)}
=>
arg(1,State,I),
(I>0 ->
E^x #= X,
E^y #= Y,
Q^xs(I) #:= X,
Q^ys(I) #:= Y,
middle(P,Q),
cgShow([P,Q]),
changeCursor(Win,move_cursor);
true).
selectPoint(E,Q,State):-
E^x #= X,
E^y #= Y,
(closeEnough(X,Y,1,Q)->setarg(1,State,1);true),
(closeEnough(X,Y,2,Q)->setarg(1,State,2);true),
(closeEnough(X,Y,3,Q)->setarg(1,State,3);true),
(closeEnough(X,Y,4,Q)->setarg(1,State,4);true).
closeEnough(X,Y,I,Q):-
Q^xs(I) #= X1,
Q^ys(I) #= Y1,
sqrt((X-X1)*(X-X1)+(Y1-Y)*(Y1-Y)) < 5.
changeCursor(Win,CursorType):-
cgGetCursor(Win,CursorType),!.
changeCursor(Win,CursorType):-
cgSetCursor(Win,CursorType).
Table 1. Summary of components.
Object |
Constrainable attributes |
Primitives |
All |
bottomY center centerX centerY color height leftBottomPoint leftTopPoint location rightBottomPoint rightTopPoint rightX size width window x y |
cgClean(O) cgGetBackground(O,Color) cgMove(O,X,Y) cgPack(O) cgResize(O,Width,Height) cgScale(O,Factor) cgSetBackground(O,Color) cgSetVisible(O,lOr0) cgShow(O) |
Arc |
fill StartAngle arcAngle |
cgArc(O) |
Button |
font fontName fontSize fontStyle |
cgButton(O) cgButton(O,T)
cgSetCursor(O,Cursor) cgGetText(O,T) cgIsEnabled(O) cgSetEnabled(O,OneOrZero) cgSetText(O,T) |
Checkbox |
font fontName fontSize fontStyle |
cgCheckbox(O) cgCheckbox(O,T) cgGetCursor(O,Cursor) cgCheckboxGroup(Os) cgGetText(O,T) cgGetState(O,S) cgIsEnabled(O) cgSetCursor(O,Cursor) cgSetEnabled(O,OneOrZero) cgSetState(O,S) cgSetText(O,T) |
Choice |
font fontName fontSize fontStyle |
cgChoice(O) cgChoice(O,Items) cgAdd(O,Items) cgAdd(O,Item,Index) cgGetCursor(O,Cursor) cgIsEnabled(O) cgRemove(O,Items) cgSelect(O,Item) cgSelectedItem(O,Item) cgSetCursor(O,Cursor) cgSetEnabled(O,OneOrZero) |
Image |
name |
cgImage(O) cgImage(O,Name) |
Label |
font fontName fontSize fontStyle |
cgLabel(O) cgLabel(O,T) cgGetAlignment(O,Align) cgGetText(O,T) cgSetAlignment(O,Align) cgSetText(O,T) |
Line |
arrow1 arrowLength1 arrowThickness1 arrow2 arrowLength2 arrowThickness2 point1 point2 thickness x1 x2 y1 y2 |
cgLine(O) |
List |
font fontName fontSize fontStyle |
cgList(O) cgList(O,Items) cgAdd(O,Items) cgAdd(O,Item,Index) cgGetCursor(O,Cursor) cgIsEnabled(O) cgRemove(O,Items) cgSelect(O,Item) cgSelectedItems(O,Items) cgSetCursor(O,Cursor) cgSetEnabled(O,OneOrZero) |
Oval |
fill |
cgOval(O) |
Polygon |
fill n point(I) x(I) y(I) |
cgPolygon(O) |
Rectangle |
fill |
cgRectangle(O) |
RoundRectangle |
arcWidth arcHeight fill |
cgRoundRectangle(O) |
Scrollbar |
|
cgScrollbar(O) cgScrollbar(O,Or,V,VA,Min,Max) cgGetBlockIncrement(O,Val) cgGetMaximum(O,Max) cgGetMinimum(O,Min cgGetOrientation(O,Orient) cgSetOrientation(O,Orient) cgGetUnitIncrement(O,Val) cgGetValue(O,Val) cgGetVisibleAmount(O,Val) cgSetBlockIncrement(O,Val) cgSetMaximum(O,Max) cgSetMinimum(O,Min) cgSetUnitIncrement(O,Val) cgSetValue(O,Val) cgSetVisibleAmount(O,Val) |
Square |
fill |
cgSquare(O) |
Star |
angle0 diameter fill innerDiameter n x0 y0 |
cgStar(O) |
String |
font fontName fontSize fontStyle |
cgString(O) cgString(O,T) cgGetAlignment(O,Align) cgGetText(O,T) cgSetAlignment(O,Align) cgSetText(O,T) |
TextArea |
font fontName fontSize fontStyle |
cgTextArea(O) cgTextArea(O,T) cgAppend(O,Text) cgGetCursor(O,Cursor) cgGetColumns(O,NumOfColumns) cgGetRows(O,NumOfRows) cgGetText(O,Text) cgInsert(O,Text,Pos) cgIsEditable(O) cgIsEnabled(O) cgSetColumns(O,NumOfColumns) cgSetCursor(O,Cursor) cgSetEditable(O,OneOrZero) cgSetEnabled(O,OneOrZero) cgSetRows(O,NumOfRows) |
TextField |
font fontName fontSize fontStyle |
cgTextField(O) cgTextField(O,T) cgGetColumns(O,NumOfColumns) cgGetCursor(O,Cursor) cgGetText(O,Text) cgIsEditable(O) cgIsEnabled(O) cgSetColumns(O,NumOfColumns) cgSetCursor(O,Cursor) cgSetEditable(O,OneOrZero) cgSetEnabled(O,OneOrZero) |
TextBox |
font fontName fontSize fontStyle |
cgTextBox(O) cgTextBox(O,T) cgGetAlignment(O,Align) cgGetText(O,T) cgSetAlignment(O,Align) cgSetText(O,T) |
Triangle |
fill point1 point2 point3 x1,x2,x3 y1,y2,y3 |
cgTriangle(O) |
Table 2. Summary of events.
Event
|
Event sources
|
E’s Attributes
|
Primitives on E
|
actionPerfromed(O) |
Button, MenuItem, TextField |
|
|
focusGained(O) focusLost(O) |
Component Window |
|
|
keyPressed(O,E) keyReleased(O,E) keyTyped(O,E) |
Component Window |
code char modifiers |
cgShiftIsDown(E) cgControlIsDown(E) cgMetaIsDown(E) cgAltIsDown(E) |
mousePressed(O,E) mouseReleased(O,E) mouseEntered(O,E) mouseExited(O,E) mouseClicked(O,E) mouseDragged(O,E) mouseMoved(O,E) |
Component Window |
x y count modifiers |
cgIsLeftButton(E) cgIsRightButton(E) cgShiftIsDown(E) cgControlIsDown(E) cgMetaIsDown(E) cgAltIsDown(E) |
windowClosing(O) windowOpened(O) windowIconified(O) windowDeiconified(O) windowClosed(O) windowActivated(O) windowDeactivated(O) |
Window |
|
|
componentResized(O,E) componentMoved(O,E) |
Window |
x y width height |
|
textValueChanged(O) |
TextField TextArea |
|
|
itemStateChanged(O,E) |
Checkbox CheckboxMenuItem Choice List |
index state |
|
adjustmentValueChanged(O,E) |
Scrollbar |
adjustmentType value |
|
time(T) |
Timer |
|
|
vk_0(C)
vk_1(C)
vk_2(C)
vk_3(C)
vk_4(C)
vk_5(C)
vk_6(C)
vk_7(C)
vk_8(C)
vk_9(C)
vk_A(C)
vk_B(C)
vk_C(C)
vk_D(C)
vk_E(C)
vk_F(C)
vk_G(C)
vk_H(C)
vk_I(C)
vk_J(C)
vk_K(C)
vk_L(C)
vk_M(C)
vk_N(C)
vk_O(C)
vk_P(C)
vk_Q(C)
vk_R(C)
vk_S(C)
vk_T(C)
vk_U(C)
vk_V(C)
vk_W(C)
vk_X(C)
vk_Y(C)
vk_Z(C)
vk_ACCEPT(C)
vk_ADD(C)
vk_ALT(C)
vk_BACK_QUOTE(C)
vk_BACK_SLASH(C)
vk_BACK_SPACE(C)
vk_CANCEL(C)
vk_CAPS_LOCK(C)
vk_CLEAR(C)
vk_CLOSE_BRACKET(C)
vk_COMMA(C)
vk_CONTROL(C)
vk_CONVERT(C)
vk_DECIMAL(C)
vk_DELETE(C)
vk_DIVIDE(C)
vk_DOWN(C)
vk_END(C)
vk_ENTER(C)
vk_EQUALS(C)
vk_ESCAPE(C)
vk_F1(C)
vk_F10(C)
vk_F11(C)
vk_F12(C)
vk_F2(C)
vk_F3(C)
vk_F4(C)
vk_F5(C)
vk_F6(C)
vk_F7(C)
vk_F8(C)
vk_F9(C)
vk_FINAL(C)
vk_HELP(C)
vk_HOME(C)
vk_INSERT(C)
vk_KANA(C)
vk_KANJI(C)
vk_LEFT(C)
vk_META(C)
vk_MODECHANGE(C)
vk_MULTIPLY(C)
vk_NONCONVERT(C)
vk_NUM_LOCK(C)
vk_NUMPAD0(C)
vk_NUMPAD1(C)
vk_NUMPAD2(C)
vk_NUMPAD3(C)
vk_NUMPAD4(C)
vk_NUMPAD5(C)
vk_NUMPAD6(C)
vk_NUMPAD7(C)
vk_NUMPAD8(C)
vk_NUMPAD9(C)
vk_OPEN_BRACKET(C)
vk_PAGE_DOWN(C)
vk_PAGE_UP(C)
vk_PAUSE(C)
vk_PERIOD(C)
vk_PRINTSCREEN(C)
vk_QUOTE(C)
vk_RIGHT(C)
vk_SCROLL_LOCK(C)
vk_SEMICOLON(C)
vk_SEPARATER(C)
vk_SHIFT(C)
vk_SLASH(C)
vk_SPACE(C)
vk_SUBTRACT(C)
vk_TAB(C)
vk_UNDEFINED(C)
vk_UP(C)
actionPerformed(O), 31
animation, 28
Arc, 12
AWT control components, 12
black, 10
blue, 10
bottomY, 10
cColor(C), 7
center, 10
centerX, 10
centerY, 10
cgAbove(O1,O2), 22
cgAdd, 13, 15
cgAppend, 18
cgArc(O), 9
cgArcs, 9
cgBelow(O1,O2), 22
cgButton, 3, 9, 13
cgCheckbox, 13
cgCheckboxGroup, 13
cgCheckboxMenuItem, 19
cgCircle(O), 9
cgClean, 6, 9, 11
cgClean(W), 8
cgCleanDefaultWindow, 9
cgCleanDrawing, 8
cgClose, 5
cgClose(W), 8
cgCloseDefaultWindow, 8
cgDefaultWindow, 4
cgDefaultWindow(W), 8
cgFont(F), 7, 19
cgGetAlignment, 14, 17, 18
cgGetBackground, 10
cgGetColumns, 17, 18
cgGetCursor, 12
cgGetRows, 17
cgGetText, 13, 14, 17, 18
cgGetTitle(W,Title), 8
cgGrid(L), 24
cgGrid(L,PadX,PadY), 22
cgImage(O), 9
cgInsert, 18
cgInside(O1,O2), 22
cgIsAltDown(E), 32
cgIsControlDown(E), 32
cgIsEditable, 17, 18
cgIsEnabled, 12
cgIsLeftButton(E), 32
cgIsMetaDown(E), 32
cgIsRightButton(E), 32
cgIsShiftDown(E), 32
cgLabel(O), 9
cgLeft(O1,O2), 22
cgLine(O), 9
cgMenuBar, 20
cgMenuItem, 19
cgMove(OrigO,NewO,X,Y), 27
cgNotOverlap(L), 25
cgOutside(O1,O2), 22
cgOval(O), 9
cgPack, 11
cgPack(O), 26
cgPoint(P), 7
cgPolygon(O), 9
cgRectangle(O), 9
cgRemove, 13, 15
cgResize(OrigO,NewO,Width,Height, 27
cgRight(O1,O2), 22
cgRoundRectangle(O), 9
cgSame(L,AttributeName), 22
cgSame(L,AttributeName,Value), 22
cgScale(OrigO,NewO,F), 26
cgSelect, 15
cgSelectedItem, 13, 15
cgSelectedItems, 15
cgSetAlignment, 14, 17, 18
cgSetBackground, 10
cgSetColumns, 17, 18
cgSetCursor, 12, 46, 47, 48
cgSetEditable, 17, 18
cgSetEnabled, 12
cgSetMenuBar(W,MenuBar), 8
cgSetRows, 17
cgSetText, 12, 13, 14, 17, 18
cgSetTitle(W,Title), 8
cgSetVisible(W,OneOrZero), 8
cgShow, 4, 11
cgShow(O), 26
cgShow(W), 8
cgSleep(T), 28
cgSquare(O), 9
cgStar, 5
cgStar(O), 9
cgStartRecord (Name), 29
cgStartRecordAnimation(Name), 29
cgStopRecord, 29
cgTable(L), 24
cgTable(L,PadX,PadY), 24
cgTextArea(O), 9
cgTextField(O), 9
cgTriangle(O), 9
cgWindow, 4
cgWindow(W), 4, 8
Checkbox menu items, 19
Circle, 13
color, 10
componentMoved(O,E), 33
componentResized(O,E), 33
Cursor, 12
cyan, 10
darkGray, 10
Dialog, 7
DialogInput, 7
disequality, 22
equality, 22
focusGained(O), 31
focusLost(O), 31
font, 10
fontName, 10
fontSize, 10
fontStyle, 10
gray, 10
height, 8, 10
Helvetica, 7
Image, 14
inequality, 22
Installation, 3
itemStateChanged(O,E), 33
keyPressed(O,E), 31
keyReleased(O,E), 31
keyTyped(O,E), 32
Label, 14
leftBottomPoint, 10
leftTopPoint, 10
lightGray, 10
Line, 14
magenta, 10
Menu bars, 20
Menu items, 19
Menus, 19
mouseClicked(O,E), 32
mouseDragged(O,E), 32
mouseEntered(O,E), 32
mouseExited(O,E), 32
mouseMoved(O,E), 32
mousePressed(O,E), 32
mouseReleased(O,E), 32
name, 7
orange, 10
Oval, 15
pink, 10
Polygon, 15
Rectangle, 15
red, 10
rightBottomPoint, 10
rightX, 10
RoundRectangle, 15
size, 7, 10
Square, 16
Star, 17
String, 17
style, 7
TextArea, 17
TextField, 18
time(T), 33
Timer, 33
TimesRoman, 7
Triangle, 18, 19
white, 10
width, 8, 9
windowActivated(O), 33
windowClosed(O), 33
windowClosing(O), 32
windowDeactivated(O), 33
windowDeiconified(O), 33
windowIconified(O), 32
windowOpened(O), 32
x, 7, 9
y, 7, 9
yellow, 10
ZapfDingbats, 7