PDL-Graphics-Prima
view release on metacpan or search on metacpan
lib/PDL/Graphics/Prima.pm view on Meta::CPAN
# library-specific modules whose functionality I need
use PDL::Graphics::Prima::Axis;
use PDL::Graphics::Prima::DataSet;
# Next: use block-comments to describe the purpose of each method.
######################################
# Usage : ????
# Purpose : ????
# Arguments : ????
# Returns : ????
# Side Effects : none
# Throws : no exceptions
# Comments : none
# See Also : n/a
######################################
# Usage : Not used directly; this is invoked by Prima's inherited
# : constructor.
# Purpose : Sets up a default profile for a graph widget
# Arguments : The (completely uninitialized) object
# Returns : a hashref
# Side Effects : none
# Throws : never
# Comments : none
# See Also : init
sub profile_default {
my %def = %{$_[ 0]-> SUPER::profile_default};
return {
%def,
# default properties follow
# Title basics
title => '',
titleSpace => '1line',
titleFont => { height => '10%height' },
backColor => cl::White,
# default color map
color_map => pal::BlackToWhite,
# replot duration in milliseconds
replotDuration => 30,
# Blank profiles for the axes:
x => {},
y => {},
# Other important and basic settings
selectable => 1,
buffered => 1,
popupItems => default_popup_items(),
};
}
sub default_popup_items
{[
['~Copy' => 'copy_to_clipboard' ],
['P~rint' => 'print' ],
['~Export to' => [
[ '~Image' => 'save_to_image' ],
[ '~Postscript' => 'save_to_ps' ],
[ '~EPS' => 'save_to_eps' ],
[ 'P~DF' => 'save_to_pdf' ],
]],
['~Autoscale' => 'autoscale' ],
['~Properties' => 'set_properties_dialog' ]
]}
######################################
# Usage : Not used directly; this is invoked by Prima's inherited
# : constructor.
# Purpose : Initializes self's data from the profile.
# Arguments : $self, as yet uninitialized
# : a list of key => value pairs corresponding to the list of
# : arguments provided to the constructor, merged with the default
# : profile.
# Returns : A list of key => value pairs suitable for a profile hash.
# Side Effects : none
# Throws : if unable to initialize the x/y axes from their associated
# : constructor hashrefs
# Comments : This has a lot of logic for setting defaults. It might not be
# : a bad idea to refactor some of this out, so that a Plot widget
# : can be reset to a default state.
# See Also : profile_default
sub init {
my $self = shift;
my %profile = $self->SUPER::init(@_);
# Set the title properties
$self->_title($profile{title});
$self->_titleSpace($profile{titleSpace});
$self->_titleFont(%{$profile{titleFont}});
# Set the default save-as data
$self->default_save_dir($profile{default_save_dir});
$self->default_save_format($profile{default_save_format});
# Create the x- and y-axis objects, overriding the owner and axis name
# properties if they are set in the profile.
for ('x', 'y') {
if (eval{$profile{$_}->isa('PDL::Graphics::Prima::Axis')}) {
$self->{$_} = $profile{$_};
$self->{$_}->owner($self);
$self->{$_}->name($_);
}
elsif (ref ($profile{$_}) eq 'HASH') {
$self->{$_} = PDL::Graphics::Prima::Axis->create(
%{$profile{$_}}
, owner => $self
, name => $_
);
}
elsif (not ref($profile{$_})) {
# No ref means scalar; assume it's a label name
$self->{$_} = PDL::Graphics::Prima::Axis->create(
lib/PDL/Graphics/Prima.pm view on Meta::CPAN
sub save_to_postscript {
# Get the filename as an argument, or from the save-as dialog.
my ($self, $filename) = @_;
return defined($filename) ?
$self-> export_to_ps( 'Prima::PS::File', $filename, isEPS => 1 ) :
$self-> save_to_eps;
}
# A routine to save the current plot to a rasterized file:
sub save_to_image { shift->save_to_file }
sub save_to_file {
# Get the filename as an argument or from a save-as dialog.
my ($self, $filename) = @_;
# Get the image
my $image = $self->get_image;
# If they didn't specify a filename, run a dialog to get it. Use
# the specified configuration, if given
unless ($filename) {
my %args;
$args{directory} = $self->{default_save_dir}
if exists $self->{default_save_dir};
my $dlg = Prima::Dialog::ImageSaveDialog-> create(%args);
if ($self->{default_save_format}) {
my $found;
my $i = 0;
my @types = $dlg->filter;
for (my $i = 0; $i < @types; $i++) {
if ($types[$i][0] =~ /$self->{default_save_fileShortType}/) {
$found++;
$dlg->filterIndex($i);
last;
}
}
# Should have already gotten a warning about this...
warn "Preferred image format [$self->{default_save_format}] is not available\n"
if not $found;
}
$dlg->save($image);
$dlg->destroy;
return;
}
# If they specified a filename, simply save it:
$image-> save($filename)
or do {
my $message = "Error generating figure output: $@";
if (defined $::application) {
Prima::MsgBox::message($message, mb::Ok);
carp($message);
}
else {
croak($message);
}
};
}
sub copy_to_clipboard {
my $self = shift;
my $image = $self->get_image;
my $clipboard = $::application->Clipboard;
$clipboard->open;
$clipboard->clear;
$clipboard->image($image);
$clipboard->close;
}
sub print
{
my $self = shift;
my $print_dialog = Prima::Dialog::PrintDialog-> new;
unless ($print_dialog-> execute) {
$print_dialog->destroy;
return;
}
my $ps = $print_dialog-> printer;
$ps->font(height => $self->font->height);
$ps->begin_doc or do {
my $msg = "$@";
Prima::MsgBox::message($msg, mb::Ok);
carp($msg);
};
$self->paint_with_widgets($ps);
$ps->end_doc;
$print_dialog->destroy;
}
# For a change in title, recompute the autoscaling and issue an immediate
# repaint. Replotting is not appropriate here as replotting issues a timer
# event that may not get triggered if the event loop isn't running (i.e.
# we're in the PDL shell without ReadLine integration).
sub on_changetitle {
my $self = shift;
$self->x->update_edges;
$self->y->update_edges;
$self->notify('Paint');
# If running in the PDL shell, clear the event queue so this hits
# immediately
$::application->yield if defined $PERLDL::TERM;
}
# Sets up a timer in self that eventually calls the paint notification:
sub on_replot {
my ($self) = @_;
return if $self->{timer}->get_active;
$self->{timer}->start;
}
# Just like changetitle, but we also need to check for changes to the color
# map's extrema
sub on_changedata {
my $self = shift;
$self->compute_color_map_extrema;
$self->on_changetitle;
}
#################
# Notifications #
#################
# Add a new notification_type for each of the notifications just defined.
lib/PDL/Graphics/Prima.pm view on Meta::CPAN
# This croaks:
$plot->x->max(20);
This is a L<feature of Prima|Prima::Object/bring>. Eventually, when multiple
x- and y-axes are allowed, this will allow you to transparently access them by
name just like you can access the single x- and y-axes by name at the moment.
=head2 dataSets
This is the means by which you add new content to your plot (apart from
placing sub-figures in there, of course). This either sets or returns the
L<collection|PDL::Graphics::Prima::DataSet/DataSet::Collection> of
L<DataSet|PDL::Graphics::Prima::DataSet>s. The
L<DataSet|PDL::Graphics::Prima::DataSet>s are held in a tied
anonymous hash that you directly manipulate. In order to add a new
L<DataSet|PDL::Graphics::Prima::DataSet>, you can simply modify the anonymous
hash in place using standard Perl hash manipulation functions and techniques.
For example:
# Add a new DataSet
$plot->dataSets->{new_data} = ds::Pair(
$x, $y, plotType => ppair::Squares
);
# Remove a DataSet
delete $plot->dataSets->{model};
# Clear the DataSets
%{$plot->dataSets} = ();
Since the hash is actually tied, L<DataSet|PDL::Graphics::Prima::DataSet>s
that you add will be validated as you add them.
=head1 METHODS
PDL::Graphics::Prima provides a number of methods. Most of these focus on
generating images of the plot.
=head2 get_image
Returns a L<Prima::Image> of the plot with same dimensions as the plot widget.
=head2 save_to_postscript
Saves the plot with current axis limits to an encapsulated postscript figure or
to a PDF file. This method takes an optional filename argument. If no filename
is specified, it pops-up a dialog box to ask the user where and under what name
they want to save the figure.
This functionality will likely be merged into save_to_file, though this
method will remain for backwards compatibility.
=head2 save_to_file
Saves the plot to a raster image file. This method
takes an optional filename argument, deducing the format (and applicable
codec) from the filename. If no filename is specified, it creates a dialog
box asking the user where and under what name they want to save the file.
=head2 copy_to_clipboard
Copies the plot with current axis limits as a bitmap image to the clipboard.
The resulting clipboard entry is suitable for pasting into applications that
know how to handle bitmap images such as LibreOffice or gpaint on Linux,
Microsoft Office or Windows Paint on Windows.
=head1 Events
You can send notifications and hook callbacks for the following events:
=head2 ChangeTitle
Called when the title or titleSpace gets changed
=head2 Replot
Called when the widget needs to replot "real soon", but not immediately.
Immediate replot requests should go in the form of "Paint" events.
In order to prevent the system from getting bogged down by too many
paint requests, replotting kicks off a timer that issues the paint requests
after a brief period (defaults to 30 milliseconds).
=head2 ChangeData
Called when the dataSet container changes (not the datasets themselves, but
the whole container).
=head1 DRAWING A PLOT TO AN IMAGE
Most L<methods|PDL::Graphics::Prima/METHODS> that are not properties provide
means for generating images from a plot. Sometimes it is useful to draw a plot
on a pre-formed image. Let's look at the different mechanisms for doing this.
For a point of comparison, if you simply want a L<raster image|Prima::Image/>
object from a plot, you should simply obtain it from the plot object with
the L<get_image|PDL::Graphics::Prima/get_image> method:
my $image = $plot->get_image;
However, what if you already have an L<image object|Prima::Image/> upon which
you want to draw your plot? There are at least two circumstances when you might
want to do this: first if you are creating many raster images from plots and
want to avoid memory re-allocations, and second if you have in image with some
annotations on it already. (Beware the first reason: it is likely a premature
optimization.) To draw the plot on an already-formed image, you can use the
C<paint_with_widgets> method like so:
$some_image->begin_paint;
$some_image->clear;
... other painting here ...
$plot->paint_with_widgets($some_image);
... more painting ...
$some_image->end_paint;
The C<paint_with_widgets> method is the preferred way to
draw a plot onto a pre-existing image. It gives you a bit more control on how
the painting is invoked: for example, it does not clear the canvas for you. But
with the increased control comes increased manual manipulation: you need to set
the image in the paint-enabled state before invoking it, and you need to clear
the canvas before getting started.
There is one more means for rendering a plot on an image, which arises if you
are invoking the L<Paint Event|Prima::Widget/Paint> from an arbitrary widget
( run in 1.733 second using v1.01-cache-2.11-cpan-84e82930d8c )