package WebGUI::Asset::File::Image;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2009 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
use strict;
use WebGUI::Storage;
use WebGUI::HTMLForm;
use WebGUI::Form::Image;
use Moose;
use WebGUI::Definition::Asset;
extends 'WebGUI::Asset::File';
define assetName => ['assetName', 'Asset_Image'];
define tableName => 'ImageAsset';
define icon => 'image.gif';
property thumbnailSize => (
label => ['thumbnail size', 'Asset_Image'],
hoverHelp => ['Thumbnail size description', 'Asset_Image'],
fieldType => 'integer',
builder => '_default_thumbnailSize',
lazy => 1,
);
sub _default_thumbnailSize {
my $self = shift;
return $self->session->setting->get('thumbnailSize');
}
property parameters => (
label => ['parameters', 'Asset_Image'],
hoverHelp => ['Parameters description', 'Asset_Image'],
fieldType => 'textarea',
default => 'style="border-style:none;"',
);
property annotations => (
fieldType => 'hidden',
noFormPost => 1,
default => '',
);
=head1 NAME
Package WebGUI::Asset::File::Image
=head1 DESCRIPTION
Extends WebGUI::Asset::File to add image manipulation operations.
=head1 SYNOPSIS
use WebGUI::Asset::File::Image;
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 applyConstraints ( options )
Things that are done after a new file is attached.
=head3 options
A hash reference of optional parameters.
=head4 maxImageSize
An integer (in pixels) representing the longest edge the image may have.
=head4 thumbnailSize
An integer (in pixels) representing the longest edge a thumbnail may have.
=cut
override applyConstraints => sub {
my $self = shift;
my $options = shift;
super();
my $maxImageSize = $options->{maxImageSize} || $self->session->setting->get("maxImageSize");
my $thumbnailSize = $options->{thumbnailSize} || $self->thumbnailSize || $self->session->setting->get("thumbnailSize");
my $storage = $self->getStorageLocation;
my $file = $self->filename;
$storage->adjustMaxImageSize($file, $maxImageSize);
$self->generateThumbnail($thumbnailSize);
$self->setSize;
};
#-------------------------------------------------------------------
=head2 generateThumbnail ( [ thumbnailSize ] )
Generates a thumbnail for this image.
=head3 thumbnailSize
A size, in pixels, of the maximum height or width of a thumbnail. If specified this will change the thumbnail size of the image. If unspecified the thumbnail size set in the properties of this asset will be used.
=cut
sub generateThumbnail {
my $self = shift;
my $thumbnailSize = shift;
if (defined $thumbnailSize) {
$self->update({thumbnailSize=>$thumbnailSize});
}
$self->getStorageLocation->generateThumbnail($self->filename,$self->thumbnailSize);
}
#-------------------------------------------------------------------
=head2 getEditForm ( )
Returns the TabForm object that will be used in generating the edit page for this asset.
=cut
override getEditForm => sub {
my $self = shift;
my $f = super();
my $i18n = WebGUI::International->new($self->session,"Asset_Image");
# Fix templateId to use correct namespace and default
my $template = $f->getTab('display')->getField('templateId');
$template->set( hoverHelp => $i18n->get('image template description') );
$template->set( namespace => 'ImageAsset' );
$template->set( defaultValue => 'PBtmpl0000000000000088' );
# Add the fields defined locally and apply any overrides from the config file
my $overrides = $self->session->config->get("assets/".$self->className);
if ($self->filename ne "") {
my ($x, $y) = $self->getStorageLocation->getSizeInPixels($self->filename);
$f->getTab('properties')->addField( "ReadOnly",
name => 'thumbnail',
label => $i18n->get('thumbnail'),
hoverHelp => $i18n->get('Thumbnail description'),
value => '',
( $overrides->{thumbnail} ? %{$overrides->{thumbnail}} : () ),
);
$f->getTab('properties')->addField( "ReadOnly",
name => 'imageSize',
label => $i18n->get('image size'),
value => $x.' x '.$y,
( $overrides->{imageSize} ? %{$overrides->{imageSize}} : () ),
);
}
return $f;
};
#-------------------------------------------------------------------
=head2 getThumbnailUrl
Returns the URL to the thumbnail of the image stored in the Asset.
=cut
sub getThumbnailUrl {
my $self = shift;
return $self->getStorageLocation->getThumbnailUrl($self->filename);
}
#-------------------------------------------------------------------
=head2 getToolbar ( )
Returns a toolbar with a set of icons that hyperlink to functions that delete, edit, promote, demote, cut, and copy.
=cut
override getToolbar => sub {
my $self = shift;
return undef if ($self->getToolbarState);
return super();
};
#-------------------------------------------------------------------
=head2 view
Renders this asset.
=cut
sub view {
my $self = shift;
my $session = $self->session;
my $cache = $session->cache;
my $cacheKey = $self->getWwwCacheKey('view');
if (!$session->var->isAdminOn && $self->cacheTimeout > 10) {
my $out = $cache->get( $cacheKey );
return $out if $out;
}
my %var = %{$self->get};
my ($crop_js, $domMe) = $self->annotate_js({ just_image => 1 });
if ($crop_js) {
my ($style, $url) = $session->quick(qw(style url));
$style->setLink($url->extras('yui/build/fonts/fonts-min.css'), {rel=>'stylesheet', type=>'text/css'});
$style->setLink($url->extras('yui/container/assets/container.css'), {rel=>'stylesheet', type=>'text/css'});
$style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'));
$style->setScript($url->extras('yui/build/container/container-min.js'));
}
$var{controls} = $self->getToolbar;
$var{fileUrl} = $self->getFileUrl;
$var{fileIcon} = $self->getFileIconUrl;
$var{thumbnail} = $self->getThumbnailUrl;
$var{annotateJs} = $crop_js . $domMe;
$var{parameters} .= sprintf(q{ id="%s"}, $self->getId);
my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate});
if (!$session->var->isAdminOn && $self->cacheTimeout > 10) {
$cache->set( $cacheKey, $out, $self->get("cacheTimeout") );
}
return $out;
}
#----------------------------------------------------------------------------
=head2 setFile ( filename )
Extend the superclass setFile to automatically generate thumbnails.
=cut
override setFile => sub {
my $self = shift;
super();
$self->generateThumbnail;
};
#-------------------------------------------------------------------
=head2 www_edit
Override the master class to add image editing controls to the edit screen.
Also adds the Image template form variable.
=cut
sub www_edit {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless $self->canEdit;
return $session->privilege->locked() unless $self->canEditIfLocked;
my $i18n = WebGUI::International->new($session, 'Asset_Image');
if ($self->filename) {
my $ac = $self->getAdminConsole;
# These are asset helpers now, not functions
$ac->addSubmenuItem($self->getUrl('func=resize'), $i18n->get("resize image"));
$ac->addSubmenuItem($self->getUrl('func=rotate'), $i18n->get("rotate image"));
$ac->addSubmenuItem($self->getUrl('func=crop'), $i18n->get("crop image"));
$ac->addSubmenuItem($self->getUrl('func=annotate'), $i18n->get("annotate image"));
$ac->addSubmenuItem($self->getUrl('func=undo'), $i18n->get("undo image"));
}
my $tabform = $self->getEditForm;
return $self->getAdminConsole->render($tabform->toHtml,$i18n->get("edit image"));
}
#-------------------------------------------------------------------
=head2 www_undo
Rolls back the last revision of this asset, undoing any work that may
have been done to it.
=cut
sub www_undo {
my $self = shift;
my $previous = (@{$self->getRevisions()})[1];
if ($previous) {
$self = $self->purgeRevision();
$self->generateThumbnail;
}
return $self->www_edit();
}
#-------------------------------------------------------------------
#
# All of the images will have to change to support annotate.
# The revision system doesn't support the blobs, it seems.
# All of the image operations will have to be updated to support annotations.
#
=head2 www_annotate
Allow the user to place some text on their image. This is done via JS and tooltips
=cut
sub www_annotate {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless $self->canEdit;
return $session->privilege->locked() unless $self->canEditIfLocked;
if (1) {
my $newSelf = $self->addRevision();
delete $newSelf->{_storageLocation};
$newSelf->getStorageLocation->annotate($newSelf->filename,$newSelf,$session->form);
$newSelf->setSize($newSelf->getStorageLocation->getFileSize($newSelf->filename));
$self = $newSelf;
$self->generateThumbnail;
WebGUI::VersionTag->autoCommitWorkingIfEnabled($session, { allowComments => 0 });
}
my ($style, $url) = $session->quick(qw(style url));
$style->setLink($url->extras('yui/build/resize/assets/skins/sam/resize.css'), {rel=>'stylesheet', type=>'text/css'});
$style->setLink($url->extras('yui/build/fonts/fonts-min.css'), {rel=>'stylesheet', type=>'text/css'});
$style->setLink($url->extras('yui/build/imagecropper/assets/skins/sam/imagecropper.css'), {rel=>'stylesheet', type=>'text/css'});
$style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'));
$style->setScript($url->extras('yui/build/element/element-min.js'));
$style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'));
$style->setScript($url->extras('yui/build/resize/resize-min.js'));
$style->setScript($url->extras('yui/build/imagecropper/imagecropper-min.js'));
my @pieces = split(/\n/, $self->annotations);
my ($img_null, $tooltip_block, $tooltip_none) = ('', '', '');
for (my $i = 0; $i < $#pieces; $i += 3) {
$img_null .= "YAHOO.img.container.tt$i = null;\n";
$tooltip_block .= "YAHOO.util.Dom.setStyle('tooltip$i', 'display', 'block');\n";
$tooltip_none .= "YAHOO.util.Dom.setStyle('tooltip$i', 'display', 'none');\n";
my $j = $i + 2;
}
my $image = '