llancet has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone!
I need to make some page object, in which font options needs to be configured. So I made a Role called RolePage, in which has normal attribute textFont and textSize:
package RolePage; use Moose::Role; has textFont => ( is => 'rw', isa => 'Str', default => 'Courier' ); has textSize => ( is => 'rw', isa => 'Int', default => 12 );
In a concrete page class, It may need to contain special font objects for layout calculation:
package CairoPage; use Moose; use Cairo; with 'RolePage'; has cairoFont => ( is => 'bare', isa => 'Cairo::ScaledFont' );
So, when changing on textFont or textSize occurred, such font object should be refreshed. It seems trigger mechanism is a optimum way to do that.
However:
- triggers must be subref in the same package of the attribute;
- triggers cannot be overrided by "+attrName" way;
- triggers cannot be arounded.
So how can I avoid those limitations?

Replies are listed 'Best First'.
Re: Moose: possible way to implement trigger in other packages?
by stvn (Monsignor) on Jul 04, 2010 at 23:54 UTC

    You can do this using required methods in the role and treating them as delegated "events". This is actually a pretty common technique in the Cocoa framework used by Mac OSX and the iPhone OS. Here is how that might look.

    package RolePage; use Moose::Role; has textFont => ( is => 'rw', isa => 'Str', default => 'Courier', trigger => sub { my $self = shift; $self->text_attribute_changed } ); has textSize => ( is => 'rw', isa => 'Int', default => 12, trigger => sub { my $self = shift; $self->text_attribute_changed } ); requires 'text_attribute_changed';
    Then in your class you can do:
    package CairoPage; use Moose; use Cairo; with 'RolePage'; has cairoFont => ( is => 'bare', isa => 'Cairo::ScaledFont', ); sub text_attribute_changed { # ... do whatever you need to here ... }

    -stvn
Re: Moose: possible way to implement trigger in other packages?
by tcurtis (Acolyte) on Jul 06, 2010 at 21:42 UTC

    Another option is to, instead of having the Role "RolePage" with two attributes, have two required methods "textFont" and "textSize". You could then have a PageDefault role that is equivalent to your current RolePage role.

    CairoPage could then compose the role "RolePage" and implement its own textFont and textSize accessors that delegate to the cairoFont attribute.

    Other page classes could just compose PageDefault instead of RolePage.