Mail-Thread-Arc

 view release on metacpan or  search on metacpan

lib/Mail/Thread/Arc.pm  view on Meta::CPAN

=cut

sub render {
    my $self = shift;
    my $root = shift;

    # extract just the containers with messages
    my @messages;
    $root->iterate_down(
        sub {
            my $container = shift;
            push @messages, $container if $container->message;
        } );

    # sort on date
    @messages = sort {
        $self->date_of( $a ) <=> $self->date_of( $b )
    } @messages;

    $self->messages( \@messages );

    $self->width( ( @messages + 1 ) * $self->message_radius * 3 );
    $self->height( $self->maximum_arc_height * 2 + $self->message_radius * 6 );
    $self->svg( SVG->new( width => $self->width, height => $self->height, onload => "init(evt)" ) );

    {
        # assign the numbers needed to compute X
        my $i;
        $self->message_offsets( { map { $_ => ++$i } @messages } );
    }
    $self->svg->script->CDATA( $self->javascript_chunk );

    $self->draw_arc( $_->parent, $_ ) for @messages;
    $self->draw_message( $_ ) for @messages;

    return $self->svg;
}


=head2 draw_message( $message )

Draw the message on the SVG canvas.

=cut

sub draw_message {
    my ($self, $message) = @_;

    my $i = $self->message_offsets->{$message} - 1;

    my $link = $self->make_link($message);
    my $root = $self->svg;
    $root = $root->anchor( -href=> $link ) if defined $link;

    my $group = $root->group(
        id          => "road$i",
        onmouseover => "set_group_color( $i, 'blue' )",
        $self->message_style( $message ),
       );

    $group->title->cdata( $message->header('from') );
    $group->desc->cdata( "Date: " . $message->header('date') );

    $group->circle(
        cx => $self->message_x( $message ),
        cy => $self->message_y,
        r  => $self->message_radius,
       );
    
}


=head2 make_link( $message )

Return an URI based on the message. By default returns 
undef meaning that that the message is not a link.

However if this module is subclassed then a meaningful
URI can be returned where appropriate.

=cut

sub make_link {
    my ($self, $message) = @_;
    return;
}


=head2 draw_arc( $from, $to )

draws an arc between two messages

=cut

sub draw_arc {
    my ($self, $from, $to) = @_;

    return unless $from;

    my $distance = $self->message_x( $to ) - $self->message_x( $from );
    my $radius = $distance/ 2;

    my $top = $self->thread_generation( $to ) % 2;
    my $x = $self->message_x( $from );
    my $y = $self->message_y + ( $top ? -$self->message_radius : $self->message_radius);

    my %offsets = %{ $self->message_offsets };

    my $path;
    if ($radius > $self->maximum_arc_height) { # uh oh - trickyness
        my $max = $self->maximum_arc_height;
        # to Y - the relative part of the first curve
        my $toy = $top ? -$max : $max;
        my $toy2 = -$toy;
        my $x2 = $self->message_x( $to ) - $max;
        my $y2 = $y + $toy;

        $path = join(' ',
                     "M $x,$y",                        #start the path
                     "a$max,$max 0 0,$top $max,$toy",  # arc up
                     "L $x2,$y2",                      # line across
                     "a$max,$max 0 0,$top $max,$toy2", # arc down



( run in 2.438 seconds using v1.01-cache-2.11-cpan-df04353d9ac )