###################################################################### ## $Id: Compound.pm 3668 2006-03-11 20:51:13Z spadkins $ ###################################################################### package App::Widget::Compound; $VERSION = (q$Revision: 3668 $ =~ /(\d[\d\.]*)/)[0]; # VERSION numbers generated by svn use App::Widget; @ISA = ( "App::Widget" ); use strict; =head1 NAME App::Widget::Compound - A non-visual compound of other (presumably) visual widgets =head1 SYNOPSIS $conf = { SessionObject => { begin_datetime => { class => "App::Widget::Compound", components => [ "begin_yr", "begin_mon", "begin_day", "begin_hr", "begin_min", "begin_sec", ], parse => "^([0-9]{4})-([0-9][0-9])-([0-9][0-9]) ([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$", format => "%04d-%02d-%02d %02d:%02d:%02d", } end_datetime => { class => "App::Widget::Compound", components => [ "end_yr", "end_mon", "end_day", ], separator => "-", } }, }; =cut ###################################################################### # CONSTANTS ###################################################################### ###################################################################### # ATTRIBUTES ###################################################################### # INPUTS FROM THE ENVIRONMENT =head1 DESCRIPTION This class is a non-visual compound of other (presumably) visual widgets. However, it must be "displayed" so that event-html is created (an tag). The role of a Compound widget is to keep the joined compound value in sync with the split component values. Thus, when the form is submitted an event is fired to join() the component values into the compound value. Processing then occurs, presumably affecting the value of the compound widget directly. When the compound widget is "displayed" with an html() call, its value is split out into the component values. This should happen before the component widgets are displayed or the wrong values will be shown. This may be done by placing the compound widget higher on the page than its components or by making an explicit call to split() in the code. =cut ###################################################################### # CONSTRUCTOR ###################################################################### sub _init { my $self = shift; $self->SUPER::_init(@_); my $name = $self->{name}; my $context = $self->{context}; my $component_widgets = $self->{components}; if ($component_widgets && $#$component_widgets > -1) { foreach my $widget (@$component_widgets) { $context->widget($widget); } } } ###################################################################### # EVENTS ###################################################################### # Usage: $widget->handle_event($name, $event, @args); sub handle_event { my ($self, $name, $event, @args) = @_; if ($event eq "split") { $self->split(@_); return 1; } elsif ($event eq "join") { $self->join(@_); return 1; } elsif ($event eq "change") { # i.e. onChange $self->change(@_); return 1; } else { return $self->SUPER::handle_event(@_); } } sub split { my $self = shift; my $context = $self->{context}; my $name = $self->{name}; my $value = $context->so_get($name); return if (! defined $value || $value eq ""); my (@values); my $parse = $self->{parse}; if ($parse) { @values = ($value =~ /$parse/); } else { my $sep = $self->{separator}; $sep = "," if (!defined $sep); @values = split(/$sep/, $value); } my $component_widgets = $self->{components}; if ($component_widgets && $#$component_widgets > -1) { for (my $i = 0; $i <= $#$component_widgets; $i++) { $context->so_set($component_widgets->[$i], undef, $values[$i]); } } } sub join { my $self = shift; my $context = $self->{context}; my $name = $self->{name}; my (@values, $value); my $component_widgets = $self->{components}; if ($component_widgets && $#$component_widgets > -1) { for (my $i = 0; $i <= $#$component_widgets; $i++) { $values[$i] = $context->so_get($component_widgets->[$i]); } } my $format = $self->{format}; if ($format) { $value = sprintf($format, @values); } else { my $sep = $self->{separator}; $sep = "," if (!defined $sep); $value = join($sep, @values); } $context->so_set($name, undef, $value); } sub change { my $self = shift; $self->join(); } ###################################################################### # OUTPUT METHODS ###################################################################### sub html { my $self = shift; $self->split(); return $self->callback_event_tag("change"); } 1;