Delphi GUI Predicates

The Delphi GUI Predicates (DelGUI) are a collection of extended predicates that allow Prolog to directly access and manipulate Delphi controls. For example, there are predicates that allow you to draw in paintbox controls and add lines to memo controls. They are by no means a complete collection, but provide a framework and useful start that can be easily supplemented with your own predicates.

They are contained in two files in the samples\delphi\delgui directory.

Using DelGUI

To use DelGUI you must perform the following steps.
  1. Include delgui.pas in your Delphi project.
  2. Include delgui.pro in your Prolog project, linking it with your Prolog code to form a .xpl file which is loaded by the Delphi program.
  3. Include the Amzi! Logic Server component in the main form, or some other convenient place, for the Delphi application.
  4. Initialize the Logic Server and DelGUI predicates before loading the application's Prolog code. (The mainform create is a convenient place to do this.) This is done using the normal Logic Server Initialization with the added step of calling DG_Init between the InitLS and LoadXPL functions. DG_Init takes one argument, which is the Logic Server object.
  5. (optional) For each control you want Prolog to access, you should somehow make the address of that control available to Prolog. One simple way is to assert Prolog facts with a symbolic name for each control and its address.
  6. Close the Logic Server when done. (The mainform destroy is a convenient place to do this.)
There is a test project in the samples/delphi/delgui directory that can be used as a template for building applications that use the Delphi GUI Predicates. It includes code needed to initialize and start work with the Delphi GUI Predicates and a one button form that tests to make sure its all connected correctly. For step 5 (above) it is convenient to define a function that asserts controls as dynamic clauses(facts) in the Prolog logicbase. Those asserted facts can then be used by the Prolog logic to pick up the address of the control it needs to manipulate. The following is an example of such a function. It takes three arguments, being 1) the type of the control, 2) the name of the control and 3) the address of the control. It asserts these as the three arguments of a Prolog fact dyn_control/3.
procedure TTest.AssertControl(ctype, name: string; cntl: TControl);
var
  t: TTerm;
  c: TControl;
begin
  c := cntl;
  LSEng.MakeFA(t, 'dyn_control', 3);
  LSEng.UnifyAtomArg(t, 1, ctype);
  LSEng.UnifyAtomArg(t, 2, name);
  LSEng.UnifyArg(t, 3, dADDR, @cntl);
  LSEng.Asserta(t);
end;

Flow of Control Issue

The Delphi GUI predicates enable you to apply Prolog reasoning to the layout and display of the user interface. This can lead to some interesting applications, but there are some design issues that need to be addressed for a tight integration between Prolog and Delphi.

If you wish to have Prolog query the user, there are two approaches.

  1. You can have Prolog call an extended predicate and then start a new Windows message pump which waits for the answer and returns when it gets it. Unless necessary, this approach is probably better avoided.
  2. You can have Prolog call an extended predicate which puts up the question, control or whatever and then simply returns. In this case you have an OnX function in Delphi that waits for a response, and when it gets it, it calls Prolog. This is a little more complex in the code interaction, because you need to split the Prolog logic for asking questions and receiving answers, but is a cleaner separation of responsibilities.

Extended Predicates

These are the predicates defined in delgui.pas. The majority of them take, as the first argument, the address of the control to be manipulated. This argument is indicated by CA in following text.
showmessage(Msg)
Displays the message Msg in a message box. Msg is a string. To display other Prolog terms, see w_message in the Prolog tools.
The predicates beginning with draw_ apply to canvas controls.
draw_lineto(CA, X, Y)
Draw a line to X, Y.
draw_moveto(CA, X, Y)
Move the pen to X, Y.
draw_textout(CA, X, Y, S)
Write the string S at position X, Y.
draw_textheight(CA, S, IH)
Unify IH with the height of character string S.
draw_textwidth(CA, S, IW)
Unify IW with the width of character string S.
draw_cliprect(CA, Top, Left, Bot, Rt)
Unify the four arguments with the coordinates of the clipping rectangle.
draw_rectangle(CA, Top, Left, Bot, Rt)
Draw a rectangle using the coordinates.
draw_ellipse(CA, Top, Left, Bot, Rt)
Draw an ellipse in the coordinates.
draw_pen(CA, SColor, IWidth)
Set the pen to the color named in the string SColor and to the width specified in IWidth.
draw_font(CA, SFont, SColor, ISize)
If the arguments are variables, then they are unified with the current font name, color and size. If they are bound terms, the current font name, color and size are set to the new values.
draw_brush(CA, SColor, SStyle)
Set the brush to the color and style specified.
The predicates beginning with memo_ apply to memo controls.
memo_add(CA, S)
Add the string S to the memo.
memo_lines(CA, ILine, S)
Unify string S with memo line number ILine.
memo_delete(CA, ILine)
Delete memo line ILine.
The predicates beginning with edit_ apply to edit controls
edit_text(CA, S)
If S is a variable, unify it with the text in the edit control, otherwise set the text to the bound string S.
edit_modified(CA)
If the control is modified, returns true, otherwise returns false.
The predicates beginning with radio_ apply to radio button controls.
radio_group(CA, ItemList)
Add each of the items in ItemList to the radio group.
radio_selected(CA, I)
If I is a variable, unify it with the radio group item index. It if is bound, then set the radio group index to it.
The predicates beginning with ctrl_ apply to any control.
ctrl_visible(CA, I)
If I = 0, set the control's visible property to false, otherwise set it to true.
The following functions integrate Prolog with other third party Delphi components.

Predicates beginning with graph_ apply to SciGraph controls. The SciGraph component is available from Pierre Mertz. Information about SciGraph is available from the web site: http://www.ee.princeton.edu/~phmertz/scigraph/scigraph.html

You'll find the SciGraph functions are commented out in the source code. If you install SciGraph, then you can uncomment those functions and add SciGraph to the 'uses' list.

graph_function(CA, Start, Stop, Inc, EQ)
This function maps a Prolog symbolic equation, such as f(X) = X**2 to a scientific graph. EQ is the equation and Start, Stop and Inc delimit the range of X values to be plotted. (It makes use of internal predicates defined in DELGUI.PRO.)

Prolog Predicates

w_message(T)
Converts T to a string and then call showmessage. This predicate illustrates how a simple Prolog front-end can make an extended predicate easier to work with.
set_equation(SEq), paint_equation(CA)
These two predicates implement the complex function of displaying a symbolic Prolog equation in a format as it might appear in a text book, that is, with fractions written above and below and square roots written with full radical symbols. They use two parts because paint boxes are not drawn directly, but rather are only drawn when the Delphi program receives the OnPaint command for the paint box control. paint_equation/1 does the painting. See the source codes for details, as this predicate illustrates the power of Prolog for graphical layout.

Sample

See the sample in samples/delphi/eq for an illustration of using DelGUI and in particular the equation display function.

Copyright ©1987-2011 Amzi! inc. All Rights Reserved. Amzi! is a registered trademark and Logic Server is a trademark of Amzi! inc.