package DotThingy; use strict; use warnings; use Carp; use FindBin qw($Bin); use FileHandle; use Tk; use Tk::ROText; use vars qw($VERSION); use Proc::Background; $VERSION = 0.1; =head1 METHODEN =head2 new( $class ) Konstruktor. ToDo: Was sinnvolles dazu schreiben. =cut sub new { my( $class ) = @_; my $self = bless( {}, $class ); # Initialisierung: # Sicherstellen, dass der temporäre Ordner da ist: # $Bin . /mytemp $self->{__temp_dir} = $Bin . '/mytemp'; croak("Temporärer Ordner nicht gefunden!") unless -e $self->{__temp_dir}; # Temp-Ordner leeren? -> Eventuell Konflikt mit mehreren, # gleichzeitig laufenden Programmen. # GUI zusammen bauen $self->_tkinit(); # Test my $dotcode = qq~ digraph dotsample { graph[ratio = "fill" size = "5.0,5.0" rankdir="LR" splines="true" overlap="false" ]; A -> C [label="big", constraint=false]; A -> B [label="x2", constraint=false]; B -> C [label="x4", constraint=false]; A -> B [label="x1"]; B -> C [label="x3"]; } ~; $self->{gui}->{dotkode}->insert('end', $dotcode); return $self; } # /new =head2 _tkinit() Baut die Grafische Oberfläche zusammen. Speichert alle Widgets in $self->{gui}. Diehe Designdokumente -> Layout für gewünschtes Aussehen. =cut sub _tkinit { my $self = shift; # Kontainer für alle Widgets (mindestens für die, auf die ich später # zugreifen möchte. $self->{gui} = {}; $self->{gui}->{mw} = Tk::MainWindow->new(); # 3 große Bereiche $self->{gui}->{dotKodeFrame} = $self->{gui}->{mw}->Frame(-bg => 'yellow',)->pack(); $self->{gui}->{vorschauFrame} = $self->{gui}->{mw}->Frame(-bg => 'blue',)->pack(); $self->{gui}->{dotLog} = $self->{gui}->{mw}->Frame(-bg => 'red',)->pack(); # DotKode-Widget $self->{gui}->{dotkode} = $self->{gui}->{dotKodeFrame}->Scrolled( 'Text', -height => 20, -wrap => 'none', -scrollbars => 'se', )->pack(-fill => 'x',); # Button zum Erstellen des Layouts $self->{gui}->{dotKodeFrame}->Button( -text => 'do layout', -command => sub{ $self->doLayout(), }, )->pack(); # Vorschau-Widget $self->{gui}->{vorschau} = $self->{gui}->{vorschauFrame}->Scrolled( 'Label', -text => 'bla', )->pack(); $self->{gui}->{vorschau_export} = $self->{gui}->{vorschauFrame}->Button( -text => 'Exportiere', )->pack(); # Log # DotKode-Widget $self->{gui}->{dotLog}->Scrolled( 'ROText', -height => 5, -scrollbars => 'se', )->pack(-fill => 'x',); } # /_tkinit =head2 run() Startet das Programm = startet die GUI. =cut sub run { my $self = shift; $self->{gui}->{mw}->MainLoop(); } # /run =head2 doLayout() Erstellt eine temporäre Datei im temp-Ordner, die dann an Dot übergeben wird, von dot in diesen temporären Ordner als PNG exportiert wird und dann ausgelesen und in der "Vorschau" angeziegt wird. Setzt voraus, dass dot in PATH steht. =cut sub doLayout { my $self = shift; my $temp_dir = $self->{__temp_dir}; my $ofile = $temp_dir . '/temp.png'; my $ifile = $temp_dir . '/temp.txt'; my $dotcode = $self->{gui}->{dotkode}->get('0.0','end'); my $fh = FileHandle->new("> $ifile"); if (defined $fh) { print $fh $dotcode; $fh->close(); }else{ # Meldung in Box, return $self->msg("Konnte temporäre Datei nicht erstellen: $!"); return; } my $command = qq~dot -o$ofile -Tpng $ifile~; print "$command\n"; system($command) == 0 or croak "system $command failed: $?"; #my $proc1 = Proc::Background->new($command); #if ($? == -1) { # print "failed to execute: $!\n"; #} #elsif ($? & 127) { # printf "child died with signal %d, %s coredump\n", # ($? & 127), ($? & 128) ? 'with' : 'without'; #} #else { # printf "child exited with value %d\n", $? >> 8; #} # Prüfen, ob die Datei angelegt wurde. return; } # /doLayout =head2 msg( $msg ) Fügt eine Meldung in das Log-Fenster ein. Hängt nach Bedarf noch ein Newline an die Meldung an. =cut sub msg { my $self = shift; my $msg = shift; $msg .= "\n" unless $msg =~ m/\n$/; $self->{gui}->{dotLog}->insert($msg); } # /msg 1; # /DotThingy use strict; use warnings; my $app = DotThingy->new(); $app->run();