1 package LaTeX::TikZ::Scope;
8 LaTeX::TikZ::Scope - An object modeling a TikZ scope or layer.
16 our $VERSION = '0.02';
20 use LaTeX::TikZ::Tools;
32 isa => 'Maybe[ArrayRef[LaTeX::TikZ::Mod::Formatted]]',
34 default => sub { [ ] },
37 sub mods { @{$_[0]->_mods} }
39 has '_mods_cache' => (
41 isa => 'Maybe[HashRef[LaTeX::TikZ::Mod::Formatted]]',
43 default => sub { +{ } },
52 isa => 'ArrayRef[Str]',
57 my $my_tc = LaTeX::TikZ::Tools::type_constraint(__PACKAGE__);
58 my $ltmf_tc = LaTeX::TikZ::Tools::type_constraint('LaTeX::TikZ::Mod::Formatted');
59 my $body_tc = __PACKAGE__->meta->find_attribute_by_name('body')
62 around 'BUILDARGS' => sub {
63 my ($orig, $class, %args) = @_;
65 my $mods = $args{mods};
66 if (defined $mods and ref $mods eq 'ARRAY') {
67 for my $mod (@$mods) {
68 $mod = $ltmf_tc->coerce($mod);
72 my $body = $args{body};
73 if ($my_tc->check($body)) {
74 push @$mods, $body->mods;
75 $args{body} = $body->body;
86 my $cache = $scope->_mods_cache;
89 for my $mod ($scope->mods) {
91 next if exists $cache->{$tag};
92 $cache->{$tag} = $mod;
93 push @unique_mods, $mod;
95 $scope->_mods(\@unique_mods);
102 my $inter = Sub::Name::subname('inter' => sub {
105 my (@left, @common, @right);
108 --$where{$_} for keys %$lh;
109 ++$where{$_} for keys %$rh;
111 while (my ($key, $where) = each %where) {
113 push @left, $lh->{$key};
114 } elsif ($where > 0) {
115 push @right, $rh->{$key};
117 push @common, $rh->{$key};
121 return \@left, \@common, \@right;
124 =head2 C<instantiate>
131 my ($layer, @clips, @raw_mods);
134 if ($type eq 'clip') {
135 unshift @clips, $_->content;
136 } elsif ($type eq 'layer') {
137 confess("Can't apply two layers in a row") if defined $layer;
138 $layer = $_->content;
140 push @raw_mods, $_->content;
144 my @body = @{$scope->body};
146 my $mods_string = @raw_mods ? ' [' . join(',', @raw_mods) . ']' : undef;
148 if (@raw_mods and @body == 1 and $body[0] =~ /^\s*\\draw\b\s*([^\[].*)\s*$/) {
149 $body[0] = "\\draw$mods_string $1"; # Has trailing semicolon
150 $mods_string = undef; # Done with mods
154 my $clip = $clips[$_];
155 my $clip_string = "\\clip $clip ;";
156 my $mods_string = ($_ == $#clips and defined $mods_string)
158 unshift @body, "\\begin{scope}$mods_string",
160 push @body, "\\end{scope}",
163 if (not @clips and defined $mods_string) {
164 unshift @body, "\\begin{scope}$mods_string";
165 push @body, "\\end{scope}";
168 if (defined $layer) {
169 unshift @body, "\\begin{pgfonlayer}{$layer}";
170 push @body, "\\end{pgfonlayer}";
181 my ($left, $right, $rev) = @_;
185 if ($my_tc->check($left)) {
187 if ($my_tc->check($right)) {
189 my ($only_left, $common, $only_right) = $inter->(
194 my $has_different_layers;
195 for (@$only_left, @$only_right) {
196 if ($_->type eq 'layer') {
197 $has_different_layers = 1;
202 if (!$has_different_layers and @$common) {
209 body => $right->body,
213 body => fold($x, $y, $rev),
216 @right = $right->instantiate;
219 $body_tc->assert_valid($right);
223 @left = $left->instantiate;
225 if ($my_tc->check($right)) {
226 return fold($right, $left, 1);
228 $body_tc->assert_valid($_) for $left, $right;
234 $rev ? [ @right, @left ] : [ @left, @right ];
238 '@{}' => sub { [ $_[0]->instantiate ] },
241 __PACKAGE__->meta->make_immutable;
249 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
251 You can contact me by mail or on C<irc.perl.org> (vincent).
255 Please report any bugs or feature requests to C<bug-latex-tikz at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=LaTeX-TikZ>.
256 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
260 You can find documentation for this module with the perldoc command.
264 =head1 COPYRIGHT & LICENSE
266 Copyright 2010 Vincent Pit, all rights reserved.
268 This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
272 1; # End of LaTeX::TikZ::Scope