CGLIB

A Constraint-based Graphics Library for B-Prolog

(Version 6.5)

By Neng-Fa Zhou

Afany Software & CUNY

Copyright © Afany Software, 2000-2003

1

Preface

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

1

Table of Contents

Preface

Table of Contents

1. Getting Started

1.1 An illustrative example

1.2 Installation

1.3Start and quit B-Prolog with CGLIB

1.4 Open and close windows

1.4 Draw graphics and clean windows

2. Creating Objects

2.1 Attribute objects

2.2 Windows

2.3 Graphical objects

2.4 Menu bars, menus and menu items

2.5 File dialogs

3. Constraints

3.1 Position constraints

3.2 Same property constraints

3.3 Grid and table constraints

3.4 Tree constraint

3.5 Not overlap constraint

4. Operations on Objects

4.1 Packing and Showing Objects

The primitive cgShow(O) shows O, and the primitive cgPack(O) packs O, where O can be one object or a list of objects.

4.2 Altering and Moving Objects

5. Animation

6.Generating Java Applets

7.Event Handling

7.1 Action rules

Agent ConditionSeq {Event} => ActionSeq

7.2 Events

Action events

Focus events

Key events

Mouse events

Window events

Window resize and move events

Item events

Adjustment events

Text events

Timer events

8.Examples

8.1 Drawing a flag

8.2Drawing binary trees

8.3Drawing a diagram of Java AWT’s classes

8.4Building a calculator

8.5Building a digital clock

8.6Demonstrating a geometry theorem on quadrilaterals

Appendix-I. Built-in Components

Appendix-II. Built-in Events

Appendix-III. Built-ins for Testing Key Codes

Index

1

1. Getting Started

1.1 An illustrative example

Let us start with the following program to taste the flavor of CGLIB:

The call cgButton(B,“Hello World”) in line (1) creates a button Bwith 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.

1.2 Installation

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

  1. 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.

  1. Restart your computer.

Notice that the environment variable BPDIR must be reset correctly if the system is installed in a directory other than c:\.

1.3Start and quit B-Prolog with CGLIB

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.

1.4 Open and close windows

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.

1.4 Draw graphics and clean windows

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 designatedwindow.

?-cgWindow(W), cgStar(S), S^window #= W, cgShow(S)

The constraint S^window #= Wspecifies 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)

2. Creating Objects

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.

2.1 Attribute objects

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 objectsP. A point object has two constrainable attributes, namely, xand 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.

2.2 Windows

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 Wwith 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

2.3 Graphical objects

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 Ois 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 objectO, O^font #= F, O^fontName #= F^name.
  • fontSize: For each objectO, O^font #= F, O^fontSize #= F^size.
  • fontStyle: For each objectO, 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 objectO,
    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).