--- loncom/interface/lonnavmaps.pm 2003/05/14 18:34:44 1.189 +++ loncom/interface/lonnavmaps.pm 2003/05/14 20:16:56 1.190 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.189 2003/05/14 18:34:44 bowersj2 Exp $ +# $Id: lonnavmaps.pm,v 1.190 2003/05/14 20:16:56 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -737,6 +737,14 @@ returns a true or false value. If true, false, it is simply skipped in the display. By default, all resources are shown. +=item * B: + +If you're using a filter function, and displaying sequences to orient +the user, then frequently some sequences will be empty. Setting this to +true will cause those sequences not to display, so as not to confuse the +user into thinking that if the sequence is there there should be things +under it. + =item * B: If true, will not display Navigate Content resources. Default to @@ -1223,6 +1231,43 @@ sub render { $args->{'indentString'} = setDefault($args->{'indentString'}, ""); $args->{'displayedHereMarker'} = 0; + # If we're suppressing empty sequences, look for them here. Use DFS for speed, + # since structure actually doesn't matter, except what map has what resources. + if ($args->{'suppressEmptySequences'}) { + my $dfsit = Apache::lonnavmaps::DFSiterator->new($navmap, + $it->{FIRST_RESOURCE}, + $it->{FINISH_RESOURCE}, + {}, undef, 1); + $depth = 0; + $dfsit->next(); + my $curRes = $dfsit->next(); + while ($depth > -1) { + if ($curRes == $dfsit->BEGIN_MAP()) { $depth++; } + if ($curRes == $dfsit->END_MAP()) { $depth--; } + + if (ref($curRes)) { + # Parallel pre-processing: Do sequences have non-filtered-out children? + if ($curRes->is_sequence()) { + $curRes->{DATA}->{HAS_VISIBLE_CHILDREN} = 0; + # Sequences themselves do not count as visible children, + # unless those sequences also have visible children. + # This means if a sequence appears, there's a "promise" + # that there's something under it if you open it, somewhere. + } else { + # Not a sequence: if it's filtered, ignore it, otherwise + # rise up the stack and mark the sequences as having children + if (&$filterFunc($curRes)) { + for my $sequence (@{$dfsit->getStack()}) { + $sequence->{DATA}->{HAS_VISIBLE_CHILDREN} = 1; + } + } + } + } + } continue { + $curRes = $dfsit->next(); + } + } + my $displayedJumpMarker = 0; # Set up iteration. $depth = 1; @@ -1266,6 +1311,12 @@ sub render { next; } + # If this is an empty sequence and we're filtering them, continue on + if ($curRes->is_sequence() && $args->{'suppressEmptySequences'} && + !$curRes->{DATA}->{HAS_VISIBLE_CHILDREN}) { + next; + } + # If we're suppressing navmaps and this is a navmap, continue on if ($suppressNavmap && $curRes->src() =~ /^\/adm\/navmaps/) { next; @@ -2194,7 +2245,8 @@ sub new { $curRes->{DATA}->{DISPLAY_DEPTH} = $finalDepth; if ($finalDepth > $maxDepth) {$maxDepth = $finalDepth;} - } + } + } continue { $curRes = $iterator->next(); } } @@ -2571,6 +2623,31 @@ sub next { return $self->{HERE}; } +# Identical to the full iterator methods of the same name. Hate to copy/paste +# but I also hate to "inherit" either iterator from the other. + +sub getStack { + my $self=shift; + + my @stack; + + $self->populateStack(\@stack); + + return \@stack; +} + +# Private method: Calls the iterators recursively to populate the stack. +sub populateStack { + my $self=shift; + my $stack = shift; + + push @$stack, $self->{HERE} if ($self->{HERE}); + + if ($self->{RECURSIVE_ITERATOR_FLAG}) { + $self->{RECURSIVE_ITERATOR}->populateStack($stack); + } +} + 1; package Apache::lonnavmaps::resource;