/usr/local/CPAN/PPresenter/PPresenter/Style.pm
# Copyright (C) 2000-2002, Free Software Foundation FSF.
package PPresenter::Style;
use strict;
use PPresenter::StyleElem;
use base 'PPresenter::StyleElem';
my @style_elements = qw(template fontset dynamic decoration formatter);
sub objtype($;) {ucfirst $_[0]}
use constant ObjDefaults =>
{ type => 'style'
, -templates => [ 'PPresenter::Template::Default' ]
, -fontsets => [ 'PPresenter::Fontset::TkFonts'
, 'PPresenter::Fontset::XScaling' ]
, -dynamics => [ 'PPresenter::Dynamic::Default' ]
, -formatters => [ 'PPresenter::Formatter::Plain'
, 'PPresenter::Formatter::Simple'
, 'PPresenter::Formatter::Markup' ]
, -decorations => [ 'PPresenter::Decoration::Solid'
, 'PPresenter::Decoration::Lines1' ]
};
sub InitObject()
{ my $style = shift;
print PPresenter::TRACE "Creating style $style.\n";
$style->SUPER::InitObject;
# Get all the modules.
foreach (@style_elements)
{ my $type = objtype($_);
my $list = "-${_}s";
my $show = $style->{show};
no strict 'refs';
my @loaded
= map {PPresenter::StyleElem::load($_, style=>$style, show=>$show)}
@{$style->{$list}};
$style->{$list} = \@loaded;
}
# Select all firsts as starting defaults.
# In the initiation of derived classes, you can select other defaults.
map {$style->select($_, 'FIRST')} @style_elements;
print PPresenter::TRACE "Initialized style $style.\n";
}
#
# About style-elements, in general.
# Only the four functions below may be called from other modules: all
# other may change in later versions of this package.
#
sub find($;$)
{ my ($style, $type, $name) = @_;
$name = 'SELECTED' unless defined $name;
unless(grep {$type eq $_} @style_elements)
{ warn "Cannot find unknown style-type $type for style $style.\n";
return undef;
}
return $style->{selected}{$type}
if $name eq 'SELECTED';
return PPresenter::Template->fromList($style->{-templates}, $name)
if $type eq 'template';
return PPresenter::Fontset->fromList($style->{-fontsets}, $name)
if $type eq 'fontset';
return PPresenter::Dynamic->fromList($style->{-dynamics}, $name)
if $type eq 'dynamic';
return PPresenter::Decoration->fromList($style->{-decorations}, $name)
if $type eq 'decoration';
return PPresenter::Formatter->fromList($style->{-formatters}, $name)
if $type eq 'formatter';
die "Unknown style-element $type.\n"
}
sub add($$)
{ my ($style, $type, $element) = @_;
return $style->{show}->addStyle($element)
if $type eq 'style';
unless(grep {$type eq $_} @style_elements)
{ warn "Cannot add unknown style-type $type to style $style.\n";
return $style;
}
my $list = "-${type}s";
my $objtype = objtype($type);
unless($element->isa("PPresenter::$objtype"))
{ warn "Cannot add $element as a $objtype in style $style.\n";
return $style;
}
unshift @{$style->{$list}}, $element;
print PPresenter::TRACE "Added $type $element.\n";
return $style;
}
# The change-function on a style is a bit different, because it can be
# used to change its style-elements too, not only the overal style settings.
sub change($$@)
{ my ($style, $type, $element) = (shift,shift,shift);
return $style unless defined $type;
unless(grep {$type eq $_} @style_elements)
{ # Change style's options itself, hence not $type=>$elem
return $style->SUPER::change($type,$element,@_);
}
if($element eq 'ALL')
{ map {$_->change(@_)} @{$style->{"-${type}s"}};
return $style;
}
# When a scalar is presented, that must be the name of an existing
# element.
if(ref $element eq '')
{ $style->find($type, $element)->change(@_);
return $style;
}
$element->change(@_);
$style;
}
sub select($$)
{ my ($style, $type, $name) = @_;
unless(grep {$type eq $_} @style_elements)
{ warn "Cannot select unknown style-type $type to style $style.\n";
return;
}
my $found = $style->find($type, $name);
unless(defined $found)
{ warn "Could not find $type $name in style $style.\n";
return 0
}
$style->{selected}{$type} = $found;
return $found;
}
# When a new slide is produced, the selected style-elements are copied
# to it and merged with the slide specified data.
sub get_slide_pref($$;)
{ my ($style, $slide, $type) = @_;
my $selected = $style->find($type, 'SELECTED');
if(defined $slide->{"-$type"})
{ # User specified non-default style element.
my $elem = $style->find($type, $slide->{"-$type"});
$slide->{$type} = $elem->copy
if defined $elem;
warn <<WARN unless defined $elem;
Cannot find $type "$slide->{"-$type"}", so try to continue by falling
back on the default $type, being "$selected".
WARN
# user's spec not needed anymore.
delete $slide->{"-$type"};
}
# Copy defs of selected slide when user didn't specify one.
$slide->{$type} = $selected->copy
unless defined $slide->{$type};
return $style;
}
#
# Collecting style elements.
#
sub styleFlags($)
{ my $options = shift;
my %flags;
foreach (@style_elements, 'style')
{ $flags{$_} = $options->{"-$_"}
if defined $options->{"-$_"};
}
return \%flags;
}
sub styleElems($)
{ my ($style, $slide, $flags) = @_;
my %elems;
foreach (keys %{$style->{selected}})
{ my $elem = exists $flags->{$_}
? $style->find($_ => $flags->{$_})
: $style->{selected}{$_};
die "Slide $slide: Cannot find $_ $flags->{$_}.\n"
unless defined $elem;
$elem->setUsed;
$elems{$_} = $elem;
}
\%elems;
}
sub collectSlidePrefs($)
{ my ($style, $slide) = @_;
# Collect a copy of the selected elements.
map {$style->get_slide_pref($slide, $_)} @style_elements;
# Merge-in user's specifications if they overrule parts of this
# style element.
foreach my $flag (keys %$slide)
{ next unless $flag =~ /^-/; # user options start with dash.
my $flag_used = 0;
foreach (@style_elements)
{ next unless exists $slide->{$_}{$flag};
$slide->{$_}{$flag} = $slide->{$flag};
$flag_used++;
}
warn "Flag $flag is not usable for slide \"$slide\"; removed.\n"
unless $flag_used;
delete $slide->{$flag};
}
return $style;
}
1;