#!/usr/cogent/bin/phgamma

/*
 * This example demonstrates the use of active values.  An active value
 * is a symbol which also carries code to be executed whenever its value
 * changes.  This is useful for adding side_effects to program variables.
 * For example, it might be very useful to add a function which will
 * update a Photon widget whenever a variable changes.  Active values
 * make it possible to implement forward_chaining expert systems very
 * easily.  An active value is established by calling the add_set_function
 * function.
 *
 * Remember, since it is possible to chain active values, it is possible
 * to create infinite chaining loops.
 *
 * This file is best viewed with a tab width of 4.
 */

/*
 * Create a simple Photon window which lets us see our active values
 * in action.
 */

PtInit(nil);

/*
 * Load PhAB support
 */

method PtWidget.constructor ()
{ PtRealizeWidget (self); }

require_lisp ("PhabTemplate");

/*
 * Load the window.
 */

w = car (PhabLoad ("wgt/example11.wgtw"));

/*
 * When the user presses or holds the button, b is incremented.
 */

PtAttachCallback (button, Pt_CB_ACTIVATE, #b++);
PtAttachCallback (button, Pt_CB_REPEAT, #b++);
PtRealizeWidget (w);

/*
 * Make a an active value, by attaching a piece of code which will set
 * the A value label to the current value of a.
 */

add_set_function (#a, #lab_a.text_string = string (a));

/*
 * Make b an active value, such that whenever b changes, it sets a to
 * be the square root of b.  This type of dependency is common when
 * writing an expert system, or maintaining a mapping relationship (as is
 * commonly done in implementing fuzzy sets).  More than one function can
 * be placed on a variable, so we will also make b update its label.
 */

add_set_function (#b, #a = sqrt(b));
add_set_function (#b, #lab_b.text_string = string (b));

/*
 * Start b at a known numeric value.
 */

b = 0;

/*
 * Loop forever.
 */

PtMainLoop();
