Miscellaneous
|
|
|
|
<?php /*
+----------------------------------------------------------------------+
| Foo and Associates Library Code |
+----------------------------------------------------------------------+
| Copyright (c) 2001 Foo and Associates, All Rights Reserved |
+----------------------------------------------------------------------+
| This file is subject to version 1.00 of the Foo and Associates |
| license. A copy of this license is stored in the FOO-LICENCE file. |
| The licence can be viewed online at http://fooassociates.com/license |
| Send email to license@fooassociate.com to receive a copy via email. |
+----------------------------------------------------------------------+
| Authors: Zak Greant <zak@fooassociates.com> |
+----------------------------------------------------------------------+
*/
/* $Id: slots.php,v 1.2 2001/10/16 07:26:42 zak Exp $ */
/* TODO: Add additional error handling/reporting */
/* Slots and Signals
** =================
** This code is a simple implementation of the slots/signals concept.
** Slots and signals are used by the Qt toolkit as a kind of extra-powerful callback.
** The best source of information on them is the Qt toolkit docs
** see (http://doc.trolltech.com/3.0/signalsandslots.html)
**
** To briefly summarize, they allow you to bind a signal to one or more slots and/or signals.
** When a signal is 'emitted', all slots and signals bound to it are called. Each slot corresponds
** to a single function. When a signal is called by another signal, the called signal is emitted,
** calling the slots and signals that it is bound to.
**
** Any parameters passed when the signal is emitted are passed to the slots and signals that
** that are called. This easily allows you to write handler functions (slots) and bind them to events
** (signals) as needed - without having to make explicit function calls or rewrite handler functions
** just to accomodate minor modifications in how a function is called.
**
** I find slots and signals particular useful for message passing and error handling.
**
** Have Fun! :)
**
** Zak Greant
*/
function slot ( # Request or define a slot (one arg == request, two == define)
$name, # The name of the slot to request or define
$handler = NULL # The handler to bind to a slot when defining it (optional)
) {
static $slots = array (); # A static array containing all defined slots
if (is_null ($handler)) { # If the function is called with 1 argument
if (isset ($slots[$name])) # and the slot name requested is defined
return array ( # Return the slot
'type' => 'slot', # Note that each slot is an array containing 3 elements
'name' => $name,
'handler' => $slots[$name]
);
return FALSE; # If the slot name requested is not defined, exit
}
# If the function has been called with 2 arguments
if (! function_exists ($handler)) { # Ensure that the function named in $handler is defined
trigger_error ("Cannot create slot '$name'. Function '$handler' is not defined.");
return FALSE;
}
$slots[(string) $name] = (string) $handler; # Define the slot
return array (
'type' => 'slot',
'name' => $name,
'handler' => $slots[$name]
);
}
function signal ( # Return a signal (and define if needed)
$name # The name of the signal to define (and return)
) {
static $signals = array (); # A static array containing all signals
if (! isset ($signals[$name])) # If the called signal has not been defined, define it
$signals[$name] = TRUE; # Note that signals can easily be numeric values, allowing for numeric constants
return array (
'type' => 'signal',
'name' => $name
);
}
function signal_bind ( # Bind a signal to a slot or another signal signal (or list the bindings for a signal)
$signal, # The signal to bind/unbind - should be a call to signal()
$slot_or_signal = NULL # The slot/signal to bind to the signal (optional)
) {
static $bindings = array (); # A static array containing all the signal to signal/slot bindings
if (is_null ($slot_or_signal)) { # If called with one argument
if (is_array ($signal)
&& 'signal' == $signal['type'])
$signal = $signal['name'];
if (isset ($bindings[$signal]))
return $bindings[$signal]; # Return an array of signals and/or slots bound to $signal
return array (); # Return an empty array if nothing is bound to $signal
}
if (! is_array ($signal)
|| 'signal' != $signal['type'] # If $signal is not a valid signal
|| ! is_array ($slot_or_signal)) # If $slot_or_signal can not be a valid signal or slot
return FALSE;
$bindings[$signal['name']][] = $slot_or_signal; # Bind $slot_or_signal to $signal
return TRUE;
}
function emit ( # Call all the slots/signals bound to a signal
$signal # The signal to throw
) {
$args = func_get_args (); # Get the arguments passed with the signal
array_shift ($args); # Strip off the first argument - it contains the signal ($signal)
foreach (signal_bind ($signal) as $slot_or_signal) { # Call every signal or slot bound to $signal
if ('signal' == $slot_or_signal['type']) { # If the current bound item is a signal
array_unshift ($args, $slot_or_signal['name']); # Pass the arguments to the signal called
call_user_func_array ('emit', $args);
continue;
}
call_user_func_array ( # If the current bound item is not a signal
$slot_or_signal['handler'], # It must be a slot - call it
$args # Pass the arguments to it
);
}
}
/* Basic usage examples
Uncomment to perform some simple tests
function bar () {
$args = func_get_args ();
echo implode ('::', $args), "<br />";
}
slot ('argent', create_function ('', 'echo "Silver<br />";'));
signal_bind (signal ('foo'), slot ('bar', 'bar'));
signal_bind (signal ('foo'), slot ('bar'));
signal_bind (signal ('far'), signal ('foo'));
signal_bind (signal ('far'), slot ('argent'));
emit ('foo', 'a', 1, 2);
emit ('foo', 2, 1);
emit ('far', 'test', 'test2');
emit ('lar', 'loo');
*/ ?>
?>
|
|
|
Usage Example
|
|
|
Rate This Script
|
|
|
|