--- loncom/xml/lonplot.pm 2002/01/03 22:09:49 1.31 +++ loncom/xml/lonplot.pm 2005/06/09 02:16:04 1.110 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Dynamic plot # -# $Id: lonplot.pm,v 1.31 2002/01/03 22:09:49 matthew Exp $ +# $Id: lonplot.pm,v 1.110 2005/06/09 02:16:04 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,22 +25,35 @@ # # http://www.lon-capa.org/ # -# 12/15/01 Matthew -# 12/17 12/18 12/19 12/20 12/21 12/27 12/28 12/30 12/31 Matthew -# 01/01/02 Matthew -# 01/02 01/03 Matthew + package Apache::lonplot; use strict; +use warnings FATAL=>'all'; +no warnings 'uninitialized'; use Apache::File; use Apache::response; use Apache::lonxml; use Apache::edit; +use Apache::lonnet; + +use vars qw/$weboutputformat $versionstring/; + -sub BEGIN { - &Apache::lonxml::register('Apache::lonplot',('plot')); + +BEGIN { + &Apache::lonxml::register('Apache::lonplot',('gnuplot')); + # + # Determine the version of GNUPLOT + $weboutputformat = 'gif'; + $versionstring = `gnuplot --version 2>/dev/null`; + if ($versionstring =~ /^gnuplot 4/) { + $weboutputformat = 'png'; + } + } + ## ## Description of data structures: ## @@ -72,6 +85,9 @@ sub BEGIN { ## ## ################################################################### +my $max_str_len = 50; # if a label, title, xlabel, or ylabel text + # is longer than this, it will be truncated. + my %linestyles = ( lines => 2, # Maybe this will be used in the future @@ -81,76 +97,107 @@ my %linestyles = steps => 2, # now there are more important things fsteps => 2, # for me to deal with. histeps => 2, - errorbars => 2, - xerrorbars => 2, - yerrorbars => 2, - xyerrorbars => 2, - boxes => 2, - boxerrorbars => 2, - boxxyerrorbars => 2, - financebars => 2, - candlesticks => 2, - vector => 2 + errorbars => 3, + xerrorbars => [3,4], + yerrorbars => [3,4], + xyerrorbars => [4,6], + boxes => 3, + filledcurves => 2, + vector => 4 ); my $int_test = sub {$_[0]=~s/\s+//g;$_[0]=~/^\d+$/}; my $real_test = sub {$_[0]=~s/\s+//g;$_[0]=~/^[+-]?\d*\.?\d*([eE][+-]\d+)?$/}; -my $color_test = sub {$_[0]=~s/\s+//g;$_[0]=~/^x[\da-f]{6}$/}; +my $pos_real_test = + sub {$_[0]=~s/\s+//g;$_[0]=~/^[+]?\d*\.?\d*([eE][+-]\d+)?$/}; +my $color_test = sub {$_[0]=~s/\s+//g;$_[0]=~/^x[\da-fA-F]{6}$/}; my $onoff_test = sub {$_[0]=~/^(on|off)$/}; my $key_pos_test = sub {$_[0]=~/^(top|bottom|right|left|outside|below| )+$/}; my $sml_test = sub {$_[0]=~/^(small|medium|large)$/}; my $linestyle_test = sub {exists($linestyles{$_[0]})}; -my $words_test = sub {$_[0]=~s/\s+/ /g;$_[0]=~/^([\w\(\)]+ ?)+$/}; +my $words_test = sub {$_[0]=~s/\s+/ /g;$_[0]=~/^([\w~!\@\#\$\%^&\*\(\)-=_\+\[\]\{\}:\;\'<>,\.\/\?\\]+ ?)+$/}; ################################################################### ## ## ## Attribute metadata ## ## ## ################################################################### -my %plot_defaults = +my @gnuplot_edit_order = + qw/alttag bgcolor fgcolor height width font transparent grid samples + border align texwidth texfont plotcolor plottype lmargin rmargin tmargin + bmargin major_ticscale minor_ticscale boxwidth gridlayer fillstyle + pattern solid/; + +my $margin_choices = ['default',0..20]; + +my %gnuplot_defaults = ( + alttag => { + default => 'dynamically generated plot', + test => $words_test, + description => 'brief description of the plot', + edit_type => 'entry', + size => '40' + }, height => { - default => 200, + default => 300, test => $int_test, description => 'height of image (pixels)', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, width => { - default => 200, + default => 400, test => $int_test, description => 'width of image (pixels)', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, bgcolor => { default => 'xffffff', test => $color_test, description => 'background color of image (xffffff)', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, fgcolor => { default => 'x000000', test => $color_test, description => 'foreground color of image (x000000)', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, transparent => { default => 'off', test => $onoff_test, - description => '', - edit_type => 'on_off' + description => 'Transparent image', + edit_type => 'onoff' }, grid => { + default => 'on', + test => $onoff_test, + description => 'Display grid', + edit_type => 'onoff' + }, + gridlayer => { default => 'off', test => $onoff_test, - description => '', - edit_type => 'on_off' + description => 'Display grid front layer over filled boxes or filled curves', + edit_type => 'onoff' + }, + box_border => { + default => 'noborder', + test => sub {$_[0]=~/^(noborder|border)$/}, + description => 'Draw border for boxes', + edit_type => 'choice', + choices => ['border','noborder'] }, border => { default => 'on', test => $onoff_test, - description => '', - edit_type => 'on_off' + description => 'Draw border around plot', + edit_type => 'onoff' }, font => { default => 'medium', @@ -159,13 +206,118 @@ my %plot_defaults = edit_type => 'choice', choices => ['small','medium','large'] }, + samples => { + default => '100', + test => $int_test, + description => 'Number of samples for non-data plots', + edit_type => 'choice', + choices => ['100','200','500','1000','2000','5000'] + }, align => { - default => 'left', + default => 'center', test => sub {$_[0]=~/^(left|right|center)$/}, description => 'alignment for image in html', edit_type => 'choice', choices => ['left','right','center'] - } + }, + texwidth => { + default => '93', + test => $int_test, + description => 'Width of plot when printed (mm)', + edit_type => 'entry', + size => '5' + }, + texfont => { + default => '22', + test => $int_test, + description => 'Font size to use in TeX output (pts):', + edit_type => 'choice', + choices => [qw/8 10 12 14 16 18 20 22 24 26 28 30 32 34 36/], + }, + plotcolor => { + default => 'monochrome', + test => sub {$_[0]=~/^(monochrome|color|colour)$/}, + description => 'Color setting for printing:', + edit_type => 'choice', + choices => [qw/monochrome color colour/], + }, + pattern => { + default => '', + test => $int_test, + description => 'pattern value for boxes:', + edit_type => 'choice', + choices => [0,1,2,3,4,5,6] + }, + solid => { + default => 0, + test => $real_test, + description => 'The density of fill style for boxes', + edit_type => 'entry', + size => '5' + }, + fillstyle => { + default => 'empty', + test => sub {$_[0]=~/^(empty|solid|pattern)$/}, + description => 'Filled style for boxes:', + edit_type => 'choice', + choices => ['empty','solid','pattern'] + }, + plottype => { + default => 'Cartesian', + test => sub {$_[0]=~/^(Polar|Cartesian)$/}, + description => 'Plot type:', + edit_type => 'choice', + choices => ['Cartesian','Polar'] + }, + lmargin => { + default => 'default', + test => sub {$_[0]=~/^(default|\d+)$/}, + description => 'Left margin width (pts):', + edit_type => 'choice', + choices => $margin_choices, + }, + rmargin => { + default => 'default', + test => sub {$_[0]=~/^(default|\d+)$/}, + description => 'Right margin width (pts):', + edit_type => 'choice', + choices => $margin_choices, + }, + tmargin => { + default => 'default', + test => sub {$_[0]=~/^(default|\d+)$/}, + description => 'Top margin width (pts):', + edit_type => 'choice', + choices => $margin_choices, + }, + bmargin => { + default => 'default', + test => sub {$_[0]=~/^(default|\d+)$/}, + description => 'Bottom margin width (pts):', + edit_type => 'choice', + choices => $margin_choices, + }, + boxwidth => { + default => '', + test => $real_test, + description => 'width of boxes default auto', + edit_type => 'entry', + size => '5' + }, + major_ticscale => { + default => '1', + test => $real_test, + description => 'Size of major tic marks (plot coordinates)', + edit_type => 'entry', + size => '5' + }, + minor_ticscale => { + default => '0.5', + test => $real_test, + description => 'Size of minor tic mark (plot coordinates)', + edit_type => 'entry', + size => '5' + }, ); my %key_defaults = @@ -174,13 +326,14 @@ my %key_defaults = default => '', test => $words_test, description => 'Title of key', - edit_type => 'entry' + edit_type => 'entry', + size => '40' }, box => { default => 'off', test => $onoff_test, description => 'Draw a box around the key?', - edit_type => 'on_off' + edit_type => 'onoff' }, pos => { default => 'top right', @@ -198,13 +351,15 @@ my %label_defaults = default => 0, test => $real_test, description => 'x position of label (graph coordinates)', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, ypos => { default => 0, test => $real_test, description => 'y position of label (graph coordinates)', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, justify => { default => 'left', @@ -215,65 +370,147 @@ my %label_defaults = } ); +my @tic_edit_order = ('location','mirror','start','increment','end', + 'minorfreq'); +my %tic_defaults = + ( + location => { + default => 'border', + test => sub {$_[0]=~/^(border|axis)$/}, + description => 'Location of major tic marks', + edit_type => 'choice', + choices => ['border','axis'] + }, + mirror => { + default => 'on', + test => $onoff_test, + description => 'mirror tics on opposite axis?', + edit_type => 'onoff' + }, + start => { + default => '-10.0', + test => $real_test, + description => 'Start major tics at', + edit_type => 'entry', + size => '10' + }, + increment => { + default => '1.0', + test => $real_test, + description => 'Place a major tic every', + edit_type => 'entry', + size => '10' + }, + end => { + default => ' 10.0', + test => $real_test, + description => 'Stop major tics at ', + edit_type => 'entry', + size => '10' + }, + minorfreq => { + default => '0', + test => $int_test, + description => 'Number of minor tics per major tic mark', + edit_type => 'entry', + size => '10' + }, + ); + +my @axis_edit_order = ('color','xmin','xmax','ymin','ymax'); my %axis_defaults = ( color => { default => 'x000000', test => $color_test, - description => 'color of axes (x000000)', - edit_type => 'entry' + description => 'color of grid lines (x000000)', + edit_type => 'entry', + size => '10' }, xmin => { default => '-10.0', test => $real_test, description => 'minimum x-value shown in plot', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, xmax => { default => ' 10.0', test => $real_test, description => 'maximum x-value shown in plot', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, ymin => { default => '-10.0', test => $real_test, description => 'minimum y-value shown in plot', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, ymax => { default => ' 10.0', test => $real_test, description => 'maximum y-value shown in plot', - edit_type => 'entry' + edit_type => 'entry', + size => '10' } ); +my @curve_edit_order = ('color','name','linestyle','pointtype','pointsize','limit'); + my %curve_defaults = ( color => { default => 'x000000', test => $color_test, description => 'color of curve (x000000)', - edit_type => 'entry' + edit_type => 'entry', + size => '10' }, name => { default => '', test => $words_test, description => 'name of curve to appear in key', - edit_type => 'entry' + edit_type => 'entry', + size => '20' }, linestyle => { default => 'lines', test => $linestyle_test, - description => 'Style of the axis lines', + description => 'Line style', edit_type => 'choice', - choices => ['lines','linespoints','dots','points','steps', - 'fsteps','histeps','errorbars','xerrorbars', - 'yerrorbars','xyerrorbars','boxes','boxerrorbars', - 'boxxyerrorbars','financebars','candlesticks', - 'vector'] - } + choices => [keys(%linestyles)] + }, +# gnuplots term=gif driver does not handle linewidth :( +# linewidth => { +# default => 1, +# test => $int_test, +# description => 'Line width (may not apply to all line styles)', +# edit_type => 'choice', +# choices => [1,2,3,4,5,6,7,8,9,10] +# }, + pointsize => { + default => 1, + test => $pos_real_test, + description => 'point size (may not apply to all line styles)', + edit_type => 'entry', + size => '5' + }, + pointtype => { + default => 1, + test => $int_test, + description => 'point type (may not apply to all line styles)', + edit_type => 'choice', + choices => [0,1,2,3,4,5,6] + }, + limit => { + default => 'closed', + test => sub {$_[0]=~/^(closed|x1|x2|y1|y2)$/}, + description => 'point to fill -- for filledcurves', + edit_type => 'choice', + choices => ['closed','x1','x2','y1','y2'] + }, ); ################################################################### @@ -281,75 +518,156 @@ my %curve_defaults = ## parsing and edit rendering ## ## ## ################################################################### -my (%plot,%key,%axis,$title,$xlabel,$ylabel,@labels,@curves); -sub start_plot { - %plot = (); %key = (); %axis = (); - $title = undef; $xlabel = undef; $ylabel = undef; - $#labels = -1; $#curves = -1; +undef %Apache::lonplot::plot; +my (%key,%axis,$title,$xlabel,$ylabel,@labels,@curves,%xtics,%ytics); + +sub start_gnuplot { + undef(%Apache::lonplot::plot); undef(%key); undef(%axis); + undef($title); undef($xlabel); undef($ylabel); + undef(@labels); undef(@curves); + undef(%xtics); undef(%ytics); # my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; &Apache::lonxml::register('Apache::lonplot', - ('title','xlabel','ylabel','key','axis','label','curve')); + ('title','xlabel','ylabel','key','axis','label','curve', + 'xtics','ytics')); push (@Apache::lonxml::namespace,'lonplot'); - if ($target eq 'web') { - my $inside = &Apache::lonxml::get_all_text("/plot",$$parser[-1]); - $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]); - &Apache::lonxml::newparser($parser,\$inside); - &get_attributes(\%plot,\%plot_defaults,$parstack,$safeeval, + if ($target eq 'web' || $target eq 'tex') { + &get_attributes(\%Apache::lonplot::plot,\%gnuplot_defaults,$parstack,$safeeval, $tagstack->[-1]); } elsif ($target eq 'edit') { - $result .= &Apache::edit::tag_start($target,$token,'Plot'); - $result .= &edit_attributes($target,$token,\%plot_defaults); + $result .= &Apache::edit::tag_start($target,$token,'GnuPlot'); + $result .= &edit_attributes($target,$token,\%gnuplot_defaults, + \@gnuplot_edit_order); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args - ($token,$parstack,$safeeval,keys(%plot_defaults)); + ($token,$parstack,$safeeval,keys(%gnuplot_defaults)); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); -# $result.= &Apache::edit::handle_insert(); } } return $result; } -sub end_plot { +sub end_gnuplot { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; - pop @Apache::lonxml::namespace; &Apache::lonxml::deregister('Apache::lonplot', ('title','xlabel','ylabel','key','axis','label','curve')); my $result = ''; - if ($target eq 'web') { + my $randnumber; + # need to call rand everytime start_script would evaluate, as the + # safe space rand number generator and the global rand generator + # are not separate + if ($target eq 'web' || $target eq 'tex' || $target eq 'grade' || + $target eq 'answer') { + $randnumber=int(rand(1000)); + } + if ($target eq 'web' || $target eq 'tex') { &check_inputs(); # Make sure we have all the data we need ## ## Determine filename my $tmpdir = '/home/httpd/perl/tmp/'; - my $filename = $ENV{'user.name'}.'_'.$ENV{'user.domain'}. - '_'.time.'_'.$$.int(rand(1000)).'_plot.data'; + my $filename = $env{'user.name'}.'_'.$env{'user.domain'}. + '_'.time.'_'.$$.$randnumber.'_plot'; ## Write the plot description to the file - my $fh=Apache::File->new(">$tmpdir$filename"); - print $fh &write_gnuplot_file(); - close($fh); + &write_gnuplot_file($tmpdir,$filename,$target); + $filename = &Apache::lonnet::escape($filename); ## return image tag for the plot - $result .= <<"ENDIMAGE"; -/cgi-bin/plot.gif?$filename + if ($target eq 'web') { + $result .= <<"ENDIMAGE"; +$Apache::lonplot::plot{'alttag'} ENDIMAGE + } elsif ($target eq 'tex') { + &Apache::lonxml::debug(" gnuplot wid = $Apache::lonplot::plot{'width'}"); + &Apache::lonxml::debug(" gnuplot ht = $Apache::lonplot::plot{'height'}"); + #might be inside the safe space, register the URL for later + &Apache::lonxml::register_ssi("/cgi-bin/plot.gif?file=$filename.data&output=eps"); + $result = "%DYNAMICIMAGE:$Apache::lonplot::plot{'width'}:$Apache::lonplot::plot{'height'}:$Apache::lonplot::plot{'texwidth'} \n"; + $result .= '\graphicspath{{/home/httpd/perl/tmp/}}'."\n"; + $result .= '\includegraphics[width='.$Apache::lonplot::plot{'texwidth'}.' mm]{'.&Apache::lonnet::unescape($filename).'.eps}'; + } + } elsif ($target eq 'edit') { + $result.=&Apache::edit::tag_end($target,$token); + } + return $result; +} + + +##--------------------------------------------------------------- xtics +sub start_xtics { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result=''; + if ($target eq 'web' || $target eq 'tex') { + &get_attributes(\%xtics,\%tic_defaults,$parstack,$safeeval, + $tagstack->[-1]); + } elsif ($target eq 'edit') { + $result .= &Apache::edit::tag_start($target,$token,'xtics'); + $result .= &edit_attributes($target,$token,\%tic_defaults, + \@tic_edit_order); + } elsif ($target eq 'modified') { + my $constructtag=&Apache::edit::get_new_args + ($token,$parstack,$safeeval,keys(%tic_defaults)); + if ($constructtag) { + $result = &Apache::edit::rebuild_tag($token); + } + } + return $result; +} + +sub end_xtics { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result = ''; + if ($target eq 'web' || $target eq 'tex') { + } elsif ($target eq 'edit') { + $result.=&Apache::edit::tag_end($target,$token); + } + return $result; +} + +##--------------------------------------------------------------- ytics +sub start_ytics { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result=''; + if ($target eq 'web' || $target eq 'tex') { + &get_attributes(\%ytics,\%tic_defaults,$parstack,$safeeval, + $tagstack->[-1]); + } elsif ($target eq 'edit') { + $result .= &Apache::edit::tag_start($target,$token,'ytics'); + $result .= &edit_attributes($target,$token,\%tic_defaults, + \@tic_edit_order); + } elsif ($target eq 'modified') { + my $constructtag=&Apache::edit::get_new_args + ($token,$parstack,$safeeval,keys(%tic_defaults)); + if ($constructtag) { + $result = &Apache::edit::rebuild_tag($token); + } + } + return $result; +} + +sub end_ytics { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + my $result = ''; + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); } return $result; } + ##----------------------------------------------------------------- key sub start_key { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { &get_attributes(\%key,\%key_defaults,$parstack,$safeeval, $tagstack->[-1]); } elsif ($target eq 'edit') { @@ -360,7 +678,6 @@ sub start_key { ($token,$parstack,$safeeval,keys(%key_defaults)); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); - $result.= &Apache::edit::handle_insert(); } } return $result; @@ -369,7 +686,7 @@ sub start_key { sub end_key { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result = ''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); } @@ -380,16 +697,22 @@ sub end_key { sub start_title { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; - if ($target eq 'web') { - $title = &Apache::lonxml::get_all_text("/title",$$parser[-1]); + if ($target eq 'web' || $target eq 'tex') { + $title = &Apache::lonxml::get_all_text("/title",$parser); + $title=&Apache::run::evaluate($title,$safeeval,$$parstack[-1]); + $title =~ s/\n/ /g; + if (length($title) > $max_str_len) { + $title = substr($title,0,$max_str_len); + } } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_start($target,$token,'Plot Title'); - my $text=&Apache::lonxml::get_all_text("/title",$$parser[-1]); - $result.=''. - &Apache::edit::editfield('',$text,'',60,1); + my $text=&Apache::lonxml::get_all_text("/title",$parser); + $result.=&Apache::edit::end_row(). + &Apache::edit::start_spanning_row(). + &Apache::edit::editline('',$text,'',60); } elsif ($target eq 'modified') { - my $text=$$parser[-1]->get_text("/title"); - $result.=&Apache::edit::modifiedfield($token); + $result.=&Apache::edit::rebuild_tag($token); + $result.=&Apache::edit::modifiedfield("/title",$parser); } return $result; } @@ -397,7 +720,7 @@ sub start_title { sub end_title { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result = ''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); } @@ -407,16 +730,22 @@ sub end_title { sub start_xlabel { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; - if ($target eq 'web') { - $xlabel = &Apache::lonxml::get_all_text("/xlabel",$$parser[-1]); + if ($target eq 'web' || $target eq 'tex') { + $xlabel = &Apache::lonxml::get_all_text("/xlabel",$parser); + $xlabel=&Apache::run::evaluate($xlabel,$safeeval,$$parstack[-1]); + $xlabel =~ s/\n/ /g; + if (length($xlabel) > $max_str_len) { + $xlabel = substr($xlabel,0,$max_str_len); + } } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_start($target,$token,'Plot Xlabel'); - my $text=&Apache::lonxml::get_all_text("/xlabel",$$parser[-1]); - $result.=''. - &Apache::edit::editfield('',$text,'',60,1); + my $text=&Apache::lonxml::get_all_text("/xlabel",$parser); + $result.=&Apache::edit::end_row(). + &Apache::edit::start_spanning_row(). + &Apache::edit::editline('',$text,'',60); } elsif ($target eq 'modified') { - my $text=$$parser[-1]->get_text("/xlabel"); - $result.=&Apache::edit::modifiedfield($token); + $result.=&Apache::edit::rebuild_tag($token); + $result.=&Apache::edit::modifiedfield("/xlabel",$parser); } return $result; } @@ -424,7 +753,7 @@ sub start_xlabel { sub end_xlabel { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result = ''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); } @@ -435,16 +764,22 @@ sub end_xlabel { sub start_ylabel { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; - if ($target eq 'web') { - $ylabel = &Apache::lonxml::get_all_text("/ylabel",$$parser[-1]); + if ($target eq 'web' || $target eq 'tex') { + $ylabel = &Apache::lonxml::get_all_text("/ylabel",$parser); + $ylabel = &Apache::run::evaluate($ylabel,$safeeval,$$parstack[-1]); + $ylabel =~ s/\n/ /g; + if (length($ylabel) > $max_str_len) { + $ylabel = substr($ylabel,0,$max_str_len); + } } elsif ($target eq 'edit') { $result .= &Apache::edit::tag_start($target,$token,'Plot Ylabel'); - my $text = &Apache::lonxml::get_all_text("/ylabel",$$parser[-1]); - $result .= ''. - &Apache::edit::editfield('',$text,'',60,1); + my $text = &Apache::lonxml::get_all_text("/ylabel",$parser); + $result .= &Apache::edit::end_row(). + &Apache::edit::start_spanning_row(). + &Apache::edit::editline('',$text,'',60); } elsif ($target eq 'modified') { - my $text=$$parser[-1]->get_text("/ylabel"); - $result.=&Apache::edit::modifiedfield($token); + $result.=&Apache::edit::rebuild_tag($token); + $result.=&Apache::edit::modifiedfield("/ylabel",$parser); } return $result; } @@ -452,7 +787,7 @@ sub start_ylabel { sub end_ylabel { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result = ''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); } @@ -463,32 +798,28 @@ sub end_ylabel { sub start_label { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { my %label; &get_attributes(\%label,\%label_defaults,$parstack,$safeeval, $tagstack->[-1]); - $label{'text'} = &Apache::lonxml::get_all_text("/label",$$parser[-1]); - $label{'text'} =~ s/[\-\:\`\'\"\,\.]//g; - if (! &$words_test($label{'text'})) { - # I should probably warn about it, too. - $label{'text'} = 'Illegal text'; - } + my $text = &Apache::lonxml::get_all_text("/label",$parser); + $text = &Apache::run::evaluate($text,$safeeval,$$parstack[-1]); + $text =~ s/\n/ /g; + $text = substr($text,0,$max_str_len) if (length($text) > $max_str_len); + $label{'text'} = $text; push(@labels,\%label); } elsif ($target eq 'edit') { $result .= &Apache::edit::tag_start($target,$token,'Plot Label'); $result .= &edit_attributes($target,$token,\%label_defaults); - my $text = &Apache::lonxml::get_all_text("/label",$$parser[-1]); - $result .= ''. - &Apache::edit::editfield('',$text,'',60,1); + my $text = &Apache::lonxml::get_all_text("/label",$parser); + $result .= &Apache::edit::end_row(). + &Apache::edit::start_spanning_row(). + &Apache::edit::editline('',$text,'',60); } elsif ($target eq 'modified') { - my $constructtag=&Apache::edit::get_new_args + &Apache::edit::get_new_args ($token,$parstack,$safeeval,keys(%label_defaults)); - if ($constructtag) { - $result = &Apache::edit::rebuild_tag($token); - $result.= &Apache::edit::handle_insert(); - } - my $text=$$parser[-1]->get_text("/label"); - $result.=&Apache::edit::modifiedfield($token); + $result.=&Apache::edit::rebuild_tag($token); + $result.=&Apache::edit::modifiedfield("/label",$parser); } return $result; } @@ -496,7 +827,7 @@ sub start_label { sub end_label { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result = ''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); } @@ -509,17 +840,18 @@ sub start_curve { my $result=''; &Apache::lonxml::register('Apache::lonplot',('function','data')); push (@Apache::lonxml::namespace,'curve'); - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { my %curve; &get_attributes(\%curve,\%curve_defaults,$parstack,$safeeval, $tagstack->[-1]); push (@curves,\%curve); } elsif ($target eq 'edit') { $result .= &Apache::edit::tag_start($target,$token,'Curve'); - $result .= &edit_attributes($target,$token,\%curve_defaults); + $result .= &edit_attributes($target,$token,\%curve_defaults, + \@curve_edit_order); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args - ($token,$parstack,$safeeval,keys(%label_defaults)); + ($token,$parstack,$safeeval,keys(%curve_defaults)); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); $result.= &Apache::edit::handle_insert(); @@ -533,7 +865,7 @@ sub end_curve { my $result = ''; pop @Apache::lonxml::namespace; &Apache::lonxml::deregister('Apache::lonplot',('function','data')); - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); } @@ -544,22 +876,27 @@ sub end_curve { sub start_function { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { if (exists($curves[-1]->{'data'})) { - &Apache::lonxml::warning('Use of precludes use of . The will be omitted in favor of the declaration.'); + &Apache::lonxml::warning + ('Use of the curve function tag precludes use of '. + ' the curve data tag. '. + 'The curve data tag will be omitted in favor of the '. + 'curve function declaration.'); delete $curves[-1]->{'data'} ; } - $curves[-1]->{'function'} = - &Apache::lonxml::get_all_text("/function",$$parser[-1]); + my $function = &Apache::lonxml::get_all_text("/function",$parser); + $function = &Apache::run::evaluate($function,$safeeval,$$parstack[-1]); + $curves[-1]->{'function'} = $function; } elsif ($target eq 'edit') { - $result .= &Apache::edit::tag_start($target,$token,'Curve Function'); - my $text = &Apache::lonxml::get_all_text("/function",$$parser[-1]); - $result .= ''. - &Apache::edit::editfield('',$text,'',60,1); - } elsif ($target eq 'modified') { - # Why do I do this? - my $text=$$parser[-1]->get_text("/function"); - $result.=&Apache::edit::modifiedfield($token); + $result .= &Apache::edit::tag_start($target,$token,'Gnuplot compatible curve function'); + my $text = &Apache::lonxml::get_all_text("/function",$parser); + $result .= &Apache::edit::end_row(). + &Apache::edit::start_spanning_row(). + &Apache::edit::editline('',$text,'',60); + } elsif ($target eq 'modified') { + $result.=&Apache::edit::rebuild_tag($token); + $result.=&Apache::edit::modifiedfield("/function",$parser); } return $result; } @@ -567,7 +904,7 @@ sub start_function { sub end_function { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result = ''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result .= &Apache::edit::end_table(); } @@ -578,49 +915,65 @@ sub end_function { sub start_data { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { if (exists($curves[-1]->{'function'})) { - &Apache::lonxml::warning('Use of precludes use of .'. - '. The will be omitted in favor of '. - 'the declaration.'); + &Apache::lonxml::warning + ('Use of the curve function tag precludes use of '. + ' the curve data tag. '. + 'The curve function tag will be omitted in favor of the '. + 'curve data declaration.'); delete($curves[-1]->{'function'}); } - my $datatext = &Apache::lonxml::get_all_text("/data",$$parser[-1]); - $datatext =~ s/\s+/ /g; + my $datatext = &Apache::lonxml::get_all_text("/data",$parser); + $datatext=&Apache::run::evaluate($datatext,$safeeval,$$parstack[-1]); + # Deal with cases where we're given an array... + if ($datatext =~ /^\@/) { + $datatext = &Apache::run::run('return "'.$datatext.'"', + $safeeval,1); + } + $datatext =~ s/\s+/ /g; # Need to do some error checking on the @data array - # make sure it's all numbers and make sure each array # is of the same length. my @data; - if ($datatext =~ /,/) { + if ($datatext =~ /,/) { # comma deliminated @data = split /,/,$datatext; - } else { # Assume it's space seperated. + } else { # Assume it's space separated. @data = split / /,$datatext; } for (my $i=0;$i<=$#data;$i++) { # Check that it's non-empty if (! defined($data[$i])) { &Apache::lonxml::warning( - 'undefined value. Replacing with '. + 'undefined curve data value. Replacing with '. ' pi/e = 1.15572734979092'); $data[$i] = 1.15572734979092; } # Check that it's a number if (! &$real_test($data[$i]) & ! &$int_test($data[$i])) { &Apache::lonxml::warning( - 'Bad value of '.$data[$i].' Replacing with '. + 'Bad curve data value of '.$data[$i].' Replacing with '. ' pi/e = 1.15572734979092'); $data[$i] = 1.15572734979092; } } + # complain if the number of data points is not the same as + # in previous sets of data. + if (($curves[-1]->{'data'}) && ($#data != $#{@{$curves[-1]->{'data'}->[0]}})){ + &Apache::lonxml::warning + ('Number of data points is not consistent with previous '. + 'number of data points'); + } push @{$curves[-1]->{'data'}},\@data; } elsif ($target eq 'edit') { - $result .= &Apache::edit::tag_start($target,$token,'Curve Data'); - my $text = &Apache::lonxml::get_all_text("/data",$$parser[-1]); - $result .= ''. - &Apache::edit::editfield('',$text,'',60,1); + $result .= &Apache::edit::tag_start($target,$token,'Comma or space deliminated curve data'); + my $text = &Apache::lonxml::get_all_text("/data",$parser); + $result .= &Apache::edit::end_row(). + &Apache::edit::start_spanning_row(). + &Apache::edit::editline('',$text,'',60); } elsif ($target eq 'modified') { - my $text=$$parser[-1]->get_text("/data"); - $result.=&Apache::edit::modifiedfield($token); + $result.=&Apache::edit::rebuild_tag($token); + $result.=&Apache::edit::modifiedfield("/data",$parser); } return $result; } @@ -628,7 +981,7 @@ sub start_data { sub end_data { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result = ''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result .= &Apache::edit::end_table(); } @@ -639,18 +992,18 @@ sub end_data { sub start_axis { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { &get_attributes(\%axis,\%axis_defaults,$parstack,$safeeval, $tagstack->[-1]); } elsif ($target eq 'edit') { $result .= &Apache::edit::tag_start($target,$token,'Plot Axes'); - $result .= &edit_attributes($target,$token,\%axis_defaults); + $result .= &edit_attributes($target,$token,\%axis_defaults, + \@axis_edit_order); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args ($token,$parstack,$safeeval,keys(%axis_defaults)); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); - $result.= &Apache::edit::handle_insert(); } } return $result; @@ -659,7 +1012,7 @@ sub start_axis { sub end_axis { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result = ''; - if ($target eq 'web') { + if ($target eq 'web' || $target eq 'tex') { } elsif ($target eq 'edit') { $result.=&Apache::edit::tag_end($target,$token); } elsif ($target eq 'modified') { @@ -686,8 +1039,13 @@ sub set_defaults { sub get_attributes{ my ($values,$defaults,$parstack,$safeeval,$tag) = @_; foreach my $attr (keys(%{$defaults})) { - $values->{$attr} = - &Apache::lonxml::get_param($attr,$parstack,$safeeval); + if ($attr eq 'texwidth' || $attr eq 'texfont') { + $values->{$attr} = + &Apache::lonxml::get_param($attr,$parstack,$safeeval,undef,1); + } else { + $values->{$attr} = + &Apache::lonxml::get_param($attr,$parstack,$safeeval); + } if ($values->{$attr} eq '' | !defined($values->{$attr})) { $values->{$attr} = $defaults->{$attr}->{'default'}; next; @@ -702,36 +1060,134 @@ sub get_attributes{ } return ; } + ##------------------------------------------------------- write_gnuplot_file sub write_gnuplot_file { + my ($tmpdir,$filename,$target)= @_; my $gnuplot_input = ''; my $curve; + my $pt = $Apache::lonplot::plot{'texfont'}; + # + # Check to be sure we do not have any empty curves + my @curvescopy; + foreach my $curve (@curves) { + if (exists($curve->{'function'})) { + if ($curve->{'function'} !~ /^\s*$/) { + push(@curvescopy,$curve); + } + } elsif (exists($curve->{'data'})) { + foreach my $data (@{$curve->{'data'}}) { + if (scalar(@$data) > 0) { + push(@curvescopy,$curve); + last; + } + } + } + } + @curves = @curvescopy; # Collect all the colors my @Colors; - push @Colors, $plot{'bgcolor'}; - push @Colors, $plot{'fgcolor'}; - push @Colors, (defined($axis{'color'})?$axis{'color'}:$plot{'fgcolor'}); + push @Colors, $Apache::lonplot::plot{'bgcolor'}; + push @Colors, $Apache::lonplot::plot{'fgcolor'}; + push @Colors, (defined($axis{'color'})?$axis{'color'}:$Apache::lonplot::plot{'fgcolor'}); foreach $curve (@curves) { push @Colors, ($curve->{'color'} ne '' ? $curve->{'color'} : - $plot{'fgcolor'} ); + $Apache::lonplot::plot{'fgcolor'} ); } # set term - $gnuplot_input .= 'set term gif '; - $gnuplot_input .= 'transparent ' if ($plot{'transparent'} eq 'on'); - $gnuplot_input .= $plot{'font'} . ' '; - $gnuplot_input .= 'size '.$plot{'width'}.','.$plot{'height'}.' '; - $gnuplot_input .= "@Colors\n"; + if ($target eq 'web') { + $gnuplot_input .= 'set term '.$weboutputformat .' '; + $gnuplot_input .= 'transparent ' if ($Apache::lonplot::plot{'transparent'} eq 'on'); + $gnuplot_input .= $Apache::lonplot::plot{'font'} . ' '; + $gnuplot_input .= 'size '.$Apache::lonplot::plot{'width'}.','.$Apache::lonplot::plot{'height'}.' '; + $gnuplot_input .= "@Colors\n"; + # set output + $gnuplot_input .= "set output\n"; + } elsif ($target eq 'tex') { + $gnuplot_input .= "set term postscript eps $Apache::lonplot::plot{'plotcolor'} solid \"Helvetica\" $pt \n"; + $gnuplot_input .= "set output \"/home/httpd/perl/tmp/". + &Apache::lonnet::unescape($filename).".eps\"\n"; + } + # cartesian or polar? + if (lc($Apache::lonplot::plot{'plottype'}) eq 'polar') { + $gnuplot_input .= 'set polar'.$/; + } else { + # Assume Cartesian + } + # solid or pattern for boxes? + if (lc($Apache::lonplot::plot{'fillstyle'}) eq 'solid') { + $gnuplot_input .= 'set style fill solid '. + $Apache::lonplot::plot{'solid'}.$Apache::lonplot::plot{'box_border'}.$/; + } elsif (lc($Apache::lonplot::plot{'fillstyle'}) eq 'pattern') { + $gnuplot_input .= 'set style fill pattern '.$Apache::lonplot::plot{'pattern'}.$Apache::lonplot::plot{'box_border'}.$/; + } elsif (lc($Apache::lonplot::plot{'fillstyle'}) eq 'empty') { + } + # margin + if (lc($Apache::lonplot::plot{'lmargin'}) ne 'default') { + $gnuplot_input .= 'set lmargin '.$Apache::lonplot::plot{'lmargin'}.$/; + } + if (lc($Apache::lonplot::plot{'rmargin'}) ne 'default') { + $gnuplot_input .= 'set rmargin '.$Apache::lonplot::plot{'rmargin'}.$/; + } + if (lc($Apache::lonplot::plot{'tmargin'}) ne 'default') { + $gnuplot_input .= 'set tmargin '.$Apache::lonplot::plot{'tmargin'}.$/; + } + if (lc($Apache::lonplot::plot{'bmargin'}) ne 'default') { + $gnuplot_input .= 'set bmargin '.$Apache::lonplot::plot{'bmargin'}.$/; + } + # tic scales + $gnuplot_input .= 'set ticscale '. + $Apache::lonplot::plot{'major_ticscale'}.' '.$Apache::lonplot::plot{'minor_ticscale'}.$/; + #boxwidth + if (lc($Apache::lonplot::plot{'boxwidth'}) ne '') { + $gnuplot_input .= 'set boxwidth '.$Apache::lonplot::plot{'boxwidth'}.$/; + } + # gridlayer + $gnuplot_input .= 'set grid noxtics noytics front '.$/ + if ($Apache::lonplot::plot{'gridlayer'} eq 'on'); + # grid - $gnuplot_input .= 'set grid'.$/ if ($plot{'grid'} eq 'on'); + $gnuplot_input .= 'set grid'.$/ if ($Apache::lonplot::plot{'grid'} eq 'on'); # border - $gnuplot_input .= ($plot{'border'} eq 'on'? + $gnuplot_input .= ($Apache::lonplot::plot{'border'} eq 'on'? 'set border'.$/ : - 'set noborder'.$/ ); # title, xlabel, ylabel - $gnuplot_input .= "set output\n"; - $gnuplot_input .= "set title \"$title\"\n" if (defined($title)) ; - $gnuplot_input .= "set xlabel \"$xlabel\"\n" if (defined($xlabel)); - $gnuplot_input .= "set ylabel \"$ylabel\"\n" if (defined($ylabel)); + 'set noborder'.$/ ); + # sampling rate for non-data curves + $gnuplot_input .= "set samples $Apache::lonplot::plot{'samples'}\n"; + # title, xlabel, ylabel + # titles + if ($target eq 'tex') { + $gnuplot_input .= "set title \"$title\" font \"Helvetica,".$pt."pt\"\n" if (defined($title)) ; + $gnuplot_input .= "set xlabel \"$xlabel\" font \"Helvetica,".$pt."pt\" \n" if (defined($xlabel)); + $gnuplot_input .= "set ylabel \"$ylabel\" font \"Helvetica,".$pt."pt\"\n" if (defined($ylabel)); + } else { + $gnuplot_input .= "set title \"$title\" \n" if (defined($title)) ; + $gnuplot_input .= "set xlabel \"$xlabel\" \n" if (defined($xlabel)); + $gnuplot_input .= "set ylabel \"$ylabel\" \n" if (defined($ylabel)); + } + # tics + if (%xtics) { + $gnuplot_input .= "set xtics $xtics{'location'} "; + $gnuplot_input .= ( $xtics{'mirror'} eq 'on'?"mirror ":"nomirror "); + $gnuplot_input .= "$xtics{'start'}, "; + $gnuplot_input .= "$xtics{'increment'}, "; + $gnuplot_input .= "$xtics{'end'}\n"; + if ($xtics{'minorfreq'} != 0) { + $gnuplot_input .= "set mxtics ".$xtics{'minorfreq'}."\n"; + } + } + if (%ytics) { + $gnuplot_input .= "set ytics $ytics{'location'} "; + $gnuplot_input .= ( $ytics{'mirror'} eq 'on'?"mirror ":"nomirror "); + $gnuplot_input .= "$ytics{'start'}, "; + $gnuplot_input .= "$ytics{'increment'}, "; + $gnuplot_input .= "$ytics{'end'}\n"; + if ($ytics{'minorfreq'} != 0) { + $gnuplot_input .= "set mytics ".$ytics{'minorfreq'}."\n"; + } + } + # axis if (%axis) { $gnuplot_input .= "set xrange \[$axis{'xmin'}:$axis{'xmax'}\]\n"; $gnuplot_input .= "set yrange \[$axis{'ymin'}:$axis{'ymax'}\]\n"; @@ -750,11 +1206,18 @@ sub write_gnuplot_file { my $label; foreach $label (@labels) { $gnuplot_input .= 'set label "'.$label->{'text'}.'" at '. - $label->{'xpos'}.','.$label->{'ypos'}.' '.$label->{'justify'}.$/ ; - } + $label->{'xpos'}.','.$label->{'ypos'}.' '.$label->{'justify'}; + if ($target eq 'tex') { + $gnuplot_input .=' font "Helvetica,'.$pt.'pt"' ; + } + $gnuplot_input .= $/; + } + if ($target eq 'tex') { + $gnuplot_input .="set size 1,".$Apache::lonplot::plot{'height'}/$Apache::lonplot::plot{'width'}*1.38; + $gnuplot_input .="\n"; + } # curves $gnuplot_input .= 'plot '; - my $datatext = ''; for (my $i = 0;$i<=$#curves;$i++) { $curve = $curves[$i]; $gnuplot_input.= ', ' if ($i > 0); @@ -762,11 +1225,26 @@ sub write_gnuplot_file { $gnuplot_input.= $curve->{'function'}.' title "'. $curve->{'name'}.'" with '. - $curve->{'linestyle'}; + $curve->{'linestyle'}; + $gnuplot_input.= ' linewidth 4 ' if ($target eq 'tex'); + if (($curve->{'linestyle'} eq 'points') || + ($curve->{'linestyle'} eq 'linespoints') || + ($curve->{'linestyle'} eq 'errorbars') || + ($curve->{'linestyle'} eq 'xerrorbars') || + ($curve->{'linestyle'} eq 'yerrorbars') || + ($curve->{'linestyle'} eq 'xyerrorbars')) { + $gnuplot_input.=' pointtype '.$curve->{'pointtype'}; + $gnuplot_input.=' pointsize '.$curve->{'pointsize'}; + } elsif ($curve->{'linestyle'} eq 'filledcurves') { + $gnuplot_input.= ' '.$curve->{'limit'}; + } } elsif (exists($curve->{'data'})) { - $gnuplot_input.= '\'-\' title "'. - $curve->{'name'}.'" with '. - $curve->{'linestyle'}; + # Store data values in $datatext + my $datatext = ''; + # get new filename + my $datafilename = "$tmpdir/$filename.data.$i"; + my $fh=Apache::File->new(">$datafilename"); + # Compile data my @Data = @{$curve->{'data'}}; my @Data0 = @{$Data[0]}; for (my $i =0; $i<=$#Data0; $i++) { @@ -776,20 +1254,42 @@ sub write_gnuplot_file { } $datatext .= $/; } - $datatext .=$/; + # write file + print $fh $datatext; + close ($fh); + # generate gnuplot text + $gnuplot_input.= '"'.$datafilename.'" title "'. + $curve->{'name'}.'" with '. + $curve->{'linestyle'}; + $gnuplot_input.= ' linewidth 4 ' if ($target eq 'tex'); + if (($curve->{'linestyle'} eq 'points') || + ($curve->{'linestyle'} eq 'linespoints') || + ($curve->{'linestyle'} eq 'errorbars') || + ($curve->{'linestyle'} eq 'xerrorbars') || + ($curve->{'linestyle'} eq 'yerrorbars') || + ($curve->{'linestyle'} eq 'xyerrorbars')) { + $gnuplot_input.=' pointtype '.$curve->{'pointtype'}; + $gnuplot_input.=' pointsize '.$curve->{'pointsize'}; + } elsif ($curve->{'linestyle'} eq 'filledcurves') { + $gnuplot_input.= ' '.$curve->{'limit'}; + } } } - $gnuplot_input .= $/.$datatext; - return $gnuplot_input; + # Write the output to a file. + my $fh=Apache::File->new(">$tmpdir$filename.data"); + print $fh $gnuplot_input; + close($fh); + # That's all folks. + return ; } #---------------------------------------------- check_inputs sub check_inputs { ## Note: no inputs, no outputs - this acts only on global variables. ## Make sure we have all the input we need: - if (! %plot) { &set_defaults(\%plot,\%plot_defaults); } + if (! %Apache::lonplot::plot) { &set_defaults(\%Apache::lonplot::plot,\%gnuplot_defaults); } if (! %key ) {} # No key for this plot, thats okay - if (! %axis) { &set_defaults(\%axis,\%axis_defaults); } +# if (! %axis) { &set_defaults(\%axis,\%axis_defaults); } if (! defined($title )) {} # No title for this plot, thats okay if (! defined($xlabel)) {} # No xlabel for this plot, thats okay if (! defined($ylabel)) {} # No ylabel for this plot, thats okay @@ -801,7 +1301,7 @@ sub check_inputs { my $curve; foreach $curve (@curves) { if (!defined($curve->{'function'})&&!defined($curve->{'data'})){ - &Apache::lonxml::warning("One of the curves specified did not contain any or declarations\n"); + &Apache::lonxml::warning("One of the curves specified did not contain any curve data or curve function declarations\n"); return ''; } } @@ -809,20 +1309,27 @@ sub check_inputs { #------------------------------------------------ make_edit sub edit_attributes { - my ($target,$token,$defaults) = @_; - my $result; - foreach my $attr (sort keys(%$defaults)) { + my ($target,$token,$defaults,$keys) = @_; + my ($result,@keys); + if ($keys && ref($keys) eq 'ARRAY') { + @keys = @$keys; + } else { + @keys = sort(keys(%$defaults)); + } + foreach my $attr (@keys) { + # append a ' ' to the description if it doesn't have one already. + my $description = $defaults->{$attr}->{'description'}; + $description .= ' ' if ($description !~ / $/); if ($defaults->{$attr}->{'edit_type'} eq 'entry') { - $result .= &Apache::edit::text_arg( - $defaults->{$attr}->{'description'}, - $attr, - $token); + $result .= &Apache::edit::text_arg + ($description,$attr,$token, + $defaults->{$attr}->{'size'}); } elsif ($defaults->{$attr}->{'edit_type'} eq 'choice') { - $result .= &Apache::edit::select_arg( - $defaults->{$attr}->{'description'}, - $attr, - $defaults->{$attr}->{'choices'}, - $token); + $result .= &Apache::edit::select_or_text_arg + ($description,$attr,$defaults->{$attr}->{'choices'},$token); + } elsif ($defaults->{$attr}->{'edit_type'} eq 'onoff') { + $result .= &Apache::edit::select_or_text_arg + ($description,$attr,['on','off'],$token); } $result .= '
'; } @@ -836,81 +1343,107 @@ sub edit_attributes { ## ## ################################################################### -#------------------------------------------------ insert_xxxxxxx -sub insert_plot { +sub insert_gnuplot { my $result = ''; # plot attributes - $result .= "{'default'}\"\n"; - } - $result .= ">\n"; - # Add the components - $result .= &insert_key(); - $result .= &insert_axis(); - $result .= &insert_title(); - $result .= &insert_xlabel(); - $result .= &insert_ylabel(); + $result .= "\n{'default'}\""; + } + $result .= ">"; + # Add the components (most are commented out for simplicity) + # $result .= &insert_key(); + # $result .= &insert_axis(); + # $result .= &insert_title(); + # $result .= &insert_xlabel(); + # $result .= &insert_ylabel(); $result .= &insert_curve(); - # close up the - $result .= "\n"; + # close up the + $result .= "\n"; + return $result; +} + +sub insert_tics { + my $result; + $result .= &insert_xtics() . &insert_ytics; + return $result; +} + +sub insert_xtics { + my $result; + $result .= "\n {'default'}\" "; + } + $result .= "/>"; + return $result; +} + +sub insert_ytics { + my $result; + $result .= "\n {'default'}\" "; + } + $result .= "/>"; return $result; } sub insert_key { my $result; - $result .= " {'default'}\"\n"; + $result .= "\n $attr=\"$key_defaults{$attr}->{'default'}\""; } - $result .= " />\n"; + $result .= " />"; return $result; } sub insert_axis{ my $result; - $result .= ' {'default'}\"\n"; + $result .= "\n $attr=\"$axis_defaults{$attr}->{'default'}\""; } - $result .= " />\n"; + $result .= " />"; return $result; } -sub insert_title { return " \n"; } -sub insert_xlabel { return " \n"; } -sub insert_ylabel { return " \n"; } +sub insert_title { return "\n "; } +sub insert_xlabel { return "\n "; } +sub insert_ylabel { return "\n "; } sub insert_label { my $result; - $result .= ' \n"; + $result .= ">"; return $result; } sub insert_curve { my $result; - $result .= ' {'default'}."\""; } - $result .= " >\n"; + $result .= " >"; + $result .= &insert_data().&insert_data()."\n "; } sub insert_function { my $result; - $result .= "\n"; + $result .= "\n "; return $result; } sub insert_data { my $result; - $result .= " \n"; + $result .= "\n "; return $result; } 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.