Author: Frederik Holljen Date: 2006-09-22 16:29:10 +0200 (Fri, 22 Sep 2006) New Revision: 3533
Log: - added tutorial for SignalSlot Added: trunk/SignalObserver/docs/tutorial.txt trunk/SignalObserver/docs/tutorial_multiple_slots_example.php trunk/SignalObserver/docs/tutorial_prioritized_slots_example.php trunk/SignalObserver/docs/tutorial_signals_in_class_example.php trunk/SignalObserver/docs/tutorial_signals_with_parameters_example.php trunk/SignalObserver/docs/tutorial_simple_signal_example.php trunk/SignalObserver/docs/tutorial_slot_types_example2.php trunk/SignalObserver/docs/tutorial_slot_types_example3.php trunk/SignalObserver/docs/tutorial_static_connections_example.php Added: trunk/SignalObserver/docs/tutorial.txt =================================================================== --- trunk/SignalObserver/docs/tutorial.txt 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial.txt 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,188 @@ +eZ components - SignalSlot +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. contents:: Table of Contents + +Introduction +============ + +The SignalSlot component implements a mechanism for inter and intra object +communication through the use of signals and slots. Signals are emitted through +instances of the ezcSignalCollection class and connected to as many functions as you +like. A function that is connected to a signal is called a slot. When the +signal is emitted all connected slots will be run in the order they are +connected or in the order of the priorities specified when connecting to the signals. + +The SignalSlot library supports signals with arguments that are passed on to +the slot. Slots must accept all the parameters that are sent to it. The +SignalSlot library also support prioritized slots. Using this mechanism you can +ensure that a slot is run either before or after other slots. + +There are many different variations of the Signal/Slot model. The original +implementations required you to derive from the Signal class in order to have +signals or slots. This is acceptable for languages that support multiple +inheritance. Newer implemtentations circumvent this problem by representing signals +through one instance of the Signal class. In other words, a class that has two +signals will have member two variables holding instances of the Signals class. +This approach can lead to the creation of a lot signal objects which can be +especially problematic for scripting languages. As a result our signal class +can represent several signals. + +Class overview +============== + +This section gives you an overview of the main classes of in the Mail +component. + +ezcSignalCollection + This class represents a collection of signals. You can emit or connect to the + signals using the methods available on this class. + +ezcSignalStaticConnections + This class holds the static connections for your application. Static + connections are connections to signals that can be emitted by several + different instances of ezcSignalCollection. + +Usage +===== + +A simple signal +--------------- + +This first example shows the simplest possible usage of the signal system. We +simply create a new ezcSignalCollection class, connect the "sayHello" signal to +the function "hello" and emit the signal. + +.. include:: tutorial_simple_signal_example.php + :literal: + +The output of this example yields the classic "Hello world". + + +Slot types +---------- +Slots are not limited to be normal functions only. They are specified using the +pseudo type callback_. You can specify normal functions class methods and +static class methods as shown by these variations of the above example. + +.. _callback: http://www.imc.org/rfcs.html + +1. functions + +.. include:: tutorial_simple_signal_example.php + :literal: + +2. class methods + +.. include:: tutorial_slot_types_example2.php + :literal: + +3. static class methods + +.. include:: tutorial_slot_types_example2.php + :literal: + + +Signals in a class +------------------ + +Typical usage of signals is to have classes emit them when certain events +happen. The following example shows a data object that emits a signal when its +data is changed. The signal is connected to the caching system that clears the +cache when the data is changed. + +This example also displays how you can delay the construction of the +ezcSignalCollection object. This can be useful in applications where signals +are used only rarely and you want to avoid the overhead of creating the object. + +.. include:: tutorial_signals_in_class_example.php + :literal: + + +Signals with parameters +----------------------- + +Signals can have parameters that will be passed on to the receiving slots. The +next example is an extension of the previous example where the data object +gives some information about the data that was changed. This information is +passed to the receiving slots as a parameter. + +.. include:: tutorial_signals_with_parameters_example.php + :literal: + +Note that slots must accept the parameters that are passed to them. You will +get errors / warnings if you provide to few or to many parameters to the slots +you have connected to a signal. + +Also note that it is not possible to pass signal parameters by +reference except for object types which are always references in PHP 5+. + + +Multiple slots +-------------- + +It is possible to connect several slots to one signal. This just a matter of +calling connect several times. You can freely mix the different slot types. +The following example adds another connection to our previous example that +regenerates the cache after it has been deleted. + +.. include:: tutorial_multiple_slots_example.php + :literal: + + +Prioritized slots +----------------- + +The previous example shows how to connect several slots to one signal and how +they are executed one after another. The example code is also dependent on the +order the slots are executed. Normally slots are executed in the order they are +connected. Sometimes however it is not possible to connect slots in the order +you want them to be executed. To ensure that some slots are executed before +others you can use the priority system. When connecting you can specify a +priority for that connection. Connections with a higher priority will be +executed before connections with a lower priority. Priority numbers can be +specified using any positive integer. The lower the number the higher the +priority. By default connections are made with a priority of 1000. + +This example shows how the connections in Multiple Slots could have been +specified to ensure the order the slots are called. + +.. include:: tutorial_prioritized_slots_example.php + :literal: + +Excessive usage of the priority system can lead to unmaintainable code since it +is hard to track the various priorities that are in use in a system. We don't +recommend using it unless absolutely neccessary. + + +Static connections +------------------ + +Sometimes it is useful to connect a signal with a specific name regardless of +the sender ezcSignalCollection to a slot. E.g consider what would happen if the +Data class from our previous example was extended to a DataObject class with a +potential of thousand of instances. If you wanted the caching system to work +you would have to connect each one to the caching system upon creation. + +This is both unpractical and time consuming. The solution is to use static +connections. When creating ezcSignalCollection objects you can provide an +identifier to the constructor. Using the ezcSignalStaticConnections you can +connect to all signals from a source with a specific identifier. + +The following example shows how to use static connections to connect the signal +"dataChanged" from all objects of the type "DataObject" to the caching system. + +.. include:: tutorial_static_connections_example.php + :literal: + + +You can mix static connectons and normal connections freely. Static connections +with the same priority as normal connections are executed after the normal connections. + + +.. + Local Variables: + mode: rst + fill-column: 79 + End: + vim: et syn=rst tw=79 Property changes on: trunk/SignalObserver/docs/tutorial.txt ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/SignalObserver/docs/tutorial_multiple_slots_example.php =================================================================== --- trunk/SignalObserver/docs/tutorial_multiple_slots_example.php 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial_multiple_slots_example.php 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,43 @@ +<?php +class Data +{ + private $signals = null; + + public function signals() + { + if( $this->signals == null ) $this->signals = new ezcSignalCollection(); + return $this->signals; + } + + public function manipulate() + { + // change the data here + $this->signals()->emit( "dataChanged", "calender" ); + } +} + +class Cache +{ + public function deleteCache( $type ) + { + echo "Deleting cache for ID: {$type}\n"; + } +} + +class CacheGenerator +{ + public function generateCache( $identifier ) + { + echo "Generating cache for ID: {$identifier}\n"; + } +} + +$cache = new Cache(); +$cacheGenerator = new CacheGenerator(); + +$data = new Data(); +$data->signals()->connect( "dataChanged", array( $cache, "deleteCache" ) ); +$data->signals()->connect( "dataChanged", array( $cacheGenerator, "generateCache" ) ); + +$data->manipulate(); +?> Property changes on: trunk/SignalObserver/docs/tutorial_multiple_slots_example.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/SignalObserver/docs/tutorial_prioritized_slots_example.php =================================================================== --- trunk/SignalObserver/docs/tutorial_prioritized_slots_example.php 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial_prioritized_slots_example.php 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,43 @@ +<?php +class Data +{ + private $signals = null; + + public function signals() + { + if( $this->signals == null ) $this->signals = new ezcSignalCollection(); + return $this->signals; + } + + public function manipulate() + { + // change the data here + $this->signals()->emit( "dataChanged", "calender" ); + } +} + +class Cache +{ + public function deleteCache( $type ) + { + echo "Deleting cache for ID: {$type}\n"; + } +} + +class CacheGenerator +{ + public function generateCache( $identifier ) + { + echo "Generating cache for ID: {$identifier}\n"; + } +} + +$cache = new Cache(); +$cacheGenerator = new CacheGenerator(); + +$data = new Data(); +$data->signals()->connect( "dataChanged", array( $cacheGenerator, "generateCache" ), 20 ); +$data->signals()->connect( "dataChanged", array( $cache, "deleteCache" ), 10 ); + +$data->manipulate(); +?> Property changes on: trunk/SignalObserver/docs/tutorial_prioritized_slots_example.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/SignalObserver/docs/tutorial_signals_in_class_example.php =================================================================== --- trunk/SignalObserver/docs/tutorial_signals_in_class_example.php 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial_signals_in_class_example.php 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,31 @@ +<?php +class Data +{ + private $signals = null; + public function signals() + { + if( $this->signals == null ) $this->signals = new ezcSignalCollection(); + return $this->signals; + } + + public function manipulate() + { + // change the data here + $this->signals()->emit( "dataChanged" ); + } +} + +class Cache +{ + public function deleteCache() + { + echo "Deleting cache\n"; + } +} + +$cache = new Cache(); +$data = new Data(); +$data->signals()->connect( "dataChanged", array( $cache, "deleteCache" ) ); + +$data->manipulate(); +?> Property changes on: trunk/SignalObserver/docs/tutorial_signals_in_class_example.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/SignalObserver/docs/tutorial_signals_with_parameters_example.php =================================================================== --- trunk/SignalObserver/docs/tutorial_signals_with_parameters_example.php 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial_signals_with_parameters_example.php 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,32 @@ +<?php +class Data +{ + private $signals = null; + + public function signals() + { + if( $this->signals == null ) $this->signals = new ezcSignalCollection(); + return $this->signals; + } + + public function manipulate() + { + // change the data here + $this->signals()->emit( "dataChanged", "calender" ); + } +} + +class Cache +{ + public function deleteCache( $type ) + { + echo "Deleting cache for ID: {$type}\n"; + } +} + +$cache = new Cache(); +$data = new Data(); +$data->signals()->connect( "dataChanged", array( $cache, "deleteCache" ) ); + +$data->manipulate(); +?> Property changes on: trunk/SignalObserver/docs/tutorial_signals_with_parameters_example.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/SignalObserver/docs/tutorial_simple_signal_example.php =================================================================== --- trunk/SignalObserver/docs/tutorial_simple_signal_example.php 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial_simple_signal_example.php 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,10 @@ +<?php +function hello() +{ + echo "Hello world\n"; +} + +$signals = new ezcSignalCollection(); +$signals->connect( "sayHello", "hello" ); +$signals->emit( "sayHello" ); +?> Property changes on: trunk/SignalObserver/docs/tutorial_simple_signal_example.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/SignalObserver/docs/tutorial_slot_types_example2.php =================================================================== --- trunk/SignalObserver/docs/tutorial_slot_types_example2.php 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial_slot_types_example2.php 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,13 @@ +<?php +class HelloClass +{ + public function hello() + { + echo "Hello world\n"; + } +} + +$signals = new ezcSignalCollection(); +$signals->connect( "sayHello", array( new HelloClass(), "hello" ) ); +$signals->emit( "sayHello" ); +?> Property changes on: trunk/SignalObserver/docs/tutorial_slot_types_example2.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/SignalObserver/docs/tutorial_slot_types_example3.php =================================================================== --- trunk/SignalObserver/docs/tutorial_slot_types_example3.php 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial_slot_types_example3.php 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,13 @@ +<?php +class HelloClass +{ + public static function hello() + { + echo "Hello world\n"; + } +} + +$signals = new ezcSignalCollection(); +$signals->connect( "sayHello", array( "HelloClass", "hello" ) ); +$signals->emit( "sayHello" ); +?> Property changes on: trunk/SignalObserver/docs/tutorial_slot_types_example3.php ___________________________________________________________________ Name: svn:eol-style + native Added: trunk/SignalObserver/docs/tutorial_static_connections_example.php =================================================================== --- trunk/SignalObserver/docs/tutorial_static_connections_example.php 2006-09-22 09:53:43 UTC (rev 3532) +++ trunk/SignalObserver/docs/tutorial_static_connections_example.php 2006-09-22 14:29:10 UTC (rev 3533) @@ -0,0 +1,41 @@ +<?php +class DataObject +{ + private $signals = null; + private $identifier = null; + + public function __construct( $id ) + { + $this->identifier = $id; + } + + public function signals() + { + if( $this->signals == null ) $this->signals = new ezcSignalCollection( __CLASS__ ); + return $this->signals; + } + + public function manipulate() + { + // change the data here + $this->signals()->emit( "dataChanged", $this->identifier ); + } +} + +class Cache +{ + public function deleteCache( $identifier ) + { + echo "Deleting cache for ID: {$identifier}\n"; + } +} + +$cache = new Cache(); +ezcSignalStaticConnections::getInstance()->connect( "DataObject", + "dataChanged", array( $cache, "deleteCache" ) ); + +$data1 = new DataObject( 1 ); +$data2 = new DataObject( 2 ); +$data1->manipulate(); +$data2->manipulate(); +?> Property changes on: trunk/SignalObserver/docs/tutorial_static_connections_example.php ___________________________________________________________________ Name: svn:eol-style + native -- svn-components mailing list [email protected] http://lists.ez.no/mailman/listinfo/svn-components
