#!perl
# compare dot-generated images with graphs drawn by Tk::GraphViz

use strict;
use warnings;
use File::Temp qw(tempfile);
use Tk;
use Tk::Pane;
use Tk::GraphViz;

# Get files from the command line, if supplied

my @dots = @ARGV ? @ARGV : glob "t/graphs/directed/*";
my $async = 1;

my $mw = MainWindow->new();

# Frame for the two images
my $topFrame = $mw->Frame->pack(-side => 'top', -fill => 'both', -expand => 1);

# left image, including a label
my $imageLabel = makeScrolledWidget(
  $topFrame, 'left', "Dot-Generated GIF Image", 'packAdjust',
  Pane => -sticky => 'nsew',
)->Label->pack(-fill => 'both', -expand => 1);

# right image, including a label
# Right picture is a Tk::GraphViz object
my $gv = makeScrolledWidget(
  $topFrame, 'left', 'Tk::GraphViz-Generated Canvas', 'pack',
  GraphViz => -background => 'white',
)->createBindings;

my $buttonFrame = $mw->Frame->pack(-side => 'bottom');
my $statusLabel = $mw->Label->pack(-side => 'bottom');
my $nextButton = cmdButton($buttonFrame, Next => 0, [\&showDots], qw(left -state disabled));
cmdButton($buttonFrame, 'Find node' => 0, [\&findNode, $gv], 'left');
cmdButton($buttonFrame, 'Zoom in' => 0, [$gv, qw(zoom -in 1.5)], 'left');
cmdButton($buttonFrame, 'Zoom out X' => 9, [$gv, qw(zoom -out 1.5)], 'left');
cmdButton($buttonFrame, Quit => 0, [$mw, 'destroy'], 'right');

$mw->geometry("800x400");
showDots();

MainLoop;

sub findNode {
  my ($mw, $gv) = @_;
  $gv->scrollTo(simpleDialog($mw, 'Node Name Dialog'));
}

sub simpleDialog {
  my ($mw, $title) = @_;
  require Tk::DialogBox;
  require Tk::Entry;
  my $dialog = $mw->DialogBox(-title => $title, -default_button => 'OK', -buttons => [qw/OK Cancel/]);
  my $entry = $dialog->add('Entry')->pack;
  $dialog->configure(-focus => $entry);
  my $ans = $dialog->Show;
  my $text = $entry->get;
  $dialog->destroy;
  $ans ne 'OK' ? undef : $text;
}

sub cmdButton {
  my ($frame, $label, $underline_index, $cmd, $pack, @but_args) = @_;
  my $key = lc substr $label, $underline_index, 1;
  my $mw = $frame->MainWindow;
  $mw->bind("<Key-$key>" => $cmd);
  my @button_cmd = @$cmd;
  splice @button_cmd, 1, 0, $mw if ref($cmd->[0]) eq 'CODE';
  $frame->Button(-command => \@button_cmd, -text => $label, -underline => $underline_index, @but_args)->pack(-side => $pack);
}

sub makeScrolledWidget {
  my ($top, $side, $label, $pack, @scrolled) = @_;
  my $frame = $top->Frame(-relief => 'sunken')
    ->$pack(-fill => 'both', -expand => 1, -side => $side);
  $frame->Label(-text => $label)->pack(-side => 'top');
  $frame->Scrolled(@scrolled, -scrollbars => 'osoe')
    ->pack(-fill => 'both', -expand => 1,  -side => 'top');
}

sub showDots {
  return if !@dots;
  my $currentFile = shift @dots;
  $statusLabel->configure(-text => "Generating GIF for $currentFile ...");
  $mw->Busy;
  $mw->update;
  $imageLabel->configure(-image => GenerateImage($imageLabel, $currentFile));
  $statusLabel->configure(-text => "Generating Tk::GraphViz Canvas for $currentFile ...");
  $mw->update;
  $gv->show($currentFile, async => $async);
  $statusLabel->configure(-text => $currentFile);
  $mw->Unbusy;
  $nextButton->configure(-state => @dots ? 'normal' : 'disabled');
}

##############################################
# Sub to generate gif file from dot file
sub GenerateImage {
  my ($frame, $filename) = @_;
  die "Can't find file '$filename'\n" unless -f $filename;
  print "Processing file $filename\n";
  my (undef, $tempfile) = tempfile('XXXX', TMPDIR => 1, UNLINK => 1);
  my @command = (qw(dot -Tgif), $filename, qq{-o$tempfile});
  system @command and die "Error executing @command\n".$!;
  my $image = $frame->Photo(-file => $tempfile);
  return $image;
}
