#!/usr/bin/perl -w =head1 NAME Quizzer::FrontEnd - base FrontEnd =cut =head1 DESCRIPTION This is the base of the FrontEnd class. Each FrontEnd presents a user interface of some kind to the user, and handles generating and communicating with Elements to form that FrontEnd. =cut =head1 METHODS =cut package Quizzer::FrontEnd; use Quizzer::Level; use Quizzer::Config; use Quizzer::Base; use Quizzer::Log ':all'; use strict; use vars qw(@ISA); @ISA=qw(Quizzer::Base); my $VERSION='0.01'; =head2 new Creates a new FrontEnd object and returns it. =cut sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = bless $proto->SUPER::new(@_), $class; $self->{elements}=[]; $self->{interactive}=''; $self->{capb}=''; $self->{title}=""; return $self } =head2 makeelement This helper function creates an Element. Pass in the type of Frontend the Element is for, and the Question that will be bound to the Element. It returns the generated Element, or false if it was unable to make an Element of the given type. =cut sub makeelement { my $this=shift; my $frontend_type=shift; my $question=shift; my $type=$frontend_type.'::'.ucfirst($question->template->type); debug 2, "Trying to make element of type $type"; my $element=eval qq{ use Quizzer::Element::$type; Quizzer::Element::$type->new; }; debug 2, "Failed with $@" if $@; if (! ref $element) { return; } $element->frontend($this); $element->question($question); return $element; } =head2 add Add a Question to the list to be displayed to the user. Pass the Question and text indicating the level of the Question. This creates an Element and adds it to the array in the elements property. Returns true if the created Element is visible. =cut sub add { my $this=shift; my $question=shift || die "\$question is undefined"; my $level=shift; # Figure out if the question should be displayed to the user or not. my $visible=1; # Noninteractive frontends never show anything. $visible='' if ! $this->interactive; # Don't show items that are unimportant. $visible='' unless Quizzer::Level::high_enough($level); # Set showold to ask even default questions. $visible='' if Quizzer::Config::showold() eq 'false' && $question->flag_isdefault eq 'false'; my $element; if ($visible) { # Create an input Element of the type associated with # this frontend. This requires some nastiness. my ($frontend_type)=ref($this)=~m/Quizzer::FrontEnd::(.*)/; $element=$this->makeelement($frontend_type, $question) || die "Unknown type of element"; # Ask the Element if it thinks it is visible. If not, # fall back below to making a noninteractive element. # # This last check is useful, because for example, select # Elements are not really visible if they have less than two # choices. $visible=$element->visible; } if (! $visible) { # Create a noninteractive element. $element=$this->makeelement('Noninteractive', $question) || return; # no noninteractive element of this type. } push @{$this->{elements}}, $element; return $element->visible; } =head2 go Display accumulated Elements to the user. The Elements are in the elements property, and that property is cleared after the Elements are presented. After showing each element, checks to see if the object's backup property has been set; if so, doen't display any of the other pending questions (remove them from the buffer), and return false. The default is to return true. The return value of each element's show() method is used to set the value of the question associated with that element. =cut sub go { my $this=shift; debug 2, "preparing to ask questions"; foreach my $element (@{$this->elements}) { my $value=$element->show; if ($this->backup) { $this->{elements}=[]; $this->backup(''); return; } $element->question->value($value); # Only set isdefault if the element was visible, because we # don't want to do it when showing noninteractive select # elements and so on. $element->question->flag_isdefault('false') if $element->visible; } $this->clear; return 1; } =head2 clear Clear out the accumulated elements. =cut sub clear { my $this=shift; $this->{elements}=[]; } =head2 default_title This sets the title property to a default. Pass in the name of the package that is being configured. =cut sub default_title { my $this=shift; $this->title(ucfirst(shift)); } =head1 AUTHOR Joey Hess =cut 1