/usr/local/CPAN/Win32-CtrlGUI/Win32/CtrlGUI/Criteria/multi.pm
###########################################################################
# Copyright 2000, 2001 Toby Everett. All rights reserved.
#
# This file is distributed under the Artistic License. See
# http://www.ActiveState.com/corporate/artistic_license.htm or
# the license that comes with your perl distribution.
#
# For comments, questions, bugs or general interest, feel free to
# contact Toby Everett at teverett@alascom.att.com
##########################################################################
use Win32::CtrlGUI;
use Win32::CtrlGUI::Criteria;
use strict;
package Win32::CtrlGUI::Criteria::multi;
use vars qw($VERSION @ISA);
@ISA = ('Win32::CtrlGUI::Criteria');
$VERSION='0.30';
sub new {
my $class = shift;
$class eq 'Win32::CtrlGUI::Criteria::multi' and die "$class is an abstract parent class.\n";
my $self = {
criteria => [],
criteria_status => [],
};
bless $self, $class;
while (my $i = shift) {
if (ref $i eq 'ARRAY') {
push(@{$self->{criteria}}, Win32::CtrlGUI::Criteria->new(@{$i}));
} elsif (UNIVERSAL::isa($i, 'Win32::CtrlGUI::Criteria')) {
push(@{$self->{criteria}}, $i);
} else {
my $value = shift;
if (grep {$_ eq $i} $self->_options) {
$self->{$i} = $value;
} else {
ref $value eq 'ARRAY' or
die "$class demands ARRAY refs, Win32::CtrlGUI::Criteria objects, or class => [] pairs.\n";
push(@{$self->{criteria}}, Win32::CtrlGUI::Criteria->new($i, $value));
}
}
}
scalar(@{$self->{criteria}}) or die "$class demands at least one sub-criteria.\n";
$self->init;
return $self;
}
#### _options is a class method that returns a list of known "options" that the
#### class accepts - options are considered to be paired with their value.
sub _options {
return qw(timeout);
}
#### init gets called when a multi is initialized (i.e. by new) and when it is
#### reset. It should set the subclass statuses appropriately.
sub init {
my $self = shift;
delete($self->{end_time});
}
sub stringify {
my $self = shift;
(my $subclass = ref($self)) =~ s/^.*:://;
return "$subclass(".join(", ", grep(/\S/, $self->{timeout} ? "timeout => $self->{timeout}" : undef), map {$_->stringify} @{$self->{criteria}}).")";
}
sub tagged_stringify {
my $self = shift;
(my $subclass = ref($self)) =~ s/^.*:://;
my $tag = $self->_is_recognized ? 'active' : 'default';
my(@retval);
push(@retval, ["$subclass(", $tag]);
if ($self->{timeout}) {
my $timeout;
if ($self->{end_time}) {
$timeout = ($self->{end_time}-Win32::GetTickCount())/1000;
$timeout < 0 and $timeout = 0;
$timeout = sprintf("%0.3f", $timeout);
} else {
$timeout = 'wait';
}
push(@retval, ["timeout => $timeout", $tag]);
push(@retval, [", ", $tag]);
}
foreach my $i (0..$#{$self->{criteria}}) {
if (UNIVERSAL::isa($self->{criteria}->[$i], 'Win32::CtrlGUI::Criteria::multi')) {
push(@retval, $self->{criteria}->[$i]->tagged_stringify);
} else {
push(@retval, [$self->{criteria}->[$i]->stringify, $self->{criteria_status}->[$i] ? 'active' : 'default']);
}
push(@retval, [", ", $tag]);
}
$retval[$#retval]->[0] eq ", " and pop(@retval);
push(@retval, [")", $tag]);
return @retval;
}
sub is_recognized {
my $self = shift;
$self->_update_criteria_status;
if ($self->{timeout}) {
my $rcog = $self->_is_recognized;
if (ref $rcog || $rcog) {
if ($self->{end_time}) {
Win32::GetTickCount() >= $self->{end_time} and return $rcog;
} else {
$self->{end_time} = Win32::GetTickCount() + $self->{timeout} * 1000;
}
} else {
delete($self->{end_time});
}
} else {
return $self->_is_recognized;
}
return;
}
#### _is_recognized returns whether the state is actively recognized,
#### independent of the timeout. It should be overriden by the subclasses.
sub _is_recognized {
my $self = shift;
die "Win32::CtrlGUI::Criteria::multi::_is_recognized is an abstract method and needs to be overriden.\n";
}
sub _update_criteria_status {
my $self = shift;
foreach my $i (0..$#{$self->{criteria}}) {
$self->{criteria_status}->[$i] = $self->{criteria}->[$i]->is_recognized;
}
}
sub reset {
my $self = shift;
$self->SUPER::reset;
foreach my $crit (@{$self->{criteria}}) {
$crit->reset;
}
$self->init;
}
1;