/usr/local/CPAN/PPresenter/PPresenter/Export.pm


# Copyright (C) 2000-2002, Free Software Foundation FSF.

package PPresenter::Export;

use strict;
use PPresenter::Object;
use base 'PPresenter::Object';

use Tk qw(DONT_WAIT ALL_EVENTS DoOneEvent);

use vars qw(@EXPORT @papersizes);
@EXPORT = qw/@papersizes/;

use constant ObjDefaults =>
{ -viewports      => 'ALL'      # NOTES, SLIDES, ALL or name or [ names ]
, -exportSlide    => 'ACTIVE'   # ACTIVE, CURRENT, or ALL
, -includeBorders => 0

, -imageFormat    => 'gif'
, -imageWidth     => 500
, -imageQuality   => 80
, -paperSize      => 'A4'
};

# sizes at 72dpi.
@papersizes =
( [ 'no scaling' => 0,0 ]
, [ 'own size:' => undef, undef ]
, [ Letter => 612,792 ], [ Legal => 612,1008 ], [ Executive => 537,720 ]
, [ A3 => 842,1190 ], [ A4 => 595,842 ], [ A5 => 421,595]
, [ B4 => 709,1002 ], [ B5 => 501,709 ]
);

sub paperSize(;$)
{   my $export = shift;
    my $name   = shift || $export->{-paperSize};
    foreach (@papersizes)
    {   return @$_[1,2] if $_->[0] eq $name;
    }
    die "Unknown paper size $name.\n";
}

sub mapExportedPhases($$)
{   my ($export, $show, $function) = @_;

    my @viewports = $export->selectedViewports;
    my @ret;

    foreach my $slide ($export->selectedSlides($show))
    {   $slide->prepare->show;          # slide must be shown first, otherwise
        $slide->startProgram($show);    # the program-info from callbacks and
                                        # content is not known.
        foreach ($slide->exportedPhases)
        {   $slide->gotoPhase($_);
            push @ret, $function->($export, $show, $slide, \@viewports)
        }
    }

    @ret;
}

sub mapSlideViewports
{   my ($export, $show, $slide, $viewports, $function) = @_;
    my @viewport_order = $show->viewports;
    my @ret;

    # Viewport-map is made in order of definition in show.
    foreach my $vp (@viewport_order)
    {   next unless grep {"$vp" eq $_} @$viewports;
        push @ret, $function->( $export, $show, $slide
                              , $slide->find(view_of_viewport => $vp));
    }

    @ret;
}

my $imgs_read = 0;
my $picture_taken;

sub windowImage($$$$)
{   my ($export, $show, $slide, $view) = @_;
    my $mainwindow = $view->viewport->screen;
    $mainwindow->raise;
    $mainwindow->update;

    if($show->runsOnX)
    {   # Problem: X11 has a-sync screen-updates, so we must give the
        # server some time to update the screen, before taking pictures.
        undef $picture_taken;
        $mainwindow->idletasks;

        $mainwindow->after(1000
        , [ sub {$export->get_x11_image(@_)}, $show, $slide, $view ]
        );
        $mainwindow->waitVariable(\$picture_taken);
        return $picture_taken;
    }

    die "Taking images only supported for X11.\n";
}

sub get_x11_image($$$)
{   my ($export, $show, $slide, $view) = @_;
    my $tmp      = ($ENV{TMPDIR} || '/tmp')."/gpp$$-$imgs_read.xwd";

    my $borders  = $export->{-includeBorders};
    my $viewport = $view->viewport;
    my $display  = $viewport->display;
    my $window   = $borders ? $viewport->screenId : $viewport->canvasId;

    my $cmd   = "xwd >$tmp -display $display -id $window -silent";
    $cmd     .= " -nobdrs" unless $borders;

    system($cmd)==0 or die "Cannot start $cmd.\n";

    my $image = $export->readImage($tmp);
    unlink $tmp;
    $imgs_read++;
    $picture_taken = $image;
}

sub readImage($)             # You shall override this.
{   my ($export, $file) = @_;
    die "You shall implement readImage for file $file";
}

sub polishImage($)           # You may override this.
{   my ($export, $img) = @_;
    $img;
}

sub tkImageSettings($$)
{   my ($export, $show, $parent) = @_;

    my $im = $parent->LabFrame
    ( -label     => 'images'
    , -labelside => 'acrosstop'
    );

    $im->Label
    ( -text     => 'Format'
    , -anchor   => 'e'
    )->grid($im->Entry(-textvariable => \$export->{-imageFormat})
           , -sticky => 'ew');

    $im->Label
    ( -text     => 'Width'
    , -anchor   => 'e'
    )->grid($im->Entry(-textvariable => \$export->{-imageWidth})
           , -sticky => 'ew');

    $im->Label
    ( -text     => 'Quality'
    , -anchor   => 'e'
    )->grid($im->Entry(-textvariable => \$export->{-imageQuality})
           , -sticky => 'ew');

    $im->Checkbutton
    ( -text     => 'Show window borders'
    , -relief   => 'flat'
    , -anchor   => 'w'
    , -variable => \$export->{-includeBorders}
    )->grid(-columnspan => 2, -sticky => 'ew');

    $im;
}

sub tkViewportSettings($$)
{   my ($export, $show, $parent) = @_;
    my @viewports = $show->viewports;

    if(@viewports==1)
    {   $export->{vp}{"$viewports[0]"} = 1;
        return undef;
    }

    my $vp = $parent->LabFrame
    ( -label     => 'viewports'
    , -labelside => 'acrosstop'
    );

    foreach (@viewports)
    {   my ($notes, $name) = ($_->showSlideNotes, "$_");
        $export->{vp}{$name} =
              ref $export->{-viewports} eq 'ARRAY'
            ? grep {$name eq $_} @{$export->{-viewports}}
            : $export->{-viewports} eq 'ALL'    ? 1
            : $export->{-viewports} eq 'SLIDES' ? ! $_->showSlideNotes
            : $export->{-viewports} eq 'NOTES'  ? $_->showSlideNotes
            : $export->{-viewports} eq $name;     # single name specified.

        $vp->Checkbutton
        ( -text     => ($notes ? "$name (notes)" : $name)
        , -relief   => 'flat'
        , -anchor   => 'w'
        , -variable => \$export->{vp}{$name}
        )->grid(-sticky => 'nsew');
    }

    $vp;
}

sub selectedViewports()
{   my $export = shift;
    map {$export->{vp}{$_} ? ("$_") : ()}
        keys %{$export->{vp}};
}

sub tkSlideSelector($)
{   my ($export, $parent) = @_;

    $parent->Optionmenu
    ( -options  => [ 'selected slides', 'current slide', 'all slides' ]
    , -command  => sub { $export->setSelectedSlide(shift) }
    );
}

sub setSelectedSlide($)
{   my ($export, $option) = @_;
    $export->{-exportSlide} = $option eq 'current slide'   ? 'CURRENT'
                            : $option eq 'selected slides' ? 'ACTIVE'
                            : $option eq 'all slides'      ? 'ALL'
      : die "Unknown export option `$option'.\n";
}

sub selectedSlides($)
{   my ($export, $show) = @_;

    my $slides = $export->{-exportSlide};
    return $show->current      if $slides eq 'CURRENT';
    return $show->activeSlides if $slides eq 'ACTIVE';
    return $show->slides       if $slides eq 'ALL';

    die "-exportSlide shall contain CURRENT, ACTIVE, or ALL, not $slides.\n";
}

sub createDirectory($$)
{   my ($export, $parent, $directory) = @_;
    return 1 if -d $directory || mkdir $directory, 0755;

    $parent->Dialog
    ( -title   => 'Export images'
    , -text    =>
      "Directory $directory does not exist, and it can not be created either."
    , -buttons => [ 'Bummer' ]
    , -bitmap  => 'error'
    )->Show('-global');

    return 0;
}

sub optionlist($$@)
{   my ($export, $parent, $flag) = splice @_, 0, 3;

    my $default = $export->{$flag};
    die "Cannot find default $default for flag $flag.\n"
        unless grep {$default eq $_} @_;

    $parent->Optionmenu
    ( -options => [ $default, grep {$_ ne $default} @_ ]
    , -variable => \$export->{$flag}
    );
}

sub popup($$)
{   my ($export, $show, $screen) = @_;
    $export->popup($show, $screen)
           ->Popup(-popover => 'cursor');
}

1;