|
Posted by Konrad Kleine on 09/16/05 22:20
Qt like Signals and Slots (Idea + Implementation)
Hey,
I am a big fan of Qt from Trolltech.com and I especially like the signals and slot mechanism. I have implemented a small example in php here.
It is really not thought of to be production ready, but think about it a little while ;)
You can emit any signal you want with this example unlike to Qt, where
you have to declarate it in your class.
What is done here?
- There is a base class called "PBase".
- The class "A", "B" and "C" extend the base class "PBase".
- We create objects of all three classes.
- Then we connect a signal sent from the A-object to a slot function in the B- and to a completely other slot function in the C-object.
- When calling the method in the A-object that emits this special signals, the slot function of the B- and C-object are automatically called in arbitary order.
What needs to be done?
- You must have the ability to disconnect an object from a signal
- The way the connections are saved is bad (I think). It should be sufficient to store one reference per object.
Where is the code? Well, here:
<?php
function connect ( $sender_obj, $signal_string, $reciever_obj, $slot_string )
{
$sender_obj->connect( $sender_obj, $signal_string, $reciever_obj, $slot_string );
}
abstract class BaseClass
{
private $connection_array;
public function __construct()
{
$this->connection_array = array();
}
public function connect( $sender_obj, $signal_string, $reciever_obj, $slot_string )
{
$tmp = array();
$tmp['sender'] = $sender_obj;
$tmp['signal'] = $signal_string;
$tmp['reciever']= $reciever_obj;
$tmp['slot'] = $slot_string;
array_push( $this->connection_array, $tmp );
}
protected function do_emit_signal()
{
$param_count = func_num_args();
$param_array = func_get_args();
if ( $param_count < 1 )
{
trigger_error("the signals name is missing", E_USER_NOTICE);
}
$param_array = array_slice($param_array, 1, $param_count-1, true);
//$sender_name_string = get_class(); // the name of the class that has connected
$signal_name_string = func_get_arg(0);
foreach ( $this->connection_array as $key => $con )
{
// make sure, we truely talk about the same object (@see === operator)
if ( $con['sender'] === $this && $con['signal'] == $signal_name_string )
{
call_user_func_array(
array(
$con['reciever'],
$con['slot']
),
$param_array
);
}
}
}
}
class A extends BaseClass
{
public function __construct()
{
parent::__construct();
}
public function do_something()
{
// do something here...
// and then you might want to emit a signal
$this->do_emit_signal("clicked", "it's me from A");
}
}
class B extends BaseClass
{
public function __construct()
{
parent::__construct();
}
public function slot_handle_clicked( $string )
{
echo "Hey, I am B and I just caught this value from a signal: <b>" . $string . "</b><br />";
}
}
class C extends BaseClass
{
public function __construct()
{
parent::__construct();
}
public function catch_my_signal( $string )
{
echo "Hey, I am C and I just caught this value from a signal: <b>" . $string . "</b><br />";
}
}
$obj_a = new A();
$obj_b = new B();
$obj_c = new C();
connect( $obj_a, "clicked", $obj_b, "slot_handle_clicked" );
connect( $obj_a, "clicked", $obj_c, "catch_my_signal" );
$obj_a->do_something();
?>
__________________________________________________________________________
Erweitern Sie FreeMail zu einem noch leistungsstarkeren E-Mail-Postfach!
Mehr Infos unter http://freemail.web.de/home/landingpad/?mc=021131
[Back to original message]
|