package Lire::UI::CompoundWidget;
use strict;
use base qw/ Curses::UI::Container Lire::UI::Widget /;
use Carp;
use Curses;
use Curses::UI::Common;
use Locale::TextDomain 'lire';
use Lire::Utils qw/ check_object_param max/;
use vars qw/ @CARP_NOT %bindings %routines /;
@CARP_NOT = qw/ Curses::UI::Container /;
%bindings = ( KEY_PPAGE() => 'pageup',
KEY_NPAGE() => 'pagedown' );
%routines = ( 'pageup' => \&help_pageup,
'pagedown' => \&help_pagedown );
sub new {
my $class = shift;
my %userargs = @_;
keys_to_lowercase(\%userargs);
check_object_param( $userargs{'value'}, 'value',
'Lire::Config::Dictionary' );
my $self = $class->Curses::UI::Container::new( %userargs,
'-bindings' => \%bindings,
'-routines' => \%routines );
if ( $self->shown_components() ) {
$self->_setup_value_widgets();
$self->_setup_help_viewer();
} else {
$self->_setup_empty_label();
}
$self->layout();
return $self;
}
sub _setup_empty_label {
my $self = $_[0];
$self->add('empty_label', 'Label',
'-text'=>__('-- This option does not have any attributes --'));
return;
}
sub _setup_value_widgets {
my $self = $_[0];
foreach my $comp ( $self->shown_components() ) {
my $name = $comp->name();
$self->add( "${name}_label", 'Label',
'-text' => $name, '-bold' => 1,
'-textalignment' => 'right' );
$self->add( "${name}_widget", 'Lire::UI::Widget',
'value' => $self->{'value'}->get( $name ),
'-onfocus' => \&_child_focus_cb,
'onvaluechanged' => sub { $self->run_event( 'onvaluechanged' ) },
);
}
return;
}
sub shown_components {
my $self = $_[0];
grep { ! $_->obsolete() } $self->{'value'}->spec()->components();
}
# FIXME: this is hackish
sub _help_onfocus_cb {
my $help = $_[0];
my $self = $help->parent();
if ( $help->{'_tag'} ) {
$self->focus_next();
$help->{'_tag'} = 0;
} else {
$self->parent()->focus_next();
$help->{'_tag'} = 1;
}
return;
}
sub _setup_help_viewer {
my $self = $_[0];
return unless $self->shown_components();
$self->add( 'help_summary', 'Label', '-bold' => 1 );
my $viewer = $self->add( 'help_viewer', 'TextViewer',
'-wrapping' => 1, '-vscrollbar' => 1,
'_tag' => 0 );
$viewer->onFocus( \&_help_onfocus_cb );
return;
}
sub help_viewer_width {
return int( ($_[0]->canvaswidth() - 2) * 0.4 );
}
sub layout_value_widgets {
my $self = $_[0];
$self->{'_label_width'} = $self->_max_label_size();
$self->{'_widget_width'} = ( $self->canvaswidth() - $self->{'_label_width'}
- $self->help_viewer_width() - 2 );
my $y = 0;
my $left = $self->shown_components();
if ( $left * 2 - 1> $self->canvasheight() ) {
$Curses::UI::screen_too_small++;
return;
}
foreach my $comp ( $self->shown_components() ) {
my $label = $self->getobj( $comp->name() . '_label' );
$label->{'-x'} = 0;
$label->{'-y'} = $y;
$label->{'-width'} = $self->{'_label_width'};
my $widget = $self->getobj( $comp->name() . "_widget" );
$widget->{'-x'} = $self->{'_label_width'} + 1;
$widget->{'-y'} = $y;
$widget->{'-width'} = $self->{'_widget_width'};
$widget->{'-height'} =
int( ($self->canvasheight() - $y - ($left - 1)) / $left );
$widget->layout();
$y += $widget->{'-height'} + 1;
$left--;
}
return;
}
sub layout_help_viewer {
my $self = $_[0];
my $help_width = $self->help_viewer_width();
my $x = $self->{'_label_width'} + $self->{'_widget_width'} + 2;
my $summary = $self->getobj( 'help_summary' );
$summary->{'-x'} = $x;
$summary->{'-y'} = 0;
$summary->{'-width'} = $help_width;
my $viewer = $self->getobj( 'help_viewer' );
$viewer->{'-x'} = $x;
$viewer->{'-y'} = 2;
$viewer->{'-width'} = $help_width;
return;
}
sub layout_contained_objects {
my $self = $_[0];
return $self unless $self->getobj( 'help_viewer' );
$self->layout_value_widgets();
$self->layout_help_viewer();
return $self->SUPER::layout_contained_objects();
}
sub refresh_view {
my $self = $_[0];
foreach my $comp ( $self->shown_components() ) {
my $name = $comp->name();
die "$name: $self" unless $self->isa( 'Lire::UI::CompoundWidget' );
$self->getobj( "${name}_widget" )->refresh_view();
}
return;
}
sub _max_label_size {
my $self = $_[0];
my $avail = int( ( $self->canvaswidth()-2 ) * 0.25 );
my @labels = map { $_->name() } $self->shown_components();
my $max = max( map { length $_ } @labels );
return ( $max < $avail ? $max : $avail );
}
# Routines
sub help_pageup {
my $self = $_[0];
my $help_viewer = $self->getobj( 'help_viewer' );
$help_viewer->cursor_pageup();
$help_viewer->draw();
return;
}
sub help_pagedown {
my $self = $_[0];
my $help_viewer = $self->getobj( 'help_viewer' );
$help_viewer->cursor_pagedown();
$help_viewer->draw();
return;
}
# callbacks
sub _child_focus_cb {
my $widget = $_[0];
my $self = $widget->parent();
my $value = $widget->{'value'};
$self->getobj( 'help_summary' )->text( $value->summary() );
my $help_viewer = $self->getobj( 'help_viewer' );
$help_viewer->cursor_up( undef, $help_viewer->{'-yscrpos'} )
if ( $help_viewer->{'-yscrpos'} > 1 );
$help_viewer->text( $value->text_description()
|| __( 'No help available.' ) );
return;
}
1;
syntax highlighted by Code2HTML, v. 0.9.1