NAME
Prima::Object - Prima toolkit base classes
SYNOPSIS
if ( $obj-> isa('Prima::Component')) {
# set and get a property
my $name = $obj-> name;
$obj->name( 'an object' );
# set a notification callback
$obj-> onPostMessage( sub {
shift;
print "hey! I've received this: @_\n";
});
# can set multiple properties. note, that 'name' and 'owner',
# replace the old values, while onPostMessage are aggregated.
$obj-> set(
name => 'AnObject',
owner => $new_owner,
onPostMessage => sub {
shift;
print "hey! me too!\n";
},
);
# de-reference by name
$new_owner-> AnObject-> post_message(1,2);
}
DESCRIPTION
Prima::Object and Prima::Component are the root objects of the Prima
toolkit hierarchy. All the other objects are derived from the Component
class, which in turn is the only descendant of Object class. Both of
these classes are never used for spawning their instances, although
this is possible using
Prima::Component-> create( .. parameters ... );
call. This document describes the basic concepts of the OO programming
with Prima toolkit. Although Component has wider functionality than
Object, all examples will be explained on Component, since Object has
no descendant classes and all the functionality of Object is present in
Component. Some of the information here can be found in
Prima::internals as well, the difference is that Prima::internals
considers the coding tasks from a C programmer’s view, whereas this
document is wholly about perl programming.
Object base features
Creation
Object creation has fixed syntax:
$new_object = Class-> create(
parameter => value,
parameter => value,
...
);
Parameters and values form a hash, which is passed to the create()
method. This hash is applied to a default parameter-value hash ( a
profile ), specific to every Prima class. The object creation is
performed in several stages.
create
create() calls profile_default() method that returns ( as its name
states ) the default profile, a hash with the appropriate default
values assigned to its keys. The Component class defaults are (
see Classes.pm ):
name => ref $_[ 0],
owner => $::application,
delegations => undef,
While the exact meaning of these parameters is described later, in
"Properties", the idea is that a newly created object will have
’owner’ parameter set to ’$::application’ and ’delegations’ to
undef etc etc - unless these parameters are explicitly passed to
create(). Example:
$a1 = Prima::Component-> create();
$a1’s owner will be $::application
$a2 = Prima::Component-> create( owner => $a1);
$a2’s owner will be $a1. The actual merging of the default and the
parameter hashes is performed on the next stage, in
profile_check_in() method which is called inside profile_add()
method.
profile_check_in
A profile_check_in() method merges the default and the parameter
profiles. By default all specified parameters have the ultimate
precedence over the default ones, but in case the specification is
incomplete or ambiguous, the profile_check_in()’s task is to
determine actual parameter values. In case of Component, this
method maintains a simple automatic naming of the newly created
objects. If the object name was not specified with create(), it is
assigned to a concatenated class name with an integer - Component1,
Component2 etc.
Another example can be taken from
Prima::Widget::profile_check_in(). Prima::Widget horizontal
position can be specified by using basic "left" and "width"
parameters, and as well by auxiliary "right", "size" and "rect".
The default of both "left" and "width" is 100. But if only "right"
parameter, for example, was passed to create() it is
profile_check_in() job to determine "left" value, given that
"width" is still 100.
After profiles gets merged, the resulting hash is passed to the
third stage, init().
init
init() duty is to map the profile content into object, e.g., assign
"name" property to "name" parameter value, and so on - for all
relevant parameters. After that, it has to return the profile in
order the overridden subsequent init() methods can perform same
actions. This stage along with the previous is exemplified in
almost all Prima modules.
Note: usually init() attaches the object to its owner in order to
keep the newly-created object instance from being deleted by
garbage-collection mechanisms. More on that later ( see "Links
between objects").
After init() finishes, create() calls setup() method
setup
setup() method is a convenience function, it is used when some
post-init actions must be taken. It is seldom overloaded, primarily
because the Component::setup() method calls "onCreate"
notification, which is more convenient to overload than setup().
As can be noticed from the code pieces above, a successful create()
call returns a newly created object. If an error condition occurred,
undef is returned. It must be noted, that only errors that were
generated via die() during init() stage result in undef. Other errors
raise an exception instead. It is not recommended to frame create()
calls in an "eval{}" block, because the error conditions can only occur
in two situations. The first is a system error, either inside perl or
Prima guts, and not much can be done here, since that error can very
probably lead to an unstable program and almost always signals an
implementation bug. The second reason is a caller’s error, when an
unexistent parameter key or invalid value is passed; such conditions
are not subject to a runtime error handling as are not the syntax
errors.
After create(), the object is subject to the event flow. As "onCreate"
event is the first event the object receives, only after that stage
other events can be circulated.
Destruction
Object destruction can be caused by many conditions, but all execution
flow is finally passed through destroy() method. destroy(), as well as
create() performs several finalizing steps:
cleanup
The first method called inside destroy() is cleanup(). cleanup()
is the pair to setup(), as destroy() is the pair to create().
cleanup() generates "onDestroy" event, which can be overridden more
easily than cleanup() itself.
"onDestroy" is the last event the object sees. After cleanup() no
events are allowed to circulate.
done
done() method is the pair to init(), and is the place where all
object resources are freed. Although it is as safe to overload
done() as init(), it almost never gets overloaded, primarily
because overloading "onDestroy" is easier.
The typical conditions that lead to object destructions are direct
destroy() call, garbage collections mechanisms, user-initiated window
close ( on "Prima::Window" only ), and exception during init() stage.
Thus, one must be careful implementing done() which is called after
init() throws an exception.
Methods
The class methods are declared and used with perl OO syntax, which
allow both method of object referencing:
$object-> method();
and
method( $object);
The actual code is a sub, located under the object class package. The
overloaded methods that call their ancestor code use
$object-> SUPER::method();
syntax. Most Prima methods have fixed number of parameters.
Properties
Properties are methods that combine functionality of two ephemeral
"get" and "set" methods. The idea behind properties is that many object
parameters require two independent methods, one that returns some
internal state and another that changes it. For example, for managing
the object name, set_name() and get_name() methods are needed. Indeed,
the early Prima implementation dealt with large amount of these get’s
and set’s, but later these method pairs were deprecated in the favor of
properties. Currently, there is only one method name() ( referred as
"::name" later in the documentation ).
The property returns a value if no parameters ( except the object) are
passed, and changes the internal data to the passed parameters
otherwise. Here’s a sketch code for "::name" property implementation:
sub name
{
return $_[0]-> {name} unless $#_;
$_[0]->{name} = $_[1];
}
There are many examples of properties throughout the toolkit. Not all
properties deal with scalar values, some accept arrays or hashes as
well. The properties can be set-called not only by name like
$object-> name( "new name");
but also with set() method. The set() method accepts a hash, that is
much like to create(), and assigns the values to the corresponding
properties. For example, the code
$object-> name( "new name");
$object-> owner( $owner);
can be rewritten as
$object-> set(
name => "new name",
owner => $owner
);
A minor positive effect of a possible speed-up is gained by eliminating
C-to-perl and perl-to-C calls, especially if the code called is
implemented in C. The negative effect of such technique is that the
order in which the properties are set, is undefined. Therefore, the
usage of set() is recommended either when the property order is
irrelevant, or it is known beforehand that such a call speeds up the
code, or is an only way to achieve the result. An example of the latter
case from Prima::internals shows that Prima::Image calls
$image-> type( $a);
$image-> palette( $b);
and
$image-> palette( $b);
$image-> type( $a);
produce different results. It is indeed the only solution to call for
such a change using
$image-> set(
type => $a,
palette => $b
);
when it is known beforehand that "Prima::Image::set" is aware of such
combinations and calls neither "::type" nor "::palette" but performs
another image conversion instead.
Some properties are read-only and some are write-only. Some methods
that might be declared as properties are not; these are declared as
plain methods with get_ or set_ name prefix. There is not much
certainty about what methods are better off being declared as
properties and vice versa.
However, if get_ or set_ methods cannot be used in correspondingly
write or read fashion, the R/O and W/O properties can. They raise an
exception on an attempt to do so.
Links between objects
Prima::Component descendants can be used as containers, as objects that
are on a higher hierarchy level than the others. This scheme is
implemented in a child-owner relationship. The ’children’ objects have
the "::owner" property value assigned to a reference to a ’owner’
object, while the ’owner’ object conducts the list of its children. It
is a one-to-many hierarchy scheme, as a ’child’ object can have only
one owner, but an ’owner’ object can have many children. The same
object can be an owner and a child at the same time, so the owner-child
hierarchy can be viewed as a tree-like structure.
Prima::Component::owner property maintains this relation, and is
writable - the object can change its owner dynamically. There is no
corresponding property that manages children objects, but is a method
get_components(), that returns an array of the child references.
The owner-child relationship is used in several ways in the toolkit.
For example, the widgets that are children of another widget appear (
usually, but not always ) in the geometrical interior of the owner
widget. Some events ( keyboard events, for example ) are propagated
automatically up and/or down the object tree. Another important feature
is that when an object gets destroyed, its children are destroyed
first. In a typical program the whole object tree roots in a
Prima::Application object instance. When the application finishes, this
feature helps cleaning up the widgets and quitting gracefully.
Implementation note: name ’owner’ was taken instead of initial
’parent’, because the ’parent’ is a fixed term for widget hierarchy
relationship description. Prima::Widget relationship between owner and
child is not the same as GUI’s parent-to-child. The parent is the
widget for the children widgets located in and clipped by its inferior.
The owner widget is more than that, its children can be located outside
its owner boundaries.
The special convenience variety of create(), the insert() method is
used to explicitly select owner of the newly created object. insert()
can be considered a ’constructor’ in OO-terms. It makes the construct
$obj = Class-> create( owner => $owner, name => 'name);
more readable by introducing
$obj = $owner-> insert( 'Class', name => 'name');
scheme. These two code blocks are identical to each other.
There is another type of relation, where objects can hold references to
each other. Internally this link level is used to keep objects from
deletion by garbage collection mechanisms. This relation is many-to-
many scheme, where every object can have many links to other objects.
This functionality is managed by attach() and detach() methods.
Events
Prima::Component descendants employ a well-developed event propagation
mechanism, which allows handling events using several different
schemes. An event is a condition, caused by the system or the user, or
an explicit notify() call. The formerly described events onCreate and
onDestroy are triggered after a new object is created or before it gets
destroyed. These two events, and the described below onPostMessage are
present in namespaces of all Prima objects. New classes can register
their own events and define their execution flow, using
notification_types() method. This method returns all available
information about the events registered in a class.
Prima defines also a non-object event dispatching and filtering
mechanism, available through "event_hook" static method.
Propagation
The event propagation mechanism has three layers of user-defined
callback registration, that are called in different order and contexts
when an event is triggered. The examples below show the usage of these
layers. It is assumed that an implicit
$obj-> notify("PostMessage", $data1, $data2);
call is issued for all these examples.
Direct methods
As it is usual in OO programming, event callback routines are
declared as methods. ’Direct methods’ employ such a paradigm, so if
a class method with name "on_postmessage" is present, it will be
called as a method ( i.e., in the object context ) when
"onPostMessage" event is triggered. Example:
sub on_postmessage
{
my ( $self, $data1, $data2) = @_;
...
}
The callback name is a modified lower-case event name: the name for
Create event is on_create, PostMessage - on_postmessage etc. These
methods can be overloaded in the object’s class descendants. The
only note on declaring these methods in the first instance is that
no "::SUPER" call is needed, because these methods are not defined
by default.
Usually the direct methods are used for the internal object book-
keeping, reacting on the events that are not designed to be passed
higher. For example, a Prima::Button class catches mouse and
keyboard events in such a fashion, because usually the only
notification that is interesting for the code that employs push-
buttons is "Click". This scheme is convenient when an event
handling routine serves the internal, implementation-specific
needs.
Delegated methods
The delegated methods are used when objects ( mostly widgets )
include other dependent objects, and the functionality requires
interaction between these. The callback functions here are the
same methods as direct methods, except that they get called in
context of two, not one, objects. If, for example, a $obj’s owner,
$owner would be interested in $obj’s PostMessage event, it would
register the notification callback by
$obj-> delegations([ $owner, 'PostMessage']);
where the actual callback sub will be
sub Obj_PostMessage
{
my ( $self, $obj, $data1, $data2) = @_;
}
Note that the naming style is different - the callback name is
constructed from object name ( let assume that $obj’s name is
’Obj’) and the event name. ( This is one of the reasons why
Component::profile_check_in() performs automatic naming of newly
created onbjects). Note also that context objects are $self ( that
equals $owner ) and $obj.
The delegated methods can be used not only for the owner-child
relations. Every Prima object is free to add a delegation method to
every other object. However, if the objects are in other than
owner-child relation, it is a good practice to add Destroy
notification to the object which events are of interest, so if it
gets destroyed, the partner object gets a message about that.
Anonymous subroutines
The two previous callback types are more relevant when a separate
class is developed, but it is not necessary to declare a new class
every time the event handling is needed. It is possible to use the
third and the most powerful event hook method using perl anonymous
subroutines ( subs ) for the easy customization.
Contrary to the usual OO event implementations, when only one
routine per class dispatches an event, and calls inherited handlers
when it is appropriate, Prima event handling mechanism can accept
many event handlers for one object ( it is greatly facilitated by
the fact that perl has anonymous subs, however).
All the callback routines are called when an event is triggered,
one by one in turn. If the direct and delegated methods can only be
multiplexed by the usual OO inheritance, the anonymous subs are
allowed to be multiple by the design. There are three syntaxes for
setting such a event hook; the example below sets a hook on $obj
using each syntax for a different situation:
- during create():
$obj = Class-> create(
...
onPostMessage => sub {
my ( $self, $data1, $data2) = @_;
},
...
);
- after create using set()
$obj-> set( onPostMessage => sub {
my ( $self, $data1, $data2) = @_;
});
- after create using event name:
$obj-> onPostMessage( sub {
my ( $self, $data1, $data2) = @_;
});
As was noted in Prima, the events can be addressed as properties,
with the exception that they are not substitutive but additive.
The additivity is that when the latter type of syntax is used, the
subs already registered do not get overwritten or discarded but
stack in queue. Thus,
$obj-> onPostMessage( sub { print "1" });
$obj-> onPostMessage( sub { print "2" });
$obj-> notify( "PostMessage", 0, 0);
code block would print
21
as the execution result.
This, it is a distinctive feature of a toolkit is that two objects
of same class may have different set of event handlers.
Flow
When there is more than one handler of a particular event type present
on an object, a question is risen about what are callbacks call
priorities and when does the event processing stop. One of ways to
regulate the event flow is based on prototyping events, by using
notification_types() event type description. This function returns a
hash, where keys are the event names and the values are the constants
that describe the event flow. The constant can be a bitwise OR
combination of several basic flow constants, that control the three
aspects of the event flow.
Order
If both anonymous subs and direct/delegated methods are present, it
must be decided which callback class must be called first. Both
’orders’ are useful: for example, if it is designed that a class’s
default action is to be overridden, it is better to call the custom
actions first. If, on the contrary, the class action is primary,
and the others are supplementary, the reverse order is preferred.
One of two "nt::PrivateFirst" and "nt::CustomFirst" constants
defines the order.
Direction
Almost the same as order, but for finer granulation of event flow,
the direction constants "nt::FluxNormal" and "nt::FluxReverse" are
used. The ’normal flux’ defines FIFO ( first in first out )
direction. That means, that the sooner the callback is registered,
the greater priority it would possess during the execution. The
code block shown above
$obj-> onPostMessage( sub { print "1" });
$obj-> onPostMessage( sub { print "2" });
$obj-> notify( "PostMessage", 0, 0);
results in 21, not 12 because PostMessage event type is prototyped
"nt::FluxReverse".
Execution control
It was stated above that the events are additive, - the callback
storage is never discarded when ’set’-syntax is used. However,
the event can be told to behave like a substitutive property, e.g.
to call one and only one callback. This functionality is governed
by "nt::Single" bit in execution control constant set, which
consists of the following constants:
nt::Single
nt::Multiple
nt::Event
These constants are mutually exclusive, and may not appear together
in an event type declaration. A "nt::Single"-prototyped
notification calls only the first ( or the last - depending on
order and direction bits ) callback. The usage of this constant is
somewhat limited.
In contrary of "nt::Single", the "nt::Multiple" constant sets the
execution control to call all the available callbacks, with respect
to direction and order bits.
The third constant, "nt::Event", is the impact as "nt::Multiple",
except that the event flow can be stopped at any time by calling
clear_event() method.
Although there are 12 possible event type combinations, a half of them
are not viable. Another half were assigned to unique more-less
intelligible names:
nt::Default ( PrivateFirst | Multiple | FluxReverse)
nt::Property ( PrivateFirst | Single | FluxNormal )
nt::Request ( PrivateFirst | Event | FluxNormal )
nt::Notification ( CustomFirst | Multiple | FluxReverse )
nt::Action ( CustomFirst | Single | FluxReverse )
nt::Command ( CustomFirst | Event | FluxReverse )
Success state
Events do not return values, although the event generator, the notify()
method does - it returns either 1 or 0, which is the value of event
success state. The 0 and 1 results in general do not mean either
success or failure, they simply reflect the fact whether clear_event()
method was called during the processing - 1 if it was not, 0 otherwise.
The state is kept during the whole processing stage, and can be
accessed from Component::eventFlag property. Since it is allowed to
call notify() inside event callbacks, the object maintains a stack for
those states. Component::eventFlags always works with the topmost one,
and fails if is called from outside the event processing stage.
Actually, clear_event() is an alias for ::eventFlag(0) call. The state
stack is operated by push_event() and pop_event() methods.
Implementation note: a call of clear_event() inside a
"nt::Event"-prototyped event call does not automatically stops the
execution. The execution stops if the state value equals to 0 after the
callback is finished. A ::eventFlag(1) call thus cancels the effect of
clear_event().
A particular coding style is used when the event is
"nt::Single"-prototyped and is called many times in a row, so overheads
of calling notify() become a burden. Although notify() logic is
somewhat complicated, it is rather simple with "nt::Single" case. The
helper function get_notify_sub() returns the context of callback to-be-
called, so it can be used to emulate notify() behavior. Example:
for ( ... ) {
$result = $obj-> notify( "Measure", @parms);
}
can be expressed in more cumbersome, but efficient code if
"nt::Single"-prototyped event is used:
my ( $notifier, @notifyParms) = $obj-> get_notify_sub( "Measure" );
$obj-> push_event;
for ( ... ) {
$notifier-> ( @notifyParms, @parms);
# $result = $obj-> eventFlag; # this is optional
}
$result = $obj-> pop_event;
API
Prima::Object methods
alive
Returns the object ’vitality’ state - true if the object is alive
and usable, false otherwise. This method can be used as a general
checkout if the scalar passed is a Prima object, and if it is
usable. The true return value can be 1 for normal and operational
object state, and 2 if the object is alive but in its init() stage.
Example:
print $obj-> name if Prima::Object::alive( $obj);
can NAME, CACHE = 1
Checks if an object namespace contains a NAME method. Returns the
code reference to it, if found, and undef if not. If CACHE is
true, caches the result to speed-up subsequent calls.
cleanup
Called right after destroy() started. Used to initiate "cmDestroy"
event. Is never called directly.
create CLASS, %PARAMETERS
Creates a new object instance of a given CLASS and sets its
properties corresponding to the passed parameter hash. Examples:
$obj = Class-> create( PARAMETERS);
$obj = Prima::Object::create( "class" , PARAMETERS);
Is never called in an object context.
Alias: new()
destroy
Initiates the object destruction. Perform in turn cleanup() and
done() calls. destroy() can be called several times and is the
only Prima re-entrant function, therefore may not be overloaded.
done
Called by destroy() after cleanup() is finished. Used to free the
object resources, as a finalization stage. During done() no events
are allowed to circulate, and alive() returns 0. The object is not
usable after done() finishes. Is never called directly.
Note: the eventual child objects are destroyed inside done() call.
get @PARAMETERS
Returns hash where keys are @PARAMETERS and values are the
corresponding object properties.
init %PARAMETERS
The most important stage of object creation process. %PARAMETERS
is the modified hash that was passed to create(). The modification
consists of merging with the result of profile_default() class
method inside profile_check_in() method. init() is responsible for
applying the relevant data into PARAMETERS to the object
properties. Is never called directly.
insert CLASS, %PARAMETERS
A convenience wrapper for create(), that explicitly sets the owner
property for a newly created object.
$obj = $owner-> insert( 'Class', name => 'name');
is adequate to
$obj = Class-> create( owner => $owner, name => 'name);
code. insert() has another syntax that allows simultaneous creation
of several objects:
@objects = $owner-> insert(
[ 'Class', %parameters],
[ 'Class', %parameters],
...
);
With such syntax, all newly created objects would have $owner set
to their ’owner’ properties.
new CLASS, %PARAMETERS
Same as create.
profile_add PROFILE
The first stage of object creation process. PROFILE is a reference
to a PARAMETERS hash, passed to create(). It is merged with
profile_default() after passing both to profile_check_in(). The
merge result is stored back in PROFILE. Is never called directly.
profile_check_in CUSTOM_PROFILE, DEFAULT_PROFILE
The second stage of object creation process. Resolves eventual
ambiguities in CUSTOM_PROFILE, which is the reference to PARAMETERS
passed to create(), by comparing to and using default values from
DEFAULT_PROFILE, which is the result of profile_default() method.
Is never called directly.
profile_default
Returns hash of the appropriate default values for all properties
of a class. In object creation process serves as a provider of
fall-back values, and is called implicitly. This method can be used
directly, contrary to the other creation process-related functions.
Can be called in a context of class.
raise_ro TEXT
Throws an exception with text TEXT when a read-only property is
called in a set- context.
raise_wo TEXT
Throws an exception with text TEXT when a write-only property is
called in a get- context.
set %PARAMETERS
The default behavior is an equivalent to
sub set
{
my $obj = shift;
my %PARAMETERS = @_;
$obj-> $_( $PARAMETERS{$_}) for keys %PARAMETERS;
}
code. Assigns object properties correspondingly to PARAMETERS hash.
Many Prima::Component descendants overload set() to make it more
efficient for particular parameter key patterns.
As the code above, raises an exception if the key in PARAMETERS has
no correspondent object property.
setup
The last stage of object creation process. Called after init()
finishes. Used to initiate "cmCreate" event. Is never called
directly.
Prima::Component methods
add_notification NAME, SUB, REFERER = undef, INDEX = -1
Adds SUB to the list of notification of event NAME. REFERER is the
object reference, which is used to create a context to SUB and is
passed as a parameter to it when called. If REFERER is undef ( or
not specified ), the same object is assumed. REFERER also gets
implicitly attached to the object, - the implementation frees the
link between objects when one of these gets destroyed.
INDEX is a desired insert position in the notification list. By
default it is -1, what means ’in the start’. If the notification
type contains nt::FluxNormal bit set, the newly inserted SUB will
be called first. If it has nt::FluxReverse, it is called last,
correspondingly.
Returns positive integer value on success, 0 on failure. This
value can be later used to refer to the SUB in
remove_notification().
See also: "remove_notification", "get_notification".
attach OBJECT
Inserts OBJECT to the attached objects list and increases OBJECT’s
reference count. The list can not hold more than one reference to
the same object. The warning is issued on such an attempt.
See also: "detach".
bring NAME
Looks for a immediate child object that has name equals to NAME.
Returns its reference on success, undef otherwise. It is a
convenience method, that makes possible the usage of the following
constructs:
$obj-> name( "Obj");
$obj-> owner( $owner);
...
$owner-> Obj-> destroy;
can_event
Returns true if the object event circulation is allowed. In
general, the same as "alive() == 1", except that can_event() fails
if an invalid object reference is passed.
clear_event
Clears the event state, that is set to 1 when the event processing
begins. Signals the event execution stop for nt::Event-prototyped
events.
See also: "Events", "push_event", "pop_event", "::eventFlag",
"notify".
detach OBJECT, KILL
Removes OBJECT from the attached objects list and decreases
OBJECT’s reference count. If KILL is true, destroys OBJECT.
See also: "attach"
event_error
Issues a system-dependent warning sound signal.
event_hook [ SUB ]
Installs a SUB to receive all events on all Prima objects. SUB
receives same parameters passed to notify, and must return an
integer, either 1 or 0, to pass or block the event respectively.
If no SUB is set, returns currently installed event hook pointer.
If SUB is set, replaces the old hook sub with SUB. If SUB is
'undef', event filtering is not used.
Since the 'event_hook' mechanism allows only one hook routine to be
installed at a time, direct usage of the method is discouraged.
Instead, use Prima::EventHook for multiplexing of the hook access.
The method is static, and can be called either with or without
class or object as a first parameter.
get_components
Returns array of the child objects.
See: "create", "Links between objects".
get_handle
Returns a system-dependent handle for the object. For example,
Prima::Widget return its system WINDOW/HWND handles,
Prima::DeviceBitmap - its system PIXMAP/HBITMAP handles, etc.
Can be used to pass the handle value outside the program, for an
eventual interprocess communication scheme.
get_notification NAME, @INDEX_LIST
For each index in INDEX_LIST return three scalars, bound at the
index position in the NAME event notification list. These three
scalars are REFERER, SUB and ID. REFERER and SUB are those passed
to "add_notification", and ID is its result.
See also: "remove_notification", "add_notification".
get_notify_sub NAME
A convenience method for nt::Single-prototyped events. Returns
code reference and context for the first notification sub for event
NAME.
See "Success state" for example.
notification_types
Returns a hash, where the keys are the event names and the values
are the "nt::" constants that describe the event flow.
Can be called in a context of class.
See "Events" and "Flow" for details.
notify NAME, @PARAMETERS
Calls the subroutines bound to the event NAME with parameters
@PARAMETERS in context of the object. The calling order is
described by "nt::" constants, contained in the
notification_types() result hash.
notify() accepts variable number of parameters, and while it is
possible, it is not recommended to call notify() with the exceeding
number of parameters; the call with the deficient number of
parameters results in an exception.
Example:
$obj-> notify( "PostMessage", 0, 1);
See "Events" and "Flow" for details.
pop_event
Closes event processing stage brackets.
See "push_event", "Events"
post_message SCALAR1, SCALAR2
Calls "PostMessage" event with parameters SCALAR1 and SCALAR2 once
during idle event loop. Returns immediately. Does not guarantee
that "PostMessage" will be called, however.
See also "post" in Prima::Utils
push_event
Opens event processing stage brackets.
See "pop_event", "Events"
remove_notification ID
Removes a notification subroutine that was registered before with
"add_notification", where ID was its result. After successful
removal, the eventual context object gets implicitly detached from
the storage object.
See also: "add_notification", "get_notification".
set_notification NAME, SUB
Adds SUB to the event NAME notification list. Almost never used
directly, but is a key point in enabling the following notification
add syntax
$obj-> onPostMessage( sub { ... });
or
$obj-> set( onPostMessage => sub { ... });
that are shortcuts for
$obj-> add_notification( "PostMessage", sub { ... });
unlink_notifier REFERER
Removes all notification subs from all event lists bound to REFERER
object.
Prima::Component properties
eventFlag STATE
Provides access to the last event processing state in the object
event state stack.
See also: "Success state", "clear_event", "Events".
delegations [ <REFERER>, NAME, <NAME>, < <REFERER>, NAME, ... > ]
Accepts an anonymous array in set- context, which consists of a
list of event NAMEs, that a REFERER object ( the caller object by
default ) is interested in. Registers notification entries for
routines if subs with naming scheme REFERER_NAME are present on
REFERER name space. The example code
$obj-> name("Obj");
$obj-> delegations([ $owner, 'PostMessage']);
registers Obj_PostMessage callback if it is present in $owner
namespace.
In get- context returns an array reference that reflects the
object’s delegated events list content.
See also: "Delegated methods".
name NAME
Maintains object name. NAME can be an arbitrary string, however it
is recommended against usage of special characters and spaces in
NAME, to facilitate the indirect object access coding style:
$obj-> name( "Obj");
$obj-> owner( $owner);
...
$owner-> Obj-> destroy;
and to prevent system-dependent issues. If the system provides
capabilities that allow to predefine some object parameters by its
name ( or class), then it is impossible to know beforehand the
system naming restrictions. For example, in X window system the
following resource string would make all Prima toolkit buttons
green:
Prima*Button*backColor: green
In this case, using special characters such as ":" or "*" in the
name of an object would make the X resource unusable.
owner OBJECT
Selects an owner of the object, which may be any Prima::Component
descendant. Setting an owner to a object does not alter its
reference count. Some classes allow OBJECT to be undef, while some
do not. All widget objects can not exist without a valid owner;
Prima::Application on the contrary can only exist with owner set to
undef. Prima::Image objects are indifferent to the value of the
owner property.
Changing owner dynamically is allowed, but it is a main source of
implementation bugs, since the whole hierarchy tree is needed to be
recreated. Although this effect is not visible in perl, the
results are deeply system-dependent, and the code that changes
owner property should be thoroughly tested.
Changes to "owner" result in up to three notifications:
"ChangeOwner", which is called to the object itself, "ChildLeave",
which notifies the previous owner that the object is about to
leave, and "ChildEnter", telling the new owner about the new child.
Prima::Component events
ChangeOwner OLD_OWNER
Called at runtime when the object changes its owner.
ChildEnter CHILD
Triggered when a child object is attached, either as a new instance
or as a result of runtime owner change.
ChildLeave CHILD
Triggered when a child object is detached, either because it is
getting destroyed or as a result of runtime owner change.
Create
The first event an event sees. Called automatically after init() is
finished. Is never called directly.
Destroy
The last event an event sees. Called automatically before done() is
started. Is never called directly.
PostMessage SCALAR1, SCALAR2
Called after post_message() call is issued, not inside
post_message() but at the next idle event loop. SCALAR1 and
SCALAR2 are the data passed to post_message().
AUTHOR
Dmitry Karasik, <dmitry@karasik.eu.org>.
SEE ALSO
Prima, Prima::internals, Prima::EventHook.