Devel-WxProf
view release on metacpan or search on metacpan
bin/wxprofile view on Meta::CPAN
}
#die $sizer->GetRows();
$parent->Fit();
$parent->FitInside();
# $navigator_notebook->AddPage($parent, 'List View');
EVT_GRID_SELECT_CELL($pkg_grid, sub { $self->on_package_select(@_) } );
EVT_GRID_SELECT_CELL($sub_grid, sub { $self->on_sub_select(@_) } );
EVT_GRID_SELECT_CELL($call_grid, sub {
$self->populate_callee_map(@_);
$self->populate_callee_tree(@_);
} );
$main_sizer->Add($parent, 1, wxEXPAND);
}
EVT_CLOSE( $self, \&on_close );
EVT_MENU( $self, wxID_ABOUT, \&on_about );
EVT_MENU( $self, wxID_EXIT, sub { $self->Close } );
EVT_MENU( $self, wxID_OPEN, \&on_open );
$main->Fit();
$main->FitInside();
$self->SetIcon( Wx::GetWxPerlIcon() );
$self->Show;
# Wx::LogMessage( "Welcome to wxProfile!" );
return $self;
}
sub setup_grid {
my ($self,$grid, $height, @cols) = @_;
# wxFont(int pointSize, wxFontFamily family, int style, wxFontWeight weight, const bool underline = false, const wxString& faceName = "", wxFontEncoding encoding = wxFONTENCODING_DEFAULT)
my $font = Wx::Font->new(8);
my $sizer = Wx::FlexGridSizer->new(0, scalar @cols, $#cols);
$grid->SetSizer($sizer);
$grid->CreateGrid(0, scalar @cols, -1);
$grid->SetDefaultCellFont($font);
$grid->SetLabelFont($font);
$grid->SetRowLabelSize(32);
$grid->EnableEditing(0);
$grid->SetSelectionMode(1); # wxGridSelectRow
for (0..$#cols) {
$grid->SetColLabelValue($_, $cols[$_]);
}
$grid->SetMinSize([500,$height]);
$grid->SetMaxSize([500,$height]);
$grid->Fit();
$grid->FitInside();
}
sub populate_pkg_grid {
my ($self, $data) = @_;
my $busy = Wx::BusyCursor->new();
my $grid = $self->pkg_grid();
my $data_from_ref = [ sort { $b->get_elapsed <=> $a->get_elapsed } values %{ $data } ];
# die Data::Dumper::Dumper $data_from_ref;
$grid->data($data_from_ref);
$grid->AppendRows(scalar @{ $data_from_ref });
for (my $i = 0; $i<scalar @{ $data_from_ref }; $i++ ) {
$grid->SetCellValue($i, 0, $data_from_ref->[$i]->get_elapsed() );
$grid->SetCellValue($i, 1, $data_from_ref->[$i]->get_calls() );
$grid->SetCellValue($i, 2, $data_from_ref->[$i]->get_package() );
}
$grid->Fit();
$grid->FitInside();
}
sub on_package_select {
my ($self, $package_grid, $event) = @_;
my $grid = $self->sub_grid();
my $pkg = $package_grid->data()->[$event->GetRow()];
$self->populate_sub_grid($pkg);
}
sub populate_sub_grid {
my ($self, $pkg) = @_;
if (not defined $pkg) {
warn "no pkg - called from " , join " ", caller();
return;
}
my $grid = $self->sub_grid();
my @row_data = sort { $b->get_elapsed() <=> $a->get_elapsed() } values %{ $pkg->get_function };
$grid->data( \@row_data );
$grid->ClearGrid();
my $rows = $grid->GetNumberRows();
if ($rows > scalar @row_data) {
$grid->DeleteRows(scalar @row_data, $rows - scalar @row_data);
}
elsif ($rows < scalar @row_data) {
$grid->AppendRows(scalar @row_data - $rows);
}
for (my $i = 0; $i<scalar @row_data; $i++ ) {
# use Data::Dumper; die Dumper $sub_from_ref->[$i]->get_calls;
$grid->SetCellValue($i, 0, $row_data[$i]->get_elapsed() );
$grid->SetCellValue($i, 1, $row_data[$i]->get_calls() );
$grid->SetCellValue($i, 2, $row_data[$i]->get_function() );
}
$grid->Fit();
$grid->FitInside();
$grid->Layout();
$grid->SelectRow(0);
}
sub select_package {
my ($self, $package) = @_;
my $grid = $self->pkg_grid();
for my $row(0..$grid->GetNumberRows()) {
if ($package eq $grid->GetCellValue($row,2)) {
$grid->SelectRow($row);
$grid->MakeCellVisible($row,0);
return $grid->data()->[ $row ];
}
}
return;
}
sub select_sub {
my ($self, $package) = @_;
my $grid = $self->sub_grid();
for my $row(0..$grid->GetNumberRows()) {
if ($package eq $grid->GetCellValue($row,2)) {
$grid->SelectRow($row);
$grid->MakeCellVisible($row,0);
return $grid->data()->[ $row ];
}
}
return;
}
sub on_sub_select {
my ($self, $sub_grid, $event) = @_;
my $pkg = $sub_grid->data()->[ $event->GetRow() ];
$self->populate_call_grid($pkg);
}
sub populate_call_grid {
my ($self, $pkg) = @_;
my $busy = Wx::BusyCursor->new();
my @row_data = @{ $pkg->get_child_nodes() };
my $grid = $self->call_grid();
$grid->data( \@row_data );
$grid->ClearGrid();
my $rows = $grid->GetNumberRows();
if ($rows > scalar @row_data) {
$grid->DeleteRows(scalar @row_data, $rows - scalar @row_data);
}
elsif ($rows < scalar @row_data) {
$grid->AppendRows(scalar @row_data - $rows);
}
for (my $i = 0; $i<scalar @row_data; $i++ ) {
# use Data::Dumper; die Dumper $sub_from_ref->[$i]->get_calls;
$grid->SetCellValue($i, 0, $row_data[$i]->get_elapsed() );
$grid->SetCellValue($i, 1, $row_data[$i]->get_calls() );
$grid->SetCellValue($i, 2, $row_data[$i]->get_function() );
}
$grid->Fit();
$grid->FitInside();
$grid->Layout();
$grid->SelectRow(0);
}
sub populate_callee_tree {
my ($self, $call_grid, $event) = @_;
my $busy = Wx::BusyCursor->new();
my $data = $call_grid->data()->[ $event->GetRow() ];
my $child_nodes = $data->get_child_nodes();
my $callee_tree = $self->callee_tree();
$callee_tree->Clear();
$callee_tree->AppendText($data->get_function() . ": " . $data->get_elapsed() . "\n");
$callee_tree->AppendText(join q{}, $self->generate_text_tree({
data => $child_nodes,
max_depth => 10,
}));
}
sub populate_callee_map {
my ($self, $call_grid, $event) = @_;
my $busy = Wx::BusyCursor->new();
my $data = $call_grid->data()->[ $event->GetRow() ];
my $callee_map = $self->callee_map();
my $file_id = ${ $data };
my $dir = $self->preferences()->get_data_dir() . "/$$";
mkdir $dir;
my $filename = "$dir/$file_id.png";
my $preferences = $self->preferences();
if (! -r $filename) {
my $imager = Devel::WxProf::Treemap::Output::Imager->new( WIDTH=>500, HEIGHT=>400,
FONT_FILE => join ( '/', $preferences->get_font_dir(), $preferences->get_map_font_file() ),
# '/usr/share/fonts/truetype/freefont/FreeSans.ttf',
MIN_FONT_SIZE => $self->preferences()->get_map_font_size(),
MAX_FONT_SIZE => $self->preferences()->get_map_font_size(),
);
my $map = Devel::WxProf::Treemap::Squarified->new(
INPUT => $data,
OUTPUT => $imager,
SPACING => { left => 1, top => 1, right => 1, bottom => 1, min_width => 10, min_height => 10 },
PADDING => { left => 1, top => 12, right => 1, bottom => 1 },
);
my @map_from = $map->map();
$self->callee_map_data(\@map_from);
$imager->save($filename);
}
my $file = IO::File->new( $filename, "r" );
unless ($file) {
print "Can't load $filename.";return undef
};
binmode $file;
my $handler = Wx::PNGHandler->new();
my $image = Wx::Image->new();
my $bmp; # used to hold the bitLabelmap.
$handler->LoadFile( $image, $file );
$bmp = Wx::Bitmap->new($image);
if( $bmp->Ok() ) {
# create a static bitmap called ImageViewer that displays the
# selected image.
$callee_map->SetBitmap( $bmp );
# Wx::StaticBitmapWx::StaticBitmap->new($callee_map, -1, $bmp);
my $dc = $self->callee_map_dc() || Wx::MemoryDC->new();
$dc->SelectObject($bmp);
$self->callee_map_dc($dc);
}
}
sub generate_text_tree {
my $self = shift;
my $arg_ref = shift;
my @result = @{ $arg_ref->{ data } };
my $max_depth = $arg_ref->{ max_depth };
my $indent = q{ };
my $depth = 0;
my @text = ();
while (1) {
my $node = shift @result;
if (not defined $node) {
$depth--;
last if not @result;
next;
}
push @text, $indent x $depth, $node->get_elapsed , q{ }, $node->get_package, q{ ::}, $node->get_function(), "\n";
if ($depth < $max_depth) {
my $children_from = $node->get_child_nodes;
if (@{ $children_from }) {
$depth++;
@result = (@{ $children_from }, undef, @result);
}
}
last if not @result;
}
return @text;
}
sub read_profile {
my ($self, $filename) = @_;
my $busy = Wx::BusyCursor->new();
my $data = Devel::WxProf::Data->new({});
my $reader = ($filename =~m{ tmon\.out$ }x)
? Devel::WxProf::Reader::DProf->new()
: Devel::WxProf::Reader::WxProf->new();
my @result = eval {
$reader->read_file($filename)
};
if ($@) {
Wx::LogMessage( "Error: $@");
return;
}
$self->filename($filename);
$self->_set_title($filename);
$data->set_child_nodes(\@result);
$self->populate_pkg_grid($reader->get_packages());
}
sub ask_for_filename {
my ($self, $label) = shift;
$label ||= 'Select file';
my $default_dir = $self->preferences()->get_default_dir();
my $dialog = Wx::FileDialog->new($self, $label, $default_dir);
if ($dialog->ShowModal() == wxID_OK) {
$self->preferences->set_default_dir($dialog->GetDirectory());
return $dialog->GetPath()
}
return;
}
sub on_close {
my( $self, $event ) = @_;
Wx::Log::SetActiveTarget( $self->{old_log} );
$event->Skip;
}
sub on_open {
my( $self, $event ) = @_;
my $filename = $self->ask_for_filename();
if ($filename) {
$self->read_profile($filename);
}
}
sub on_about {
my( $self ) = @_;
use Wx qw(wxOK wxCENTRE wxVERSION_STRING);
Wx::MessageBox( "wxprofile (c) 2008 Martin Kutter\n" .
"wxPerl $Wx::VERSION, " . wxVERSION_STRING,
"About wxprofile", wxOK|wxCENTRE, $self );
}
sub _set_title {
my $self = shift;
$self->SetTitle(shift);
}
( run in 2.250 seconds using v1.01-cache-2.11-cpan-a49fcb8fa48 )