From 482267b8af66e677107daefc66f08365a9132106 Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Thu, 19 Feb 2009 18:32:57 +0000 Subject: [PATCH 01/15] check point --- lib/WebGUI/Asset/File.pm | 6 +- lib/WebGUI/Asset/File/Image.pm | 103 +++++++++++++++++++++++++ lib/WebGUI/Storage.pm | 72 +++++++++++++++++ lib/WebGUI/i18n/English/Asset_Image.pm | 30 +++++++ 4 files changed, 209 insertions(+), 2 deletions(-) diff --git a/lib/WebGUI/Asset/File.pm b/lib/WebGUI/Asset/File.pm index 1683a6df6..cefaa32ab 100644 --- a/lib/WebGUI/Asset/File.pm +++ b/lib/WebGUI/Asset/File.pm @@ -245,11 +245,13 @@ sub getEditFormUploadControl { return $html; } - #------------------------------------------------------------------- sub getFileUrl { my $self = shift; #return $self->get("url"); + if (-f $self->getStorageLocation->getPath('crop-' . $self->get("filename"))) { + return $self->getStorageLocation->getUrl('crop-' . $self->get("filename")); + } return $self->getStorageLocation->getUrl($self->get("filename")); } @@ -562,7 +564,7 @@ sub www_edit { sub www_view { my $self = shift; return $self->session->privilege->noAccess() unless $self->canView; - + # Check to make sure it's not in the trash or some other weird place if ($self->get("state") ne "published") { my $i18n = WebGUI::International->new($self->session,'Asset_File'); diff --git a/lib/WebGUI/Asset/File/Image.pm b/lib/WebGUI/Asset/File/Image.pm index fa1984e9a..12bc08d9e 100644 --- a/lib/WebGUI/Asset/File/Image.pm +++ b/lib/WebGUI/Asset/File/Image.pm @@ -268,6 +268,7 @@ sub www_edit { return $self->session->privilege->locked() unless $self->canEditIfLocked; my $i18n = WebGUI::International->new($self->session, 'Asset_Image'); $self->getAdminConsole->addSubmenuItem($self->getUrl('func=resize'),$i18n->get("resize image")) if ($self->get("filename")); + $self->getAdminConsole->addSubmenuItem($self->getUrl('func=crop'),$i18n->get("crop image")) if ($self->get("filename")); my $tabform = $self->getEditForm; $tabform->getTab("display")->template( -value=>$self->get("templateId"), @@ -320,6 +321,108 @@ sub www_resize { return $self->getAdminConsole->render($f->print.$image,$i18n->get("resize image")); } +#------------------------------------------------------------------- +# feel free to take over typing +sub www_crop { + my $self = shift; + return $self->session->privilege->insufficient() unless $self->canEdit; + return $self->session->privilege->locked() unless $self->canEditIfLocked; + + if ($self->session->form->process("Width") || $self->session->form->process("Height") + || $self->session->form->process("Top") || $self->session->form->process("Left")) { + my $newSelf = $self->addRevision(); + delete $newSelf->{_storageLocation}; + $newSelf->getStorageLocation->crop( + $newSelf->get("filename"), + $newSelf->session->form->process("Width"), + $newSelf->session->form->process("Height"), + $newSelf->session->form->process("Top"), + $newSelf->session->form->process("Left") + ); + $self = $newSelf; + } + + my $filename = $self->get("filename"); + + ##YUI specific datatable CSS + my ($style, $url) = $self->session->quick(qw(style url)); + + my $crop_js = qq( + + ); + + $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'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/element/element-beta-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/resize/resize-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/imagecropper/imagecropper-beta-min.js'), {type=>'text/javascript'}); + + my $i18n = WebGUI::International->new($self->session,"Asset_Image"); + + $self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image")); + my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl); + $f->hidden( + -name=>"func", + -value=>"crop" + ); + my ($x, $y) = $self->getStorageLocation->getSizeInPixels($filename); + $f->integer( + -label=>$i18n->get('width'), + -hoverHelp=>$i18n->get('new width description'), + -name=>"Width", + -value=>$x, + ); + $f->integer( + -label=>$i18n->get('height'), + -hoverHelp=>$i18n->get('new height description'), + -name=>"Height", + -value=>$y, + ); + $f->integer( + -label=>$i18n->get('top'), + -hoverHelp=>$i18n->get('new width description'), + -name=>"Top", + -value=>$x, + ); + $f->integer( + -label=>$i18n->get('left'), + -hoverHelp=>$i18n->get('new height description'), + -name=>"Left", + -value=>$y, + ); + $f->submit; + + my $image = '
'.$filename.'
'.$crop_js; + + return $self->getAdminConsole->render($f->print.$image,$i18n->get("crop image")); +} + #------------------------------------------------------------------- # Use superclass method for now. sub www_view { diff --git a/lib/WebGUI/Storage.pm b/lib/WebGUI/Storage.pm index 59dcbab2e..aa80690fc 100644 --- a/lib/WebGUI/Storage.pm +++ b/lib/WebGUI/Storage.pm @@ -1054,6 +1054,78 @@ sub renameFile { #------------------------------------------------------------------- +=head2 crop ( filename [, width, height ] ) + +Resizes the specified image by the specified height and width. If either is omitted the iamge will be scaleed proportionately to the non-omitted one. + +=head3 filename + +The name of the file to resize. + +=head3 width + +The new width of the image in pixels. + +=head3 height + +The new height of the image in pixels. + +=head3 x + +The top of the image in pixels. + +=head3 y + +The top of the image in pixels. + +=cut + +# TODO: Make this take a hash reference with width, height, and density keys. + +sub crop { + my $self = shift; + my $filename = shift; + my $width = shift; + my $height = shift; + my $x = shift; + my $y = shift; + unless (defined $filename) { + $self->session->errorHandler->error("Can't resize when you haven't specified a file."); + return 0; + } + unless ($self->isImage($filename)) { + $self->session->errorHandler->error("Can't resize something that's not an image."); + return 0; + } + unless ($width || $height || $x || $y) { + $self->session->errorHandler->error("Can't resize with no resizing parameters."); + return 0; + } + my $image = Image::Magick->new; + my $error = $image->Read($self->getPath($filename)); + if ($error) { + $self->session->errorHandler->error("Couldn't read image for resizing: ".$error); + return 0; + } + + # Next, resize dimensions + if ( $width || $height || $x || $y ) { + $self->session->errorHandler->info( "Resizing $filename to w:$width h:$height x:$x y:$y" ); + $image->Crop( height => $height, width => $width, x => $x, y => $y ); + } + + # Write our changes to disk + $error = $image->Write($self->getPath('crop-'.$filename)); + if ($error) { + $self->session->errorHandler->error("Couldn't resize image: ".$error); + return 0; + } + + return 1; +} + +#------------------------------------------------------------------- + =head2 resize ( filename [, width, height ] ) Resizes the specified image by the specified height and width. If either is omitted the iamge will be scaleed proportionately to the non-omitted one. diff --git a/lib/WebGUI/i18n/English/Asset_Image.pm b/lib/WebGUI/i18n/English/Asset_Image.pm index 026b1529d..376466662 100644 --- a/lib/WebGUI/i18n/English/Asset_Image.pm +++ b/lib/WebGUI/i18n/English/Asset_Image.pm @@ -77,6 +77,12 @@ shown here.|, lastUpdated => 1106765841 }, + 'crop image' => { + message => q|Crop Image|, + context => q|label to crop the image|, + lastUpdated => 1106765841 + }, + 'new width' => { message => q|New Width|, context => q|label to resize the image|, @@ -101,6 +107,30 @@ shown here.|, lastUpdated => 1130538987 }, + 'height' => { + message => q|Height|, + context => q|label to resize the image|, + lastUpdated => 1106765841 + }, + + 'width' => { + message => q|Width|, + context => q|label to resize the image|, + lastUpdated => 1106765841 + }, + + 'top' => { + message => q|Top|, + context => q|label to resize the image|, + lastUpdated => 1106765841 + }, + + 'left' => { + message => q|Left|, + context => q|label to resize the image|, + lastUpdated => 1106765841 + }, + 'image template title' => { message => q|Image Template Variables|, lastUpdated => 1184820779, From 3ff4f161feb7bf4da2f6dedba606159e44121541 Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Sun, 22 Feb 2009 19:45:48 +0000 Subject: [PATCH 02/15] Needed for the crop utility. --- .../build/fonts/imagecropper/assets/sam/imagecropper.css | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 www/extras/yui/build/fonts/imagecropper/assets/sam/imagecropper.css diff --git a/www/extras/yui/build/fonts/imagecropper/assets/sam/imagecropper.css b/www/extras/yui/build/fonts/imagecropper/assets/sam/imagecropper.css new file mode 100644 index 000000000..73d3216f9 --- /dev/null +++ b/www/extras/yui/build/fonts/imagecropper/assets/sam/imagecropper.css @@ -0,0 +1,7 @@ +/* +Copyright (c) 2008, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 2.6.0 +*/ +.yui-crop{position:relative;}.yui-crop .yui-crop-mask{position:absolute;top:0;left:0;height:100%;width:100%;}.yui-crop .yui-resize{position:absolute;top:10px;left:10px;border:0;}.yui-crop .yui-crop-resize-mask{position:absolute;top:0;left:0;height:100%;width:100%;background-position:-10px -10px;overflow:hidden;}.yui-skin-sam .yui-crop .yui-crop-mask{background-color:#000;opacity:.5;filter:alpha(opacity=50);}.yui-skin-sam .yui-crop .yui-resize{border:1px dashed #fff;} From 2bbd1c8610d6c7bf067660ca72653b10c88674c6 Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Sun, 22 Feb 2009 20:40:36 +0000 Subject: [PATCH 03/15] First try at resize of an image. --- lib/WebGUI/Asset/File/Image.pm | 54 ++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/WebGUI/Asset/File/Image.pm b/lib/WebGUI/Asset/File/Image.pm index 12bc08d9e..8a4ea79f1 100644 --- a/lib/WebGUI/Asset/File/Image.pm +++ b/lib/WebGUI/Asset/File/Image.pm @@ -291,6 +291,57 @@ sub www_resize { $newSelf->setSize($newSelf->getStorageLocation->getFileSize($newSelf->get("filename"))); $self = $newSelf; } + + my ($x, $y) = $self->getStorageLocation->getSizeInPixels($self->get("filename")); + + ##YUI specific datatable CSS + my ($style, $url) = $self->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/build/resize/assets/skins/sam/resize.css'), {rel=>'stylesheet', type=>'text/css'}); + $style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/element/element-beta-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/resize/resize-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/animation/animation-min.js'), {type=>'text/javascript'}); + + my $resize_js = qq( + + ); + my $i18n = WebGUI::International->new($self->session,"Asset_Image"); $self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image")); my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl); @@ -298,7 +349,6 @@ sub www_resize { -name=>"func", -value=>"resize" ); - my ($x, $y) = $self->getStorageLocation->getSizeInPixels($self->get("filename")); $f->readOnly( -label=>$i18n->get('image size'), -hoverHelp=>$i18n->get('image size description'), @@ -317,7 +367,7 @@ sub www_resize { -value=>$y, ); $f->submit; - my $image = '
'.$self->get(
'; + my $image = '
'.$self->get(
'.$resize_js; return $self->getAdminConsole->render($f->print.$image,$i18n->get("resize image")); } From 3e5c9d04ae0b190f19fde47be65603e0e9daeaa7 Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Thu, 26 Feb 2009 00:02:07 +0000 Subject: [PATCH 04/15] Another checkpoint. --- lib/WebGUI/Asset/File.pm | 4 +- lib/WebGUI/Asset/File/Image.pm | 120 ++++++++++++++++++++++++- lib/WebGUI/Storage.pm | 50 ++++++++++- lib/WebGUI/i18n/English/Asset_Image.pm | 18 ++++ 4 files changed, 184 insertions(+), 8 deletions(-) diff --git a/lib/WebGUI/Asset/File.pm b/lib/WebGUI/Asset/File.pm index cefaa32ab..56a286e04 100644 --- a/lib/WebGUI/Asset/File.pm +++ b/lib/WebGUI/Asset/File.pm @@ -249,9 +249,6 @@ sub getEditFormUploadControl { sub getFileUrl { my $self = shift; #return $self->get("url"); - if (-f $self->getStorageLocation->getPath('crop-' . $self->get("filename"))) { - return $self->getStorageLocation->getUrl('crop-' . $self->get("filename")); - } return $self->getStorageLocation->getUrl($self->get("filename")); } @@ -561,6 +558,7 @@ sub www_edit { #------------------------------------------------------------------- + sub www_view { my $self = shift; return $self->session->privilege->noAccess() unless $self->canView; diff --git a/lib/WebGUI/Asset/File/Image.pm b/lib/WebGUI/Asset/File/Image.pm index 8a4ea79f1..ccb1784dc 100644 --- a/lib/WebGUI/Asset/File/Image.pm +++ b/lib/WebGUI/Asset/File/Image.pm @@ -268,7 +268,9 @@ sub www_edit { return $self->session->privilege->locked() unless $self->canEditIfLocked; my $i18n = WebGUI::International->new($self->session, 'Asset_Image'); $self->getAdminConsole->addSubmenuItem($self->getUrl('func=resize'),$i18n->get("resize image")) if ($self->get("filename")); + $self->getAdminConsole->addSubmenuItem($self->getUrl('func=rotate'),$i18n->get("rotate image")) if ($self->get("filename")); $self->getAdminConsole->addSubmenuItem($self->getUrl('func=crop'),$i18n->get("crop image")) if ($self->get("filename")); + $self->getAdminConsole->addSubmenuItem($self->getUrl('func=undo'),$i18n->get("undo image")) if ($self->get("filename")); my $tabform = $self->getEditForm; $tabform->getTab("display")->template( -value=>$self->get("templateId"), @@ -279,6 +281,111 @@ sub www_edit { return $self->getAdminConsole->render($tabform->print,$i18n->get("edit image")); } +#------------------------------------------------------------------- +sub www_undo { + my $self = shift; + my $previous = (@{$self->getRevisions()})[-2]; + if ($previous) { + $self = $self->purgeRevision(); + $self = $previous; + $self->generateThumbnail; + } + return $self->www_edit(); +} + +#------------------------------------------------------------------- +sub www_rotate { + my $self = shift; + return $self->session->privilege->insufficient() unless $self->canEdit; + return $self->session->privilege->locked() unless $self->canEditIfLocked; + warn ($self->session->form->process("degree")); + if (defined $self->session->form->process("degree")) { + my $newSelf = $self->addRevision(); + delete $newSelf->{_storageLocation}; + $newSelf->getStorageLocation->rotate($newSelf->get("filename"),$newSelf->session->form->process("degree")); + $newSelf->setSize($newSelf->getStorageLocation->getFileSize($newSelf->get("filename"))); + $self = $newSelf; + $self->generateThumbnail; + } + + my ($x, $y) = $self->getStorageLocation->getSizeInPixels($self->get("filename")); + + ##YUI specific datatable CSS + my ($style, $url) = $self->session->quick(qw(style url)); + + my $img_name = $self->getStorageLocation->getUrl($self->get("filename")); + my $img_file = $self->get("filename"); + my $rotate_js = qq( + + + + ); + my $image = qq(
$rotate_js
); + + my $i18n = WebGUI::International->new($self->session,"Asset_Image"); + $self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image")); + my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl); + $f->hidden( + -name=>"func", + -value=>"rotate" + ); + $f->hidden( + -name=>"degree", + -value=>0 + ); + $f->readOnly( + -value=>$i18n->get('rotate image label'), + -hoverHelp=>$i18n->get('rotate image description'), + ); + $f->submit; + return $self->getAdminConsole->render($f->print.$image,$i18n->get("rotate image")); +} + #------------------------------------------------------------------- sub www_resize { my $self = shift; @@ -290,6 +397,7 @@ sub www_resize { $newSelf->getStorageLocation->resize($newSelf->get("filename"),$newSelf->session->form->process("newWidth"),$newSelf->session->form->process("newHeight")); $newSelf->setSize($newSelf->getStorageLocation->getFileSize($newSelf->get("filename"))); $self = $newSelf; + $self->generateThumbnail; } my ($x, $y) = $self->getStorageLocation->getSizeInPixels($self->get("filename")); @@ -308,7 +416,6 @@ sub www_resize { my $resize_js = qq( + ); + + my $crop_js = qq( + + ); + + for (my $i = 0; $i < $#pieces; $i += 3) { + my $top_left = $pieces[$i]; + my $width_height = $pieces[$i + 1]; + my $note = $pieces[$i + 2]; + + $hotspots .= qq( + dd#Def_${i} { $top_left } + dd#Def_$i a{ position: absolute; $width_height; text-decoration: none; border: 1px solid #FFFCE6; background: transparent url(/www/extras/annotate/note.png) repeat; } + dd#Def_$i a span{ display: none; } + dd#Def_$i a:hover{ background: transparent url(/www/extras/annotate/hover.png) repeat; border: 1px solid #BCBCBC; } + dd#Def_$i a:hover span{ + display: block; + text-indent: 0; + vertical-align: top; + color: #000; + background-color: #F4F4F4; + font-weight: bold; + position: absolute; + border: 1px solid #BCBCBC; + bottom: 100%; + margin: 0; + padding: 5px; + width: 75%; + } + ); + + $notes .= qq( +
$note
+ ); + + push(@checkboxes, $f->checkbox( + -label=>$i18n->get('delete') . " '$note'", + -checked=>0, + -name=>"delAnnotate$i", + -value=>"1" + ) + ); + $f->hidden( + -name=>"annotates", + -value=>"$i" + ); + } + + my $imageMap = qq( +
+
+ + + $notes +
+
+ ); + + my $imageCss = qq( + + ); + $self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image")); + $f->hidden( + -name=>"func", + -value=>"annotate" + ); + $f->text( + -label=>$i18n->get('annotate image'), + -value=>'', + -hoverHelp=>$i18n->get('annotate image description'), + -name=>'annotate_text' + ); + $f->integer( + -label=>$i18n->get('top'), + -name=>"annotate_top", + -value=>, + ); + $f->integer( + -label=>$i18n->get('left'), + -name=>"annotate_left", + -value=>, + ); + $f->integer( + -label=>$i18n->get('width'), + -name=>"annotate_width", + -value=>, + ); + $f->integer( + -label=>$i18n->get('height'), + -name=>"annotate_height", + -value=>, + ); + $f->submit; + return $self->getAdminConsole->render($f->print."$mouseCoord_js\n$crop_js\n$imageCss\n$image\n$imageMap",$i18n->get("annotate image")); +} + #------------------------------------------------------------------- sub www_rotate { my $self = shift; return $self->session->privilege->insufficient() unless $self->canEdit; return $self->session->privilege->locked() unless $self->canEditIfLocked; - warn ($self->session->form->process("degree")); if (defined $self->session->form->process("degree")) { my $newSelf = $self->addRevision(); delete $newSelf->{_storageLocation}; @@ -428,6 +683,7 @@ sub www_resize { ghost: true, status: true, draggable: false, + ratio: true, animate: true, animateDuration: .75, animateEasing: YAHOO.util.Easing.backBoth diff --git a/lib/WebGUI/Storage.pm b/lib/WebGUI/Storage.pm index 88c982944..f588ad5eb 100644 --- a/lib/WebGUI/Storage.pm +++ b/lib/WebGUI/Storage.pm @@ -678,6 +678,32 @@ sub generateThumbnail { #------------------------------------------------------------------- +=head2 getSize ( filename ) + +Returns width and height of image. + +=head3 filename + +The file to generate a thumbnail for. + +=cut + +sub getSize { + my $self = shift; + my $filename = shift; + my $image = Image::Magick->new; + my $error = $image->Read($self->getPath($filename)); + if ($error) { + $self->session->errorHandler->error("Couldn't read image for size reading: ".$error); + return 0; + } + my ($x, $y) = $image->Get('width','height'); + + return($x, $y); +} + +#------------------------------------------------------------------- + =head2 getErrorCount ( ) Returns the number of errors that have been generated on this object instance. @@ -1126,6 +1152,61 @@ sub crop { #------------------------------------------------------------------- +=head2 annotate ( filename [ text ] ) + +Adds annotation text to the image. + +=head3 filename + +The name of the file to annotate. + +=head3 text + +Text to add. + +=cut + +sub annotate { + my $self = shift; + my $filename = shift; + my $form = shift; + warn("there"); + unless (defined $filename) { + $self->session->errorHandler->error("Can't rotate when you haven't specified a file."); + return 0; + } + unless ($self->isImage($filename)) { + $self->session->errorHandler->error("Can't rotate something that's not an image."); + return 0; + } + warn("there"); + # form->process("degree") + my $annotate_text = $form->process("annotate_text"); + my $annotate_top = $form->process("annotate_top"); + my $annotate_left = $form->process("annotate_left"); + my $annotate_width = $form->process("annotate_width"); + my $annotate_height = $form->process("annotate_height"); + warn("there"); + unless ($annotate_text) { + $self->session->errorHandler->error("Can't annotate with no text."); + return 0; + } + warn("there"); + + my $imageAsset = $self->session->db->getRow("ImageAsset","assetId",$self->getId); + if ($imageAsset->{annotations} =~ /\n/) { + $imageAsset->{annotations} .= "\n"; + } + warn("there"); + $imageAsset->{annotations} .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n$annotate_text"; + $self->{_data}{annotations} = $self->{_data}; + $self->session->db->setRow("ImageAsset","assetId",$self->{_data}); + + return 1; +} + +#------------------------------------------------------------------- + =head2 rotate ( filename [ degrees ] ) Rotates the image by the specified degrees. diff --git a/lib/WebGUI/i18n/English/Asset_Image.pm b/lib/WebGUI/i18n/English/Asset_Image.pm index aece1fecd..ab39f38d0 100644 --- a/lib/WebGUI/i18n/English/Asset_Image.pm +++ b/lib/WebGUI/i18n/English/Asset_Image.pm @@ -77,6 +77,18 @@ shown here.|, lastUpdated => 1106765841 }, + 'annotate image' => { + message => q|Annotate Image|, + context => q|label to annotate the image|, + lastUpdated => 1106765841 + }, + + 'annotate image description' => { + message => q|Text Around the Image|, + context => q|label to annotate the image|, + lastUpdated => 1106765841 + }, + 'rotate image' => { message => q|Rotate Image|, context => q|label to rotate the image|, @@ -125,6 +137,12 @@ shown here.|, lastUpdated => 1106765841 }, + 'delete' => { + message => q|Delete|, + context => q|label to delete annotation|, + lastUpdated => 1106765841 + }, + 'height' => { message => q|Height|, context => q|label to resize the image|, From c7db6abab0580eddeb24e33e6ff3ee57973c3185 Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Tue, 3 Mar 2009 14:56:55 +0000 Subject: [PATCH 06/15] checkpoint --- lib/WebGUI/Storage.pm | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/WebGUI/Storage.pm b/lib/WebGUI/Storage.pm index f588ad5eb..74af175fc 100644 --- a/lib/WebGUI/Storage.pm +++ b/lib/WebGUI/Storage.pm @@ -1181,10 +1181,10 @@ sub annotate { } warn("there"); # form->process("degree") - my $annotate_text = $form->process("annotate_text"); - my $annotate_top = $form->process("annotate_top"); - my $annotate_left = $form->process("annotate_left"); - my $annotate_width = $form->process("annotate_width"); + my $annotate_text = $form->process("annotate_text"); + my $annotate_top = $form->process("annotate_top"); + my $annotate_left = $form->process("annotate_left"); + my $annotate_width = $form->process("annotate_width"); my $annotate_height = $form->process("annotate_height"); warn("there"); unless ($annotate_text) { @@ -1197,11 +1197,16 @@ sub annotate { if ($imageAsset->{annotations} =~ /\n/) { $imageAsset->{annotations} .= "\n"; } - warn("there"); $imageAsset->{annotations} .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n$annotate_text"; - $self->{_data}{annotations} = $self->{_data}; + warn("there: $imageAsset->{annotations}"); + $self->{_data}{annotations} = $imageAsset->{annotations}; + warn("there: $self->{_data}{annotations}"); $self->session->db->setRow("ImageAsset","assetId",$self->{_data}); + foreach my $k (sort keys %{ $self->{_data} }) { + warn("$k => $$self{_data}{$k}"); + } + return 1; } From 8761848ab3ea8b9613f375ad78d9a8d8f531c227 Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Thu, 5 Mar 2009 00:49:35 +0000 Subject: [PATCH 07/15] checkpoint --- lib/WebGUI/Asset/File/Image.pm | 188 ++++++++------------------------- 1 file changed, 45 insertions(+), 143 deletions(-) diff --git a/lib/WebGUI/Asset/File/Image.pm b/lib/WebGUI/Asset/File/Image.pm index bf3e9bfd7..180eae2ba 100644 --- a/lib/WebGUI/Asset/File/Image.pm +++ b/lib/WebGUI/Asset/File/Image.pm @@ -319,6 +319,13 @@ sub www_undo { } #------------------------------------------------------------------- + +# +# 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. +# + sub www_annotate { my $self = shift; return $self->session->privilege->insufficient() unless $self->canEdit; @@ -339,126 +346,60 @@ sub www_annotate { my ($style, $url) = $self->session->quick(qw(style url)); # http://www.kryogenix.org/code/browser/annimg/annimg.html (creative commons) - $style->setLink($url->extras('annotate/imageMap.css'), {rel=>'stylesheet', type=>'text/css'}); + # $style->setLink($url->extras('annotate/imageMap.css'), {rel=>'stylesheet', type=>'text/css'}); my $imageAsset = $self->session->db->getRow("ImageAsset","assetId",$self->getId); - warn($imageAsset->{annotations}); + warn("annotations: " . $self->{annotations}); my @pieces = split(/\n/, $imageAsset->{annotations}); # my ($top_left, $width_height, $note) = split(/\n/, $imageAsset->{annotations}); - my $imageLoc = $self->getStorageLocation->getUrl($self->get("filename")); - my $image = '
'.$self->get(
'; + my $image = '
'.$self->get(
'; my ($width, $height) = $self->getStorageLocation->getSize($self->get("filename")); - my $hotspots = ""; - my $notes = ""; my @checkboxes = (); my $i18n = WebGUI::International->new($self->session,"Asset_Image"); my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl); - my $mouseCoord_js = qq( - - ); - - my $crop_js = qq( - - ); + my $hotspots = ''; + my $domMe = ''; for (my $i = 0; $i < $#pieces; $i += 3) { my $top_left = $pieces[$i]; my $width_height = $pieces[$i + 1]; my $note = $pieces[$i + 2]; - $hotspots .= qq( - dd#Def_${i} { $top_left } - dd#Def_$i a{ position: absolute; $width_height; text-decoration: none; border: 1px solid #FFFCE6; background: transparent url(/www/extras/annotate/note.png) repeat; } - dd#Def_$i a span{ display: none; } - dd#Def_$i a:hover{ background: transparent url(/www/extras/annotate/hover.png) repeat; border: 1px solid #BCBCBC; } - dd#Def_$i a:hover span{ - display: block; - text-indent: 0; - vertical-align: top; - color: #000; - background-color: #F4F4F4; - font-weight: bold; - position: absolute; - border: 1px solid #BCBCBC; - bottom: 100%; - margin: 0; - padding: 5px; - width: 75%; - } - ); + $hotspots .= qq( + + + ); + + $domMe .= qq( + + ); - $notes .= qq( -
$note
- ); push(@checkboxes, $f->checkbox( -label=>$i18n->get('delete') . " '$note'", @@ -471,55 +412,16 @@ sub www_annotate { -name=>"annotates", -value=>"$i" ); + + # last; } - my $imageMap = qq( -
-
- - - $notes -
-
- ); - - my $imageCss = qq( - - ); $self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image")); $f->hidden( -name=>"func", -value=>"annotate" ); - $f->text( + $f->text( -label=>$i18n->get('annotate image'), -value=>'', -hoverHelp=>$i18n->get('annotate image description'), @@ -546,7 +448,7 @@ sub www_annotate { -value=>, ); $f->submit; - return $self->getAdminConsole->render($f->print."$mouseCoord_js\n$crop_js\n$imageCss\n$image\n$imageMap",$i18n->get("annotate image")); + return $self->getAdminConsole->render($f->print."$hotspots$image$domMe",$i18n->get("annotate image")); } #------------------------------------------------------------------- From 6acbdc063a51856cf264819b7dd8614957c8407e Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Tue, 17 Mar 2009 20:45:25 +0000 Subject: [PATCH 08/15] Checkpoint --- lib/WebGUI/Asset/File/Image.pm | 76 +++++++++++++++++++---- lib/WebGUI/Asset/Wobject/Collaboration.pm | 3 + lib/WebGUI/Storage.pm | 9 +-- lib/WebGUI/i18n/English/Asset_Image.pm | 6 ++ 4 files changed, 77 insertions(+), 17 deletions(-) diff --git a/lib/WebGUI/Asset/File/Image.pm b/lib/WebGUI/Asset/File/Image.pm index 180eae2ba..5df71ac9b 100644 --- a/lib/WebGUI/Asset/File/Image.pm +++ b/lib/WebGUI/Asset/File/Image.pm @@ -348,13 +348,60 @@ sub www_annotate { # http://www.kryogenix.org/code/browser/annimg/annimg.html (creative commons) # $style->setLink($url->extras('annotate/imageMap.css'), {rel=>'stylesheet', type=>'text/css'}); + $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'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/element/element-beta-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/resize/resize-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/imagecropper/imagecropper-beta-min.js'), {type=>'text/javascript'}); + my $imageAsset = $self->session->db->getRow("ImageAsset","assetId",$self->getId); warn("annotations: " . $self->{annotations}); my @pieces = split(/\n/, $imageAsset->{annotations}); # my ($top_left, $width_height, $note) = split(/\n/, $imageAsset->{annotations}); - my $image = '
'.$self->get(
'; + my $crop_js = qq( + + ); + my $image = '
'.$self->get(
'; + # my $image = '
'.$self->get(
'; my ($width, $height) = $self->getStorageLocation->getSize($self->get("filename")); @@ -370,29 +417,29 @@ sub www_annotate { my $width_height = $pieces[$i + 1]; my $note = $pieces[$i + 2]; - $hotspots .= qq( - - - ); + # next if 3 == $i; $domMe .= qq( + + + + + - ); my $image = '
'.$self->get(
'; - # my $image = '
'.$self->get(
'; my ($width, $height) = $self->getStorageLocation->getSize($self->get("filename")); @@ -409,60 +385,6 @@ sub www_annotate { my $i18n = WebGUI::International->new($self->session,"Asset_Image"); my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl); - my $hotspots = ''; - my $domMe = ''; - - for (my $i = 0; $i < $#pieces; $i += 3) { - my $top_left = $pieces[$i]; - my $width_height = $pieces[$i + 1]; - my $note = $pieces[$i + 2]; - - # next if 3 == $i; - - $domMe .= qq( - - - - - - - ); - - - push(@checkboxes, $f->checkbox( - -label=>$i18n->get('delete') . " '$note'", - -checked=>0, - -name=>"delAnnotate$i", - -value=>"1" - ) - ); - $f->hidden( - -name=>"annotates", - -value=>"$i" - ); - - # last; - } - $self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image")); $f->hidden( -name=>"func", @@ -499,9 +421,116 @@ sub www_annotate { -extras=>'onclick="switchState();"', ); $f->submit; + my ($crop_js, $domMe) = $self->annotate_js(); return $self->getAdminConsole->render($f->print."$image$crop_js$domMe",$i18n->get("annotate image")); } +#------------------------------------------------------------------- +sub annotate_js { + my $self = shift; + my $opts = shift; + + my @pieces = split(/\n/, $self->get('annotations')); + + warn("pieces: $#pieces: ". $self->getId()); + return "" if !@pieces && $opts->{just_image}; + + 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; + # warn("i: $i: ", $self->session->form->process("delAnnotate$i")); + } + + my $id = $$opts{just_image} ? $self->getId : "yui_img"; + + my $crop_js = qq( + + ); + + my $hotspots = ''; + my $domMe = ''; + + for (my $i = 0; $i < $#pieces; $i += 3) { + my $top_left = $pieces[$i]; + my $width_height = $pieces[$i + 1]; + my $note = $pieces[$i + 2]; + + if ($top_left =~ /top: (\d+)px; left: (\d+)px;/) { + $top_left = "xy[0]+$1, xy[1]+$2"; + } + + my ($width, $height) = ("", ""); + if ($width_height =~ /width: (\d+)px; height: (\d+)px;/) { + ($width, $height) = ("$1px", "$2px"); + } + + # next if 3 == $i; + + $domMe .= qq( + + + + + + + ); + } + + return($crop_js, $domMe); +} + #------------------------------------------------------------------- sub www_rotate { my $self = shift; @@ -797,7 +826,7 @@ sub www_crop { # Use superclass method for now. sub www_view { my $self = shift; - $self->SUPER::www_view; + return($self->SUPER::www_view); } #sub www_view { diff --git a/lib/WebGUI/Storage.pm b/lib/WebGUI/Storage.pm index f1e6c2b1b..83b9c7f64 100644 --- a/lib/WebGUI/Storage.pm +++ b/lib/WebGUI/Storage.pm @@ -1169,8 +1169,8 @@ Text to add. sub annotate { my $self = shift; my $filename = shift; + my $asset = shift; my $form = shift; - warn("there"); unless (defined $filename) { $self->session->errorHandler->error("Can't rotate when you haven't specified a file."); return 0; @@ -1179,34 +1179,50 @@ sub annotate { $self->session->errorHandler->error("Can't rotate something that's not an image."); return 0; } - warn("there"); - # form->process("degree") + # unless ($annotate_text) { + # $self->session->errorHandler->error("Can't annotate with no text."); + # return 0; + # } + # unless ($annotate_top && $annotate_left && $annotate_width && $annotate_height) { + # $self->session->errorHandler->error("Can't annotate with no dimensions."); + # return 0; + # } + + my $annotate = $asset->get('annotations'); + my $save_annotate = ""; + my @pieces = split(/\n/, $annotate); + for (my $i = 0; $i < $#pieces; $i += 3) { + my $top_left = $pieces[$i]; + my $width_height = $pieces[$i + 1]; + my $note = $pieces[$i + 2]; + + # warn("i: $i: ", $form->process("delAnnotate$i")); + next if $form->process("delAnnotate$i"); + + if ($save_annotate) { + $save_annotate .= "\n"; + } + $save_annotate .= "$top_left\n$width_height\n$note"; + } + my $annotate_text = $form->process("annotate_text"); my $annotate_top = $form->process("annotate_top"); my $annotate_left = $form->process("annotate_left"); my $annotate_width = $form->process("annotate_width"); my $annotate_height = $form->process("annotate_height"); - warn("there"); - unless ($annotate_text) { - $self->session->errorHandler->error("Can't annotate with no text."); - return 0; + # warn(qq(unless ($annotate_top && $annotate_left && $annotate_width && $annotate_height && $annotate_text !~ /^\s*$/))); + if ($annotate_top && $annotate_left && $annotate_width && $annotate_height && $annotate_text !~ /^\s*$/) { + if ($save_annotate) { + $save_annotate .= "\n"; + } + # warn(qq($save_annotate .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n'$annotate_text'")); + $save_annotate .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n$annotate_text"; } - warn("there"); + # warn($save_annotate); - my $imageAsset = $self->session->db->getRow("ImageAsset","assetId",$self->getId); - if ($imageAsset->{annotations} =~ /\n/) { - $imageAsset->{annotations} .= "\n"; - } - warn("there: $imageAsset->{annotations}"); - $imageAsset->{annotations} .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n$annotate_text"; - warn("there: $imageAsset->{annotations}"); - # $self->{_data}{annotations} = $imageAsset->{annotations}; - # warn("there: $self->{_data}{annotations}"); - # $self->session->db->setRow("ImageAsset","assetId",$self->{_data}); - - foreach my $k (sort keys %{ $self->{_data} }) { - # warn("$k => $$self{_data}{$k}"); - } + $asset->update({ annotations => $save_annotate }); + $save_annotate = $asset->get('annotations'); + # warn($save_annotate); return 1; } From 689a8b3e2311204c8924c244aa616efbfc1a7876 Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Sun, 22 Mar 2009 23:56:32 +0000 Subject: [PATCH 10/15] checkpoint --- lib/WebGUI/Asset/File/Image.pm | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/WebGUI/Asset/File/Image.pm b/lib/WebGUI/Asset/File/Image.pm index 63c396ae8..265d77b8d 100644 --- a/lib/WebGUI/Asset/File/Image.pm +++ b/lib/WebGUI/Asset/File/Image.pm @@ -245,15 +245,10 @@ sub view { if ($crop_js) { my ($style, $url) = $self->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->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'), {type=>'text/javascript'}); - $style->setScript($url->extras('yui/build/element/element-beta-min.js'), {type=>'text/javascript'}); - $style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'), {type=>'text/javascript'}); - $style->setScript($url->extras('yui/build/resize/resize-min.js'), {type=>'text/javascript'}); - $style->setScript($url->extras('yui/build/imagecropper/imagecropper-beta-min.js'), {type=>'text/javascript'}); + $style->setScript($url->extras('yui/build/container/container-min.js'), {type=>'text/javascript'}); } $var{controls} = $self->getToolbar; @@ -262,7 +257,6 @@ sub view { $var{thumbnail} = $self->getThumbnailUrl; $var{annotateJs} = "$crop_js$domMe"; $var{parameters} = sprintf("id=%s", $self->getId()); - warn("annotateJs: $var{annotateJs}"); my $form = $self->session->form; my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate}); if (!$self->session->var->isAdminOn && $self->get("cacheTimeout") > 10) { From cdb5421c3cbf39a5f88737dfceb01b651434d01a Mon Sep 17 00:00:00 2001 From: Brian Medley Date: Mon, 23 Mar 2009 08:41:16 +0000 Subject: [PATCH 11/15] Seems to be done --- lib/WebGUI/Asset/File/Image.pm | 83 +++++++++------------------------- 1 file changed, 22 insertions(+), 61 deletions(-) diff --git a/lib/WebGUI/Asset/File/Image.pm b/lib/WebGUI/Asset/File/Image.pm index 265d77b8d..c4fdb43dd 100644 --- a/lib/WebGUI/Asset/File/Image.pm +++ b/lib/WebGUI/Asset/File/Image.pm @@ -493,6 +493,7 @@ sub annotate_js { # next if 3 == $i; + warn('next'); $domMe .= qq(