/usr/local/CPAN/Devel-ebug-Wx/Devel/ebug/Wx/View/Breakpoints.pm
package Devel::ebug::Wx::View::Breakpoints;
use strict;
use base qw(Wx::ScrolledWindow Devel::ebug::Wx::View::Base);
use Devel::ebug::Wx::Plugin qw(:plugin);
__PACKAGE__->mk_accessors( qw(panes sizer) );
use Wx qw(:sizer);
sub tag { 'breakpoints' }
sub description { 'Breakpoints' }
sub new : View {
my( $class, $parent, $wxebug, $layout_state ) = @_;
my $self = $class->SUPER::new( $parent, -1 );
$self->wxebug( $wxebug );
$self->panes( [] );
$self->subscribe_ebug( 'break_point', sub { $self->_add_bp( @_ ) } );
$self->subscribe_ebug( 'break_point_delete', sub { $self->_del_bp( @_ ) } );
$self->subscribe_ebug( 'load_program_state', sub { $self->load_all_breakpoints } );
$self->set_layout_state( $layout_state ) if $layout_state;
$self->register_view;
my $sizer = Wx::BoxSizer->new( wxVERTICAL );
$self->SetSizer( $sizer );
$self->sizer( $sizer );
$self->load_all_breakpoints if $wxebug->ebug->is_running;
$self->SetSize( $self->default_size );
return $self;
}
sub load_all_breakpoints {
my( $self ) = @_;
my $wxebug = $self->wxebug;
foreach my $pane ( @{$self->panes} ) {
$self->sizer->Detach( $pane );
$pane->Destroy;
}
$self->{panes} = [];
$self->_add_bp( $wxebug->ebug, undef,
file => $_->{filename},
line => $_->{line},
condition => $_->{condition},
) foreach $wxebug->ebug->all_break_points_with_condition;
}
sub _compare {
my( $x, $y ) = @_;
my $fc = $x->{file} cmp $y->{file};
return $fc if $fc != 0;
return $x->{line} <=> $y->{line};
}
sub _add_bp {
my( $self, $ebug, $event, %params ) = @_;
my( $index, $order );
for( $index = 0; $index < @{$self->panes}; ++$index ) {
$order = _compare( \%params, $self->panes->[$index] );
return if $order == 0;
last if $order < 0;
}
my $pane = Devel::ebug::Wx::Breakpoints::Pane->new( $self, \%params );
splice @{$self->panes}, $index, 0, $pane;
$self->sizer->Insert( $index, $pane, 0, wxGROW );
$self->SetScrollRate( 0, $pane->GetSize->y );
# force relayout and reset virtual size
$self->Layout;
$self->SetSize( $self->GetSize );
}
sub _del_bp {
my( $self, $ebug, $event, %params ) = @_;
my $index;
for( $index = 0; $index < @{$self->panes}; ++$index ) {
last if _compare( \%params, $self->panes->[$index] ) == 0;
}
my $pane = $self->panes->[$index];
splice @{$self->panes}, $index, 1;
$self->sizer->Detach( $pane );
$pane->Destroy;
# force relayout and reset virtual size
$self->Layout;
$self->SetSize( $self->GetSize );
}
sub delete {
my( $self, $pane ) = @_;
$self->ebug->break_point_delete( $pane->file, $pane->line );
}
sub go_to {
my( $self, $pane ) = @_;
$self->wxebug->code_display_service
->highlight_line( $pane->file, $pane->line );
}
sub set_condition {
my( $self, $pane, $condition ) = @_;
$self->ebug->ebug->break_point( $pane->file, $pane->line, $condition );
}
package Devel::ebug::Wx::Breakpoints::Pane;
use strict;
use base qw(Wx::Panel Class::Accessor::Fast);
__PACKAGE__->mk_ro_accessors( qw(controls file line) );
use File::Basename qw(basename);
use Wx qw(:sizer);
use Wx::Event qw(EVT_BUTTON EVT_TEXT);
sub new {
my( $class, $parent, $args ) = @_;
my $self = $class->SUPER::new( $parent );
my $bp_label = Wx::StaticText->new( $self, -1, '' );
my $goto = Wx::Button->new( $self, -1, 'Go to' );
my $delete = Wx::Button->new( $self, -1, 'Delete' );
my $cnd_label = Wx::StaticText->new( $self, -1, 'Cond:' );
my $condition = Wx::TextCtrl->new( $self, -1, '' );
$self->{controls} = { label => $bp_label,
condition => $condition,
};
$self->{file} = $args->{file};
$self->{line} = $args->{line};
$self->display_bp( $args );
my $topsz = Wx::BoxSizer->new( wxVERTICAL );
my $fsz = Wx::BoxSizer->new( wxHORIZONTAL );
my $ssz = Wx::BoxSizer->new( wxHORIZONTAL );
$fsz->Add( $bp_label, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 2 );
$fsz->Add( $delete, 0, 0 );
$fsz->Add( $goto, 0, wxRIGHT, 2 );
$ssz->Add( $cnd_label, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 2 );
$ssz->Add( $condition, 1, wxRIGHT, 2 );
$topsz->Add( $fsz, 0, wxGROW );
$topsz->Add( $ssz, 0, wxGROW );
$self->SetSizerAndFit( $topsz );
EVT_BUTTON( $self, $goto, sub { $self->GetParent->go_to( $self ) } );
EVT_BUTTON( $self, $delete, sub { $self->GetParent->delete( $self ) } );
EVT_TEXT( $self, $condition, sub { $self->GetParent->set_condition( $self, $condition->GetValue ) } );
return $self;
}
sub display_bp {
my( $self, $args ) = @_;
my $text = basename( $args->{file} ) . ': ' . $args->{line};
my $cond = $args->{condition} || '';
$self->controls->{label}->SetLabel( $text );
$self->controls->{condition}->SetValue( $cond eq '1' ? '' : $cond );
}
1;