#======================================================== # GraphFrameArray #======================================================== package GraphFrameArray; use MyTk::TkCommon; @ISA = qw(TkCommon); use strict; use MyTk::GraphFrame; #============================================================ # 変数等取得関数 #============================================================ sub App { return shift->mw()->App(); } sub Application { return shift->mw()->App(); } sub MainMenu { return shift->mw()->MainMenu(); } sub mw { return shift->{'MainWindow'}; } sub MainWindow { return shift->{'MainWindow'}; } #sub Canvas { return shift->{'Canvas'}; } sub Canvas { my ($this, $canvas) = @_; if($canvas) { return $canvas; } return $this->mw()->Canvas(); } #sub SetCanvas #{ # my ($this, $canvas) = @_; # my $pGraphFrameArray = $this->GetpGraphFrameArray(); # for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { # my $frame = $pGraphFrameArray->[$i]; # $frame->SetCanvas($canvas); # } #} sub nGraphFrame { my $gfa=shift->{'GraphFrameArray'}; return @$gfa; } sub GetpGraphFrameArray { return shift->{'GraphFrameArray'}; } #sub GetGraphFrameArray { my $array = shift->{'GraphFrameArray'}; return @$array; } sub GetGraphFrame { my ($this, $idx) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); return $pGraphFrameArray->[$idx]; } sub Index { return 0; } sub ShowMousePosition { return shift->{'ShowMousePosition'}; } sub SetShowMousePosition { my ($this,$f)=@_; return $this->{'ShowMousePosition'} = $f; } #============================================================ # コンストラクタ、デストラクタ #============================================================ sub new { my ($module, $mw, $canvas) = @_; my $this = {}; bless $this; $canvas = $mw->Canvas($canvas); # $this->{'Canvas'} = $canvas; $this->{'MainWindow'} = $mw; my @array; $this->{'GraphFrameArray'} = \@array; $this->SetShowMousePosition(0); my $App = $mw->App(); if($App) { my $f = $App->{'ShowMousePosition'}; $this->SetShowMousePosition($f) if($f); } $mw->bind($canvas, '', [ \&ShowPopupMenu, $this, Tk::Ev('X'), Tk::Ev('Y') ]); $mw->bind($canvas, '', [ \&SelTags, $this, 'Others-LButtonDown', Tk::Ev('x'), Tk::Ev('y') ]); $mw->bind($canvas, '', [ \&SelTags, $this, 'Others-LBUttonUp', Tk::Ev('x'), Tk::Ev('y'), Tk::Ev('X'), Tk::Ev('Y') ]); $mw->bind($canvas, '', [ \&SelTags, $this, 'Others-Move', Tk::Ev('x'), Tk::Ev('y') ]); $mw->bind($canvas, '', [ \&SelTags, $this, 'Others-LButtonDouble', Tk::Ev('x'), Tk::Ev('y') ]); $mw->bind($canvas, '', sub { $this->SetCanvasSize(); } ); return $this; } sub DESTROY { my $this = shift; # $this->SUPER::DESTROY(@_); } #============================================================ # 一般関数 #============================================================ sub IterateForGraphFrames { my ($this, $pSubroutine, @args) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->$pSubroutine(@args); } } sub FindGraphFrameByPosition { my ($this, $x0, $y0) = @_; return undef unless(defined $y0); my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $this->GetGraphFrame($i); next unless($frame); return $i if($frame->IsPointInFrame($x0, $y0)); } return undef; } sub SaveCSVFile { my ($this, $filepath, $LimitToViewYRange) = @_; #print "Array: $LimitToViewYRange\n"; my $App = $this->App(); print "\nSave to CSV file.\n"; $filepath =~ s/\.$//; $filepath = "$filepath.csv" unless($filepath =~ /\.csv$/i); Jcode::convert(\$filepath, $App->FileSystemCharCode()) if($App and $App->FileSystemCharCode()); my $pGraphFrameArray = $this->{GraphFrameArray}; my $nGraphFrame = $this->nGraphFrame(); print "nGraphFrame: $nGraphFrame\n"; return undef if($nGraphFrame == 0); if($nGraphFrame == 1) { if($pGraphFrameArray->[0]->SaveCSVFile($filepath, $LimitToViewYRange)) { print "GraphFrame0 was saved to [$filepath]\n"; return 1; } else { print "Error: Can not save to [$filepath]\n"; return undef; } } my $ErrorExist = 0; for(my $i = 0 ; $i < $nGraphFrame ; $i++) { my $i1 = $i+1; my $pGraphFrame = $pGraphFrameArray->[$i]; if($pGraphFrame->nDataArray() == 0) { print " GraphFrame$i does not have data. Skipped.\n"; next; } my ($drive, $directory, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($filepath); $ext = ".$ext" unless($ext =~ /^\./); my $path = Deps::MakePath("$drive$directory", "$filebody-$i1$ext"); if($pGraphFrame->SaveCSVFile($path, $LimitToViewYRange)) { print " GraphFrame$i was saved to [$path]\n"; } else { print " Error: Can not save to [$path]\n"; $ErrorExist = 1; } } return undef if($ErrorExist); return 1; } sub AddGraphFrame { my ($this, $GraphFrame) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); my $idx = @$pGraphFrameArray; my $canvas = $this->Canvas(); unless($GraphFrame) { $GraphFrame = new GraphFrame($this->mw(), $idx); # $GraphFrame = new GraphFrame($this->mw(), $this->Canvas(), $idx); } push(@$pGraphFrameArray, $GraphFrame); $canvas->bind("Frame$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "Frame-LButtonDown" ] ); $canvas->bind("Frame$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "Frame-LButtonDClick" ] ); $canvas->bind("XScale$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "XScale-LButtonDown" ] ); $canvas->bind("XScale$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "XScale-LButtonDClick" ] ); $canvas->bind("YScale$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "YScale-LButtonDown" ] ); $canvas->bind("YScale$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "YScale-LButtonDClick" ] ); $canvas->bind("XCaption$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "XCaption-LButtonDown" ] ); $canvas->bind("XCaption$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "XCaption-LButtonDClick" ] ); $canvas->bind("YCaption$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "YCaption-LButtonDown" ] ); $canvas->bind("YCaption$idx", '', [ \&SelTags, $this->GetGraphFrame($idx), "YCaption-LButtonDClick" ] ); } sub SetShowScaleDialogCallback { my ($this, $func) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->{'ShowScaleDialogFunc'} = $func; } } sub SelTags { my ($canvas, $this, $command, $x, $y, $X, $Y) = @_; my $idx = $this->Index(); #print "command: $command idx: $idx\n"; if($command =~ /Others-LButtonDown/i) { if($canvas->{'PrevSelTime'} and $canvas->{'PrevSelTime'} < time() ) { $canvas->delete("SelectedBox"); } } if($command =~ /XScale/i) { if($command =~ /down/i) { my ($x0,$y0,$x1,$y1) = split(/,/, $canvas->{"XScale${idx}Rect"}); #print "xscale: $x0, $y0, $x1, $y1\n"; $canvas->delete("SelectedBox"); $canvas->DrawBox($x0, $y0, $x1, $y1, 1, "", "red", "SelectedBox"); } else { my $func = $this->{'ShowScaleDialogFunc'}; if($func) { &$func($this, $command, "X Scale"); } else { $this->ShowScaleDialog("X Scale"); } $canvas->{'PrevDialogTime'} = time(); } } elsif($command =~ /YScale/i) { if($command =~ /down/i) { my ($x0,$y0,$x1,$y1) = split(/,/, $canvas->{"YScale${idx}Rect"}); $canvas->delete("SelectedBox"); $canvas->DrawBox($x0, $y0, $x1, $y1, 1, "", "red", "SelectedBox"); } else { my $func = $this->{'ShowScaleDialogFunc'}; if($func) { &$func($this, $command, "Y Scale"); } else { $this->ShowScaleDialog("Y Scale"); } $canvas->{'PrevDialogTime'} = time(); } } elsif($command =~ /XCaption/i) { if($command =~ /down/i) { my ($x0,$y0,$x1,$y1) = split(/,/, $canvas->{"XCaption${idx}Rect"}); $canvas->delete("SelectedBox"); $canvas->DrawBox($x0, $y0, $x1, $y1, 1, "", "red", "SelectedBox"); } else { my $text = Dialog::InputDialog($this->mw(), "X Caption", $this->{'XCaption'}, 50, 1); if($text) { chomp($text); $this->{'XCaption'} = $text; $this->mw()->Redraw(); } $canvas->{'PrevDialogTime'} = time(); } } elsif($command =~ /YCaption/i) { if($command =~ /down/i) { my ($x0,$y0,$x1,$y1) = split(/,/, $canvas->{"YCaption${idx}Rect"}); $canvas->delete("SelectedBox"); $canvas->DrawBox($x0, $y0, $x1, $y1, 1, "", "red", "SelectedBox"); } else { my $text = Dialog::InputDialog($this->mw(), "Y Caption", $this->{'YCaption'}, 50, 1); if($text) { chomp($text); $this->{'YCaption'} = $text; $this->mw()->Redraw(); } $canvas->{'PrevDialogTime'} = time(); } } elsif($command =~ /frame/i) { if($command =~ /down/i) { $canvas->delete("SelectedBox"); $canvas->DrawBox($this->{'x0'}, $this->{'y0'}, $this->{'x1'}, $this->{'y1'}, 1, '', 'red', 'SelectedBox'); } else { $this->ShowGraphFrameDialog("Graph Frame"); $canvas->{'PrevDialogTime'} = time(); } } else { #$command =~ /others/i if($command =~ /LButtonDown/i) { if($canvas->{'PrevSelTime'} and $canvas->{'PrevSelTime'} < time()) { $canvas->delete("SelectedBox"); } if($canvas->{'PrevDialogTime'} and time()-$canvas->{'PrevDialogTime'} <= 1) { undef $this->{'PrevX'}; undef $this->{'PrevY'}; } else { $canvas->delete("SelRangeBox"); $this->{'PrevX'} = $x; $this->{'PrevY'} = $y; } } elsif($command =~ /Move/i) { #print "move:", $this->ShowMousePosition(), "\n"; if($this->ShowMousePosition()) { my $s = ""; $s = $s . "P:($x, $y)"; for(my $idx = 0 ; ; $idx++) { my $frame = $this->GetGraphFrame($idx); last unless($frame); my ($vx0, $vy0) = $frame->PositionToValue($x, $y); next unless($vx0); $vx0 = Utils::Round($vx0, 6, 1); $vy0 = Utils::Round($vy0, 6, 1); $s = $s . " F$idx:($vx0, $vy0)"; } $this->mw()->WriteStatusBar($s); } if($this->{'PrevX'}) { $canvas->delete("SelRangeBox"); $canvas->DrawBox($this->{'PrevX'}, $this->{'PrevY'}, $x, $y, 1, '', 'red', 'SelRangeBox'); } } elsif($command =~ /LButtonUp/i) { $this->SelRangeBoxMenu($this->{'PrevX'}, $this->{'PrevY'}, $x, $y, $X, $Y, $command); undef $this->{'PrevX'}; undef $this->{'PrevY'}; $canvas->delete("SelRangeBox"); } } #以外の場合は、前の赤枠を削除するための現在時間を記録する $canvas->{'PrevSelTime'} = time() unless($command =~ /move/i); } sub ExpandViewRange { my ($this, $cx0, $cy0, $cx1, $cy1, $command) = @_; my $idx = $this->FindGraphFrameByPosition($cx0, $cy0); return unless(defined $idx); ($cx0, $cx1) = Utils::Sort($cx0, $cx1); ($cy0, $cy1) = Utils::Sort($cy0, $cy1); return if($cx1 - $cx0 < 3); return if($cy1 - $cy0 < 3); my $frame = $this->GetGraphFrame($idx); return unless($frame); #print "frame $idx: $frame\n"; my ($x0, $y0, $x1, $y1) = $frame->GetPosition(); my ($vx0, $vy0, $vx1, $vy1) = $frame->GetViewRange(); my ($nx0, $ny1) = $frame->PositionToValue($cx0, $cy0); my ($nx1, $ny0) = $frame->PositionToValue($cx1, $cy1); ($nx0, $nx1) = Utils::Sort($nx0, $nx1); ($ny0, $ny1) = Utils::Sort($ny0, $ny1); #print "nx: $nx0, $ny0, $nx1, $ny1\n"; if($command eq "ShowDialog") { ($nx0, $ny0, $nx1, $ny1) = $frame->ShowScaleDialog( "Change View Range for Frame $idx", $nx0, $ny0, $nx1, $ny1); return undef unless(defined $nx0); #print "nx: $nx0, $ny0, $nx1, $ny1\n"; return 1; } #print "nx: $nx0, $ny0, $nx1, $ny1\n"; $frame->SetViewRange($nx0, $ny0, $nx1, $ny1, 1); #print "nx: $nx0, $ny0, $nx1, $ny1\n"; $this->mw()->Redraw(); return 1; } sub SelRangeBoxMenu($$$$$) { my ($this, $x0, $y0, $x1, $y1, $X, $Y, $command) = @_; #print "x: $x0, $y0, $x1, $y1\n"; return unless(defined $y0); return if(defined $x1 and $x0 == $x1); return if(defined $y1 and $y0 == $y1); my $cb = 'ON'; my $menu = $this->mw()->Menu(-tearoff => 'no'); $menu->add('command', -label => "Expand", -underline => 0, -command => [ \&ExpandViewRange, $this, $x0, $y0, $x1, $y1, "Expand" ] ); $menu->add('command', -label => "Show Expand Dialog", -underline => 12, -command => [ \&ExpandViewRange, $this, $x0, $y0, $x1, $y1, "ShowDialog" ] ); $menu->add('command', -label => "Redraw", -underline => 0, -command => sub { $this->mw()->Redraw(); } ); $menu->add('separator'); $menu->add('command', -label => "Close", -underline => 0, -command => sub { $this->mw()->Close(1); } ); # $menu->add('separator'); # $menu->add('command', # -label => "Command", # -command => sub { print "Command: $command\n"; } ); # $menu->add('checkbutton', # -label => 'Checkbutton', # -variable => \$cb, # -onvalue => 'ON', # -offvalue => 'OFF' ); $menu->Post($X, $Y); } sub ShowPopupMenu($$) { my ($canvas, $this, $X, $Y) = @_; my $menu = $this->MainMenu(); unless(defined $menu) { $menu = $this->mw()->Menu(-tearoff => 'no'); $menu->add('command', -label => "Redraw", -underline => 0, -command => sub { $this->mw()->Redraw(); } ); $menu->add('separator'); $menu->add('command', -label => "Close", -underline => 0, -command => sub { $this->mw()->Close(1); } ); } $menu->Post($X, $Y) if($menu); } sub Draw { my ($this, $canvas) = @_; $canvas = $this->Canvas() unless($canvas); my $rect = new Rect; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; #my ($x0,$y0,$x1,$y1)=$frame->GetViewRange(); #print "xy: $x0,$y0,$x1,$y1\n"; $rect->Merge($frame->Draw($canvas)); } return $rect; } sub SetFont { my ($this, $font) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->SetFont($font); } } sub SetPositionByStr { my ($this, $str) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->SetPositionByStr($str); } } sub SetCanvasSize { my ($this, $width, $height) = @_; if(not defined $width) { my $canvas = $this->Canvas(); return unless($canvas); $width = $canvas->width(); $height = $canvas->height(); } my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->SetCanvasSize($width, $height); } } sub SetXCaption { my ($this, $caption) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->SetXCaption($caption); } } sub SetYCaption { my ($this, $caption) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->SetYCaption($caption); } } sub SetViewXRange { my ($this, $x0, $x1, $DoSynchronize) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->SetViewXRange($x0, $x1, $DoSynchronize); } } sub SetViewYRange { my ($this, $y0, $y1, $DoSynchronize) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->SetViewYRange($y0, $y1, $DoSynchronize); } } sub SetViewRange { my ($this, $x0, $y0, $x1, $y1, $DoSynchronize) = @_; $this->SetViewXRange($x0, $x1, $DoSynchronize); $this->SetViewYRange($y0, $y1, $DoSynchronize); } sub SetSmoothLine { my ($this, $f) = @_; $this->IterateForGraphFrames("SetSmoothLine", $f); } sub SetX0LineVisible { my ($this, $f) = @_; $this->IterateForGraphFrames("SetX0LineVisible", $f); } sub SetY0LineVisible { my ($this, $f) = @_; $this->IterateForGraphFrames("SetY0LineVisible", $f); } sub SetScaleStringVisible { my ($this, $XYStr, $f) = @_; $this->IterateForGraphFrames("SetScaleStringVisible", $XYStr, $f); # my $pGraphFrameArray = $this->GetpGraphFrameArray(); # for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { # my $frame = $pGraphFrameArray->[$i]; # $frame->SetScaleStringVisible($XYStr, $f); # } } sub SetScaleVisible { my ($this, $XYStr, $f) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->SetScaleVisible($XYStr, $f); } } sub AdjustViewRange { my ($this, $marginx0, $marginx1, $marginy0, $marginy1) = @_; my $pGraphFrameArray = $this->GetpGraphFrameArray(); for(my $i = 0 ; $i < @$pGraphFrameArray ; $i++) { my $frame = $pGraphFrameArray->[$i]; $frame->AdjustViewRange($marginx0, $marginx1, $marginy0, $marginy1); } } 1;