|Did you know ...||Search Documentation:|
On this page, we will give an impression on what programming and using XPCE looks like. This is by no means a manual. Definitions of classes and methods used in the examples are not provided.
XPCE adds four predicates to Prolog. The predicate new/2 creates an object, send/2 modifies an object or performs a boolean test, get/3 queries an object and free/1 destroys an object.
An object is represented using an object-reference, which is a @/1, which is defined as a prefix operator. For example, @display refers to an instance of class display representing the default screen and @658211 (see example below) is a unique reference generated by XPCE.
An object is created from an object term, a Prolog term whose functor denotes the class from which to create the object, and whose arguments are the initialisation arguments for creating the object. The arguments in turn can be object terms.
The following dialogue illustrates these predicates by creating and opening a simple graphical window, asking the size of this (default) window and destroying it again.
?- new(X, picture). X = @658211 . ?- send(@658211, open(point(200,200))). true. ?- get(@658211, size, size(W, H)). W = 400, H = 200 . ?- free(@658211). true.
The following example creates a modal dialogue window that prompts the user for a name. First, a dialog window is created. Dialog windows have rules that control the layout of the items placed in them, and computes the required size dynamically from the content. The first item added is a text_item, a field for entering a (short) textual value. Second is a button called OK which, when activated, will send the return message to the dialog window, providing the typed text as argument. This causes the confirm modal loop to return. Next, a button called Cancel is added, which causes the modal loop to return with the constant @nil. The remainder starts the modal loop, destroys the window checks for cancel (causing the predicate to fail) and returns the result.
ask_name(Name) :- new(D, dialog('Register')), send(D, append(new(NameItem, text_item(name)))), send(D, append(button(ok, message(D, return, NameItem?selection)))), send(D, append(button(cancel, message(D, return, @nil)))), send(D, default_button(ok)), get(D, confirm, Rval), free(D), Rval \== @nil, Name = Rval.
?- ask_name(Name). Name = 'Bert'
In this section, we will create the same functionality to prompt for a name by defining a XPCE class. This is not a typical example for using a class, but it illustrates the two ways to achieve the same goal.
The class definition is embraced by :- pce_begin_class and :- pce_end_class. Methods are similar to clauses, but the head and body is separated by :-> for a send- and :<- for a get- method.
Prolog term-expansion translates the method declaration into a registration of the method with the current XPCE class, as well as a clause dealing with the implementation. Arguments in the head can optionally be followed by :<type>. The type is registered with the method, and verified by XPCE type logic at runtime.
As the execution of the method body is in Prolog, all normal Prolog debugging and development tools may be used.
The initialise method is the constructor of the class. Buttons by default invoke the method indicated by their name on the window on which they are displayed, so ok and cancel are called if the corresponding button is pressed. Finally, prompt runs the and destroys the prompter.
:- use_module(library(pce)). :- pce_begin_class(name_asker, dialog, "Modal prompter for a name"). initialise(W, Label:[name]) :-> "Initialise the window and fill it":: send_super(W, initialise(Label)), send(W, append(text_item(name))), send(W, append(button(ok))), send(W, append(button(cancel))), send(W, default_button(ok)). ok(W) :-> "User pressed the OK button":: get(W, member(name), NameItem), get(NameItem, selection, Typed), send(W, return, Typed). cancel(W) :-> "User pressed the Cancel button":: send(W, return(@nil)). prompt(W, Value:name) :<- "Open it, destroy it and return the result":: get(W, confirm, Value), free(W). :- pce_end_class.
After loading this definition, the following suffices to prompt for a name:
?- get(name_asker('Register'), prompt, Name). Name = 'Bert'.