# +-----------------------------------------------------------------------+ # | pLoader - a Perl photo uploader for Piwigo | # +-----------------------------------------------------------------------+ # | Copyright(C) 2008-2010 Piwigo Team http://piwigo.org | # +-----------------------------------------------------------------------+ # | This program is free software; you can redistribute it and/or modify | # | it under the terms of the GNU General Public License as published by | # | the Free Software Foundation | # | | # | This program is distributed in the hope that it will be useful, but | # | WITHOUT ANY WARRANTY; without even the implied warranty of | # | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | # | General Public License for more details. | # | | # | You should have received a copy of the GNU General Public License | # | along with this program; if not, write to the Free Software | # | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | # | USA. | # +-----------------------------------------------------------------------+ package Uploader::GUI::Frame; use strict; use Carp; use Wx; use Wx::DND; use Wx qw/ wxSP_3DBORDER wxSP_3D wxNO_FULL_REPAINT_ON_RESIZE wxCLIP_CHILDREN wxYES_NO wxYES wxICON_QUESTION wxITEM_NORMAL wxNullBitmap wxID_OK wxDEFAULT_FRAME_STYLE wxVERTICAL wxGROW wxSHAPED wxBITMAP_TYPE_JPEG wxBITMAP_TYPE_GIF wxBITMAP_TYPE_PNG wxBITMAP_TYPE_ANY wxTB_FLAT wxTB_TEXT wxSIZE wxWHITE wxBLACK wxID_CANCEL wxFD_OPEN wxFD_MULTIPLE wxLI_HORIZONTAL wxALIGN_CENTER_VERTICAL wxALIGN_CENTER_HORIZONTAL wxALL wxGROW wxDefaultPosition wxDefaultSize wxTheApp wxIMAGE_LIST_NORMAL wxAUI_NB_TAB_MOVE wxAUI_NB_TAB_SPLIT wxNO_BORDER wxTE_MULTILINE wxTE_READONLY wxITEM_NORMAL wxCLIP_CHILDREN wxBORDER_NONE wxNullBitmap wxTR_MULTIPLE wxTR_EXTENDED wxTR_HIDE_ROOT wxTR_HAS_BUTTONS wxTR_EDIT_LABELS wxMAXIMIZE wxOK wxICON_EXCLAMATION wxICON_INFORMATION WXK_DELETE wxHORIZONTAL wxVERTICAL wxEXPAND /; use base qw/Wx::Frame Class::Accessor::Fast/; use File::Spec; use Wx::Locale qw/:default/; use POSIX qw(ceil floor); require Win32 if($^O =~ /MSWin32/); my @properties = qw/ progressdlg upload_progressdlg imageviewer imageviewer_img tree tree_root treeimglist tree_item_default pwg logwnd oldlogwnd categories imagelist image_preview image_prop_piwigo image_prop_exif image_prop_tags global_settings_panel piwigo_property_list exif_properties global_settings toolbar branding current_imageviewer_index imageviewer_mnu tree_mnu imageviewer_select_multi frameLayout piwigo_tags image_tags piwigo_photo_properties dlg_piwigo_photo_properties piwigo_photo_properties_tags image_preview_refresh imageviewer_refresh imageviewer_item_refresh horizontal_splitter /; __PACKAGE__->mk_accessors( @properties ); use Wx::Perl::TextValidator; use Uploader::GUI::wxImageListCtrl; use Uploader::GUI::wxPropertyListDlg; use Uploader::GUI::wxGlobalSettings; use Uploader::GUI::wxImagePreview; use Uploader::GUI::wxPhotoProperties; use Uploader::GUI::wxImageReuploadDlg; use Uploader::GUI::wxImageProcessingProgressDlg; use Uploader::GUI::wxChoiceFilteredPanel; use utf8; $|=1; my $ID_TREE_CTX_MENU = 20000 ; my $ID_IMAGEVIEWER_CTX_MENU = 20100 ; sub new { my( $class, $params ) = @_; my $self = $class->SUPER::new( undef, -1, $params->{title}, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE ); $self->pwg( $params->{pwg} ); $self->imagelist( $params->{imagelist} ); # callback for GUI refresh : add thumbnail images to the imageviewer control $self->imagelist->SetNewFilesViewerRefreshCallback( sub { $self->SetNewFilesViewerRefresh(@_) } ); # callback for GUI refresh : progress dialog display of thumbnail image being created $self->imagelist->SetNewFilesProgressCallback( sub { $self->SetNewFilesProgress(@_) } ); $self->imagelist->SetNewFilesDisplayEndInfoCallback( sub { $self->SetNewFilesDisplayEndInfo(@_) } ); # callback for GUI refresh : remove thumbnail images from imageviewer control $self->imagelist->UploadImagesViewerCallback( sub { $self->UploadImagesViewerRefresh(@_) } ); $self->imagelist->ReuploadCallback( sub { Uploader::GUI::wxImageReuploadDlg->new( { title => gettext("Photo update management"), properties => { $main::ID_REUPLOAD_ACTION_FILES => { selection=>sub {$self->imagelist->reupload_action_files(@_)}, label=>gettext("What shall we do with files? (thumbnail, resized, high resolution)"), labels=>[ gettext("nothing"), gettext("replace"), ], }, $main::ID_REUPLOAD_ACTION_PROPERTIES => { selection=>sub{$self->imagelist->reupload_action_properties(@_)}, label=>gettext("What shall we do with single value properties?(caption, comment, author, create date)"), labels=>[ gettext("nothing"), gettext("fill if empty (only replace properties currently empty in Piwigo)"), gettext("replace"), ], }, $main::ID_REUPLOAD_ACTION_PROPERTIES_M => { selection=>sub{$self->imagelist->reupload_action_properties_m(@_)}, label=>gettext("What shall we do with multiple values properties? (categories, tags)"), labels=>[ gettext("nothing"), gettext("append (keep existing and add new)"), gettext("replace"), ], }, $main::ID_REUPLOAD_NOT_ASK => { value=>sub{$self->imagelist->reupload_not_ask(@_)}, label=>gettext("Do not ask me again"), }, $main::ID_REUPLOAD_TEXT => { label=>gettext("A least one photo has already been added in the past."), }, }, } )->ShowModal();} ); # callback for GUI refresh : progress dialog display current uploaded image $self->imagelist->progress_thumbnail_refresh( sub { $self->UploadProgressThumbnailRefresh(@_) } ); $self->imagelist->progress_msg_refresh( sub { $self->UploadProgressMessageRefresh(@_) } ); $self->imagelist->progress_msg_details_refresh( sub { $self->UploadProgressMessageDetailsRefresh(@_) } ); $self->imagelist->progressbar_refresh( sub { $self->UploadProgressBarRefresh(@_) } ); $self->imagelist->progress_endinfo_refresh( sub { $self->UploadDisplayEndInfo(@_) } ); $self->imagelist->pwg( $self->pwg ); $self->imagelist->categories( [] ); $self->_set_setting_properties; $self->_initFrame; $self->_initMenus; $self->_initEventHandlers; $self->_initImgTypes; # only refresh when calling event is finished Wx::Event::EVT_IDLE( $self, sub { my ( $self, $event ) = @_; if ( $self->image_preview_refresh and $self->image_preview->IsShown ){ $self->set_preview_image; $self->image_preview->Refresh; $self->image_preview_refresh(0); } if($self->imageviewer_refresh){ $self->imageviewer->Refresh; $self->imageviewer_refresh(0); } # have to support batch mode if($self->imageviewer_item_refresh){ map { $self->imageviewer->ItemRefresh( $_ ) } @{$self->imageviewer->GetSelectedItems}; $self->imageviewer_item_refresh(0); } if(!scalar @{$self->imageviewer->GetSelectedItems} and $self->dlg_piwigo_photo_properties->{_properties_notebook}->IsEnabled){ $self->dlg_piwigo_photo_properties->{_properties_notebook}->Enable(0); } $self->OnUpdateToolbar; $event->Skip; } ); $self->imageviewer->SelectItem( $self->current_imageviewer_index ) if $self->imageviewer->GetItemCount; # if file in command line parameters, try to load my $files = wxTheApp->argv; $self->SetNewFiles($files) if scalar @$files; $self->Show; $self; } sub _initImgTypes { my ( $self ) = @_; $self->{IMGTYPE} = { 'jpg' => wxBITMAP_TYPE_JPEG, 'gif' => wxBITMAP_TYPE_GIF, 'png' => wxBITMAP_TYPE_PNG, }; } sub GetWxBitmapType { my ( $self, $type ) = @_; $self->{IMGTYPE}->{$type}; } sub _set_setting_properties { my ( $self ) = @_; $self->piwigo_photo_properties( { $main::CAPTION => { label=>gettext("Caption")}, $main::PHOTO_PROPERTIES_CAPTION => { value => sub { $self->multi_selection_mode ? $self->imagelist->SetImageSelectionName(@_): $self->imagelist->current_image->site_name(@_) }, frame_callback => sub { $self->imageviewer_item_refresh(1); }, }, $main::COMMENT => { label=>gettext("Comment")}, $main::PHOTO_PROPERTIES_COMMENT => { value => sub { $self->multi_selection_mode ? $self->imagelist->SetImageSelectionComment(@_): $self->imagelist->current_image->site_comment(@_) }, frame_callback => sub { $self->imageviewer_item_refresh(1); }, }, $main::AUTHOR => { label=>gettext("Author")}, $main::PHOTO_PROPERTIES_AUTHOR => { value => sub { $self->multi_selection_mode ? $self->imagelist->SetImageSelectionAuthor(@_): $self->imagelist->current_image->site_author(@_) }, frame_callback => sub { $self->imageviewer_item_refresh(1); }, }, $main::TAGS => { label=>gettext("Tags")}, $main::CREATE_DATE => { label=>gettext("Create date")}, $main::PHOTO_PROPERTIES_CREATE_DATE => { value => sub { $self->multi_selection_mode ? $self->imagelist->SetImageSelectionCreateDate(@_): $self->imagelist->current_image->create_date(@_) }, frame_callback => sub { $self->imageviewer_item_refresh(1); }, }, $main::PRIVACY_LEVEL => { label=>gettext("Who can see?")}, $main::PHOTO_PROPERTIES_PRIVACY_LEVEL => { selection => sub { $self->multi_selection_mode ? $self->imagelist->SetImageSelectionPrivacyLevel(@_): $self->imagelist->current_image->privacy_level(@_) }, choices => wxTheApp->privacy_level_choices, }, $main::PHOTO_PROPERTIES_NB => { texts => [ gettext("Properties"), gettext("Tags") ], }, $main::PHOTO_PROPERTIES_UPLOAD => { label=>gettext("Upload to Piwigo") }, } ); $self->global_settings( { $main::DEFAULT_PHOTO_CAPTION => { label => gettext("Default photo caption") }, $main::CPANE_RESIZE_ADVANCED => { label => gettext("Advanced") }, $main::CPANE_HD_ADVANCED => { label => gettext("Advanced") }, $main::CPANE_TRANSFERT_ADVANCED => { label => gettext("Advanced") }, $main::GS_THUMBNAIL => { label => gettext("Thumbnail") }, $main::GS_SITE_IMG => { label => gettext("Web sized") }, $main::GS_HD => { label => gettext("High definition") }, $main::GS_CLOSE => { label => gettext("Close")}, $main::GS_DEFAULT_PHOTO_CAPTION => { string_selection => sub { $self->imagelist->default_photo_name(@_) }, choices => [ map { gettext $_ } @{wxTheApp->default_photo_names} ], pre_process => sub { my ( $value ) = @_; wxTheApp->eng_default_photo_names->{$value} }, frame_callback => sub { my( $self, $ctrl, $event ) = @_; $self->OnDefaultPhotoCaption($event); }, }, $main::PHOTO_CAPTION_PREFIX => { label => gettext("Photo caption prefix") }, $main::GS_PHOTO_CAPTION_PREFIX => { value => sub { $self->imagelist->default_name_prefix(@_) }, }, $main::GS_AUTO_ROTATE => { label => gettext("Auto rotate image"), value => sub { $self->imagelist->auto_rotate(@_) } }, $main::DEFAULT_AUTHOR => { label => gettext("Default author")}, $main::GS_DEFAULT_AUTHOR => { value => sub { $self->imagelist->author(@_) } }, $main::THUMBNAIL_SIZE => { label => gettext("Site thumbnail size") }, $main::GS_THUMBNAIL_SIZE => { value => sub { $self->imagelist->thumb_size(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::THUMBNAIL_JPEG_QUALITY => { label => gettext("Site thumbnail jpeg quality") }, $main::GS_THUMBNAIL_JPEG_QUALITY => { value => sub { $self->imagelist->th_quality(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::GS_CREATE_RESIZED => { selection => sub { $self->imagelist->create_resized(@_) }, choices => [ map { gettext $_ } ( "Use original", "Use resized original" ) ], frame_callback => sub { my( $dlg, $ctrl, $event ) = @_; $dlg->OnCreateResized($event); }, }, $main::SITE_IMG_WIDTH => { label => gettext("Maximum width") }, $main::GS_SITE_IMG_WIDTH => { value => sub { $self->imagelist->resize_w(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::SITE_IMG_HEIGHT => { label => gettext("Maximum height") }, $main::GS_SITE_IMG_HEIGHT => { value => sub { $self->imagelist->resize_h(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::SITE_IMG_JPEG_QUALITY => { label => gettext("Site image jpeg quality") }, $main::GS_SITE_IMG_JPEG_QUALITY => { value => sub { $self->imagelist->quality(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::SITE_IMG_FILTER => { label => gettext("Site image filter") }, $main::GS_SITE_IMG_FILTER => { string_selection => sub { $self->imagelist->filter(@_) }, choices => [ qw/Point Box Triangle Hermite Hanning Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos Bessel Sinc/ ], }, $main::SITE_IMG_BLUR => { label => gettext("Site image blur") }, $main::GS_SITE_IMG_BLUR => { value => sub { $self->imagelist->blur(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::SITE_IMG_INTERLACE => { label => gettext("Site image interlace") }, $main::GS_SITE_IMG_INTERLACE => { string_selection => sub { $self->imagelist->interlace(@_) }, choices => [ qw/None Line Plane Partition JPEG GIF PNG/ ], }, $main::GS_REMOVE_UPLOADED_FROM_SELECTION => { label => gettext("Remove uploaded photo from selection"), value => sub { $self->imagelist->remove_uploaded_from_selection(@_) }, }, $main::GS_HD_UPLOAD => { choices => [ map { gettext $_ } @{wxTheApp->upload_hd} ], pre_process => sub { my ( $value ) = @_; wxTheApp->eng_upload_hd->{$value} }, string_selection => sub { $self->imagelist->upload_hd(@_) }, frame_callback => sub { my( $self, $ctrl, $event ) = @_; $self->OnHDUpload($event); }, }, $main::HD_IMG_WIDTH => { label => gettext("Maximum width") }, $main::GS_HD_IMG_WIDTH => { label => gettext("HD image width"), value => sub { $self->imagelist->hd_w(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::HD_IMG_HEIGHT => { label => gettext("Maximum height") }, $main::GS_HD_IMG_HEIGHT => { label => gettext("HD image height"), value => sub { $self->imagelist->hd_h(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::HD_IMG_JPEG_QUALITY => { label => gettext("HD image jpeg quality") }, $main::GS_HD_IMG_JPEG_QUALITY => { value => sub { $self->imagelist->hd_quality(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::HD_IMG_FILTER => { label => gettext("HD image filter") }, $main::GS_HD_IMG_FILTER => { string_selection => sub { $self->imagelist->hd_filter(@_) }, choices => [ qw/Point Box Triangle Hermite Hanning Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos Bessel Sinc/ ], }, $main::HD_IMG_BLUR => { label => gettext("HD image blur") }, $main::GS_HD_IMG_BLUR => { value => sub { $self->imagelist->hd_blur(@_) }, validator => Wx::Perl::TextValidator->new( '\d' ) }, $main::HD_IMG_INTERLACE => { label => gettext("HD image interlace") }, $main::GS_HD_IMG_INTERLACE => { string_selection => sub { $self->imagelist->hd_interlace(@_) }, choices => [ qw/None Line Plane Partition JPEG GIF PNG/ ], }, $main::GS_WMARK_ACTIVATE => { label => gettext("Activate watermark"), value => sub { $self->imagelist->watermark_activate(@_) }, frame_callback => sub { my( $self, $ctrl, $event ) = @_; $self->OnWatermark($event); }, }, $main::GS_WMARK_ACTIVATE_HD => { label => gettext("Activate watermark on high definition"), value => sub { $self->imagelist->watermark_activate_pwg_high(@_) }, frame_callback => sub { my( $self, $ctrl, $event ) = @_; $self->OnWatermark($event); }, }, $main::WMARK_TEXT => { label => gettext("Text") }, $main::GS_WMARK_TEXT => { value => sub { $self->imagelist->watermark_text(@_) }, }, $main::WMARK_TEXT_SIZE => { label => gettext("Text size") }, $main::GS_WMARK_TEXT_SIZE => { value => sub { $self->imagelist->watermark_text_size(@_) }, }, $main::WMARK_COLOR => { label => gettext("Color") }, $main::GS_WMARK_COLOR => { string_selection => sub { $self->imagelist->watermark_color(@_) }, choices => [ map { gettext $_ } @{wxTheApp->colors} ], pre_process => sub { my ( $value ) = @_; wxTheApp->eng_colors->{$value} }, }, $main::WMARK_POSITION => { label => gettext("Position") }, $main::GS_WMARK_POSITION => { string_selection => sub { $self->imagelist->watermark_position(@_) }, choices => [ map { gettext $_ } @{wxTheApp->positions} ], pre_process => sub { my ( $value ) = @_; wxTheApp->eng_positions->{$value} }, }, $main::WMARK_MARGIN_TOP => { label => gettext("Top margin") }, $main::GS_WMARK_MARGIN_TOP => { value => sub { $self->imagelist->watermark_y(@_) }, }, $main::WMARK_MARGIN_LEFT => { label => gettext("Left margin") }, $main::GS_WMARK_MARGIN_LEFT => { value => sub { $self->imagelist->watermark_x(@_) }, }, $main::CHUNK_SIZE => { label => gettext("Transfert chunk size") }, $main::GS_CHUNK_SIZE => { value => sub { wxTheApp->chunk_size(@_) }, }, } ); $self->piwigo_property_list( [ { label => gettext("Photo caption"), }, { label => gettext("Comment"), }, { label => gettext("Author"), }, { label => gettext("File name"), }, { label => gettext("Create date"), }, ] ); $self->exif_properties( [ { label => gettext("Create date"), value => sub { $self->imagelist->current_image->create_date }, readonly => 1, }, { label => gettext("Model"), value => sub { $self->imagelist->current_image->exif_tag('Model') }, readonly => 1, }, { label => gettext("Width"), value => sub { $self->imagelist->current_image->exif_tag('ImageWidth') }, readonly => 1, }, { label => gettext("Height"), value => sub { $self->imagelist->current_image->exif_tag('ImageHeight') }, readonly => 1, }, { label => gettext("Orientation"), value => sub { $self->imagelist->current_image->exif_tag('Orientation') }, readonly => 1, }, { label => "ISO", value => sub { $self->imagelist->current_image->exif_tag('ISO') }, readonly => 1, }, { label => gettext("Shutter speed"), value => sub { $self->imagelist->current_image->exif_tag('ExposureTime') }, readonly => 1, }, { label => gettext("Aperture"), value => sub { $self->imagelist->current_image->exif_tag('ApertureValue') }, readonly => 1, }, { label => gettext("Focal length"), value => sub { $self->imagelist->current_image->exif_tag('FocalLength') }, readonly => 1, }, { label => gettext("Lens"), value => sub { $self->imagelist->current_image->exif_tag('Lens') }, readonly => 1, }, ] ); $self->image_tags( sub { scalar @{$self->imagelist->image_selection} > 1 ? $self->imagelist->SetImageSelectionTags(@_) : $self->imagelist->current_image->site_tags(@_)||[] } ); $self->piwigo_tags( sub { wxTheApp->pwg->tags } ); } sub _create_piwigo_tag { my ( $self, $name ) = @_; if( Wx::MessageBox( sprintf( "%s \"%s\" ?", gettext("Do you want to create"), $name, ), gettext("Piwigo search information"), wxYES_NO | wxICON_QUESTION, ) == wxYES ){ $self->pwg->AddTags($name); $self->pwg->RefreshTags; } } sub _refreshFrame { my ( $self ) = @_; eval { $self->_set_setting_properties; }; $self->_refresh_settings_panels_properties; map { $_->Refresh; } ( $self->image_prop_exif, $self->global_settings_panel, $self->piwigo_photo_properties_tags ); } # sub _initFrame { my ( $self ) = @_; $self->create_toolbar; my $sizer_h = Wx::BoxSizer->new( wxHORIZONTAL ); $self->imageviewer( Uploader::GUI::wxImageListCtrl->new( { parentwnd => $self, imagelist => $self->imagelist, image_size => $self->imagelist->wx_thumb_size, columns => $self->piwigo_property_list, } ) ); # message displayed in the image listctrl when empty $self->imageviewer->InitEmptyMsg; $self->init_panels; $self->dlg_piwigo_photo_properties ( Uploader::GUI::wxPhotoProperties->new( { parentwnd => $self, properties => $self->piwigo_photo_properties, tags => { id => $main::PHOTO_PROPERTIES_TAG, choices => $self->piwigo_tags, selection => $self->image_tags, creation_callback => sub { $self->_create_piwigo_tag(@_) }, }, } ) ); $self->piwigo_photo_properties_tags( $self->dlg_piwigo_photo_properties->FindWindow($main::PHOTO_PROPERTIES_TAG) ); $self->create_tree( $self->dlg_piwigo_photo_properties->FindWindow($main::PHOTO_PROPERTIES_CATEGORIES) ); $self->init_dnd_targets; if( $self->imagelist->wx_thumb_imglist->GetImageCount){ $self->ShowImageViewer; $self->imageviewer->Refresh( $self->imagelist->wx_thumb_imglist ); $self->OnUpdateImageviewerNotEmpty; } else{ $self->OnUpdateImageviewerEmpty; } # the imageviewer has a stretch factor of 1 : expands its size on frame resize $sizer_h->Add( $self->imageviewer, 1, wxEXPAND|wxALL, 2 ); $sizer_h->Add( $self->dlg_piwigo_photo_properties, 0, wxEXPAND|wxALL, 2 ); $self->SetSizer( $sizer_h ); my $new_size = $sizer_h->Fit( $self ); $self->SetMinSize([600, 660]); $self->Center; } sub OnUpdateImageviewerEmpty { my ( $self ) = @_; $self->dlg_piwigo_photo_properties->{_properties_notebook}->Enable(0); $self->imageviewer->OnEmpty; } sub OnUpdateImageviewerNotEmpty { my ( $self ) = @_; $self->dlg_piwigo_photo_properties->{_properties_notebook}->Enable(1); $self->imageviewer->OnNotEmpty; } sub _refresh_settings_panels_properties { my ( $self ) = @_; $self->dlg_piwigo_photo_properties->properties( $self->piwigo_photo_properties ); $self->image_prop_exif->properties( $self->exif_properties ); $self->global_settings_panel->properties( $self->global_settings ); } sub _init_settings_panels { my ( $self ) = @_; $self->image_prop_exif( Uploader::GUI::wxPropertyListDlg->new( { parentwnd => $self, properties => $self->exif_properties, caption => sprintf("%s - EXIF", gettext("Properties")), } ) ); $self->image_prop_exif->Hide; $self->global_settings_panel( Uploader::GUI::wxGlobalSettings->new( { parentwnd => $self, caption => gettext("Global settings"), properties => $self->global_settings, } ) ); $self->global_settings_panel->Hide; $self->image_preview( Uploader::GUI::wxImagePreview->new( { parentwnd => $self, caption => gettext("Preview"), } ) ); } sub init_panels { my ( $self ) = @_; $self->_init_settings_panels; } # HTML code for getting started dialog box sub init_dnd_targets { my ( $self ) = @_; $self->imageviewer->SetDropTarget( DNDImageListDropTarget->new( $self->imageviewer ) ); $self->tree->SetDropTarget( DNDCategoryTreeDropTarget->new( $self->tree ) ); } sub OnPhotoProperties { my ( $self ) = @_; $self->image_prop_exif->Show(1); } sub OnPreview { my ( $self ) = @_; $self->image_preview->Show(1); } sub OnGlobalSettings { my ( $self ) = @_; $self->global_settings_panel->Show(1); } sub OnChooseLanguage { my ( $self ) = @_; my $languages = wxTheApp->available_languages; my $dialog = new Wx::SingleChoiceDialog( undef, gettext( "Choose a language" ), gettext( "Choose a language" ), [ map { sprintf($_->[0], gettext($_->[2])) } @$languages ] ); if( $dialog->ShowModal() == wxID_OK ) { wxTheApp->current_language( $languages->[$dialog->GetSelection][1] ); Wx::LogMessage( sprintf( "%s : %s", gettext("pLoader needs to be restarted to display the new selected language"), gettext($languages->[$dialog->GetSelection][2]) ) ); wxTheApp->layout_clean(1); } $dialog->Destroy; } sub OnDefaultPhotoNameChanged { my ( $self ) = @_; Wx::LogMessage("New default_photo_name %s", $self->imagelist->default_photo_name); } sub OnGeneralSettingsClose { my ( $self, $event ) = @_; $self->global_settings_panel->Hide; } sub OnImageExifPropClose { my ( $self, $event ) = @_; $self->image_exif_prop->Hide; } sub create_tree { my ( $self, $tree ) = @_; my $images = [ map { Wx::Bitmap->new( $_, wxBITMAP_TYPE_PNG ) } ( wxTheApp->resource_path('tree_pwg.png'), wxTheApp->resource_path('tree_folder.png'), ) ]; $self->treeimglist( Wx::ImageList->new( 16, 16, 1 ) ); map { $self->treeimglist->Add($_); } @$images; $self->tree( $tree || Wx::TreeCtrl->new( $self->horizontal_splitter, -1, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN| wxTR_HAS_BUTTONS| wxTR_EDIT_LABELS ) ); $self->tree->SetImageList( $self->treeimglist ); $self->populate_tree_categories if !wxTheApp->use_offline; $self->tree ; } sub populate_tree_categories { my ( $self ) = @_; $self->populate_tree( $self->tree, wxTheApp->pwg->categories, ) if defined wxTheApp->pwg ; } # returns a valid itemData sub itemData { Wx::TreeItemData->new( $_[0] ) } sub populate_tree { my ( $self, $tree, $tree_items ) = @_; my $root = shift @{$tree_items}; $self->tree_root( $tree->AddRoot( $root->[0], $root->[3], $root->[4], itemData( $root->[2] ) ) ); $self->populate_tree_helper( $tree, $self->tree_root, $tree_items ); $tree->SelectItem( $self->tree_root ); $tree->Expand( $self->tree_root ); } sub populate_tree_helper { my ( $self, $tree, $parent_id, $tree_items ) = @_; my $id; map { my $name = $_->[0]; $id = $tree->AppendItem( $parent_id, $name, defined($_->[3]) ? $_->[3] : 0, defined($_->[4]) ? $_->[4] : 0, itemData( $_->[2]) ); $self->tree_item_default($id) if ! defined $self->tree_item_default; # current item has children if( ref( $_->[1] ) eq 'ARRAY' ) { $self->populate_tree_helper( $tree, $id, $_->[1] ); } } @{$tree_items}; } sub _initMenus { my ( $self ) = @_ ; $self->_tree_mnu; $self->_imageviewer_mnu; } sub _tree_mnu { my ( $self ) = @_; my $ctx_mnu = Wx::Menu->new; map { $ctx_mnu->Append( @$_[0..2], wxITEM_NORMAL ); } ( # workaround : first item does not show bitmap [ 0, "", "", wxTheApp->resource_path('mnu_folder_new.png'), ], [ 1+$ID_TREE_CTX_MENU, wxTheApp->branding->{'Add new category'}, sprintf( "%s %s %s %s", gettext("Add a new"), wxTheApp->branding->{category}, gettext("to the currently selected"), wxTheApp->branding->{category}, ), wxTheApp->resource_path('mnu_folder_new.png'), ], [ 2+$ID_TREE_CTX_MENU, gettext("Refresh"), sprintf( "Refresh %s list.", wxTheApp->branding->{category}, ), wxTheApp->resource_path('mnu_refresh.png'), ], [ 3+$ID_TREE_CTX_MENU, gettext("Expand all"), sprintf( "Expand %s list.", wxTheApp->branding->{category}, ), wxTheApp->resource_path('mnu_expandall.png'), ], [ 4+$ID_TREE_CTX_MENU, gettext("Collapse all"), sprintf( "Collapse %s list.", wxTheApp->branding->{category}, ), wxTheApp->resource_path('mnu_collapseall.png'), ], ); $ctx_mnu->Delete(0); $self->tree_mnu( $ctx_mnu ); } sub _imageviewer_mnu { my ( $self ) = @_; my $ctx_mnu = Wx::Menu->new; map { $ctx_mnu->Append( @$_[0..2] ); } ( # workaround : first item does not show bitmap [ 0, "", "", wxTheApp->resource_path('mnu_properties.png'), ], [ 1+$ID_IMAGEVIEWER_CTX_MENU, gettext("Properties"), gettext("Modify photo properties"), wxTheApp->resource_path('mnu_properties.png'), ], [ 2+$ID_IMAGEVIEWER_CTX_MENU, gettext("Preview"), gettext("Display photo preview"), wxTheApp->resource_path('mnu_preview.png'), ], ); $ctx_mnu->Delete(0); $self->imageviewer_mnu( $ctx_mnu ); } sub _initEventHandlers { my ( $self ) = @_ ; Wx::Event::EVT_MENU( $self, 101, \&OnAddImages ); Wx::Event::EVT_MENU( $self, 102, \&OnRemoveImages ); Wx::Event::EVT_MENU( $self, 103, \&OnUploadImages ); Wx::Event::EVT_MENU( $self, 104, \&OnGlobalSettings ); #Wx::Event::EVT_MENU( $self, 105, \&OnChooseLanguage ); Wx::Event::EVT_CHOICE( $self, 106, \&OnPhotoSelMode ); Wx::Event::EVT_TREE_SEL_CHANGED( $self, $self->tree, \&OnTreeSelChanged ); Wx::Event::EVT_TREE_ITEM_RIGHT_CLICK( $self, $self->tree, \&OnTreeItemRightClick ); Wx::Event::EVT_TREE_END_LABEL_EDIT( $self, $self->tree, \&OnTreeEndLabelEdit ); Wx::Event::EVT_LIST_END_LABEL_EDIT( $self, $self->imageviewer, \&OnImageViewerEndLabelEdit ); Wx::Event::EVT_LIST_ITEM_ACTIVATED( $self, $self->imageviewer, \&OnImageViewerItemActivated ); Wx::Event::EVT_LIST_ITEM_SELECTED($self, $self->imageviewer, \&OnImageViewerItemSelected) ; Wx::Event::EVT_LIST_ITEM_DESELECTED($self, $self->imageviewer, \&OnImageViewerItemDeSelected) ; Wx::Event::EVT_LIST_ITEM_RIGHT_CLICK($self, $self->imageviewer, \&OnImageViewerItemRightClick) ; Wx::Event::EVT_LIST_KEY_DOWN($self, $self->imageviewer, \&OnImageViewerKeyDown) ; Wx::Event::EVT_CLOSE( $self, \&OnClose ); Wx::Event::EVT_MENU( $self, 1+$ID_TREE_CTX_MENU, \&OnAddCategories ); Wx::Event::EVT_MENU( $self, 2+$ID_TREE_CTX_MENU, \&OnRefreshCategories ); Wx::Event::EVT_MENU( $self, 3+$ID_TREE_CTX_MENU, \&OnExpandCategories ); Wx::Event::EVT_MENU( $self, 4+$ID_TREE_CTX_MENU, \&OnCollapseCategories ); Wx::Event::EVT_MENU( $self, 1+$ID_IMAGEVIEWER_CTX_MENU, \&OnPhotoProperties ); Wx::Event::EVT_MENU( $self, 2+$ID_IMAGEVIEWER_CTX_MENU, \&OnPreview ); Wx::Event::EVT_BUTTON( $self, $main::PHOTO_PROPERTIES_UPLOAD, \&OnUploadImages ); Wx::Event::EVT_BUTTON( $self, $self->imageviewer->add_button->GetId, \&OnAddImages ); } { my $prevdir; my $prevfile; sub OnAddImages { my( $self, $event ) = @_; my $dialog = Wx::FileDialog->new ( $self, gettext("Select photos for upload"), $prevfile, $prevdir, sprintf("%s (*.JPG)|*.JPG|(*.jpg)|*.jpg|All(*.*)|*.*", gettext("JPEG files")), wxFD_OPEN|wxFD_MULTIPLE ); my $file_paths = []; if( $dialog->ShowModal != wxID_CANCEL ) { @$file_paths = $dialog->GetPaths; $self->SetNewFiles($file_paths) ; } $dialog->Destroy; } } sub OnUpdateToolbar { my( $self ) = @_; if($self->global_settings_panel->IsShown){ $self->toolbar->EnableTool(104, 0); } else{ $self->toolbar->EnableTool(104, 1); } if($self->global_settings_panel->IsShown){ $self->toolbar->EnableTool(104, 0); } else{ $self->toolbar->EnableTool(104, 1); } } sub OnRemoveImages { my( $self, $event ) = @_; $self->imagelist->RemoveImageSelection; $self->imageviewer->Refresh; if (!$self->imageviewer->GetItemCount){ $self->image_preview->image( 0 ); # have to reset $self->dlg_piwigo_photo_properties->ClearProperties; $self->piwigo_photo_properties_tags->ClearAllSelection; $self->imagelist->SetCurrentImage(-1); $self->OnUpdateImageviewerEmpty; } else{ $self->OnUpdateImageviewerNotEmpty; } if(!$self->multi_selection_mode){ $self->OnUpdateSingleSelectionModeUI; } $self->image_preview->Refresh; $self->image_prop_exif->Refresh; } sub SetNewFiles { my ( $self, $file_paths ) = @_; $self->ShowImageViewer(); $self->progressdlg->Destroy if defined $self->progressdlg; $self->progressdlg( Uploader::GUI::wxImageProcessingProgressDlg->new( { title => gettext("Image processing progress information"), bt_label => gettext("Cancel image processing"), bt_close_label => gettext("Close"), stop_processing => sub { $self->imagelist->stop_processing(1); Wx::Yield(); }, } ) ); $self->progressdlg->Show(1); Wx::Yield(); my $files = [ map { # to make sure that unicode chars in filenames are supported { ANSIPathName => $^O =~ /MSWin32/ ? Win32::GetANSIPathName($_) : $_, PathName => $_, }, }@$file_paths ]; @$files = sort { $a->{PathName} cmp $b->{PathName} } @$files; $self->imagelist->SetNewFiles( $files ); } sub OnTreeSelChanged { my( $self, $event ) = @_; my @items = $self->tree->GetSelections; $self->imagelist->categories( [ map { my $category = $self->tree->GetPlData( $_ ); $category->{id} if $category != -1; } @items ] ); } sub OnTreeItemRightClick { my( $self, $event ) = @_; $self->PopupMenu($self->tree_mnu, wxDefaultPosition); } sub OnTreeEndLabelEdit { my( $self, $event ) = @_; my $label = $event->GetLabel; $label =~ s/^\s+$//; if(defined($label) and !( "" eq $label )){ $self->_SetLabel($event) } else{ $event->Veto; } } sub _SetLabel { my( $self, $event ) = @_; my $category = $self->tree->GetPlData($event->GetItem); my $category_id; $category_id = $category->{id} if 'HASH' eq ref($category) ; my $comment; my ( $success, $status_msg, $content ) = $self->pwg->SetInfoCategories( $event->GetLabel, $comment, $category_id ); my $ok = 1; if(!$success){ $ok = 0; } if('fail' eq $content->{stat}){ $ok = 0; } # method call failed if(!$ok){ $event->Veto; Wx::MessageBox( sprintf( "%s %s", gettext("Update failed : "), $status_msg ), gettext("Piwigo update error"), wxOK | wxICON_EXCLAMATION, ); Wx::LogMessage("%s\n\n%s", Dumper($content), gettext("This function is not available. A Piwigo upgrade may resolve this issue.")); } } sub OnImageViewerItemRightClick { my( $self, $event ) = @_; $self->PopupMenu($self->imageviewer_mnu, wxDefaultPosition); } sub OnExpandCategories { my ( $self, $event ) = @_; my $parent_item = $self->tree->GetSelection; $self->tree->ExpandAllChildren($parent_item); $self->tree->EnsureVisible($parent_item); } sub OnCollapseCategories { my ( $self, $event ) = @_; my $parent_item = $self->tree->GetSelection; $self->tree->CollapseAllChildren($parent_item); $self->tree->Expand($parent_item) if -1 == $self->tree->GetPlData($parent_item); } sub OnAddCategories { my ( $self, $event ) = @_; my $parent_item = $self->tree->GetSelection; my $category = $self->tree->GetPlData($parent_item); my $category_id; $category_id = $category->{id} if 'HASH' eq ref($category) ; my $dialog = Wx::TextEntryDialog->new( $self, wxTheApp->branding->{'Category name'}, wxTheApp->branding->{'Add new category'}, wxTheApp->branding->{'New category'}, ); if( $dialog->ShowModal != wxID_CANCEL ) { my $name = $dialog->GetValue; my ( $success, $status_msg, $content ) = $self->pwg->AddCategories( $name, $category_id); if($success){ $self->_append_category($parent_item, $name, $content->{result}{id}); } } $dialog->Destroy; } sub OnRefreshCategories { my ( $self, $event ) = @_; $self->_refresh_all_categories_helper; } sub _refresh_all_categories_helper { my ( $self ) = @_; my $busycursor = Wx::BusyCursor->new(); $self->tree->CollapseAll; $self->tree->DeleteAllItems; $self->imagelist->categories([]); $self->pwg->RefreshCategories(); $self->populate_tree_categories; } sub _append_category { my ( $self, $parent_id, $name, $id ) = @_; $self->tree->SelectItem( $self->tree->AppendItem( $parent_id, $name, 1, -1, Wx::TreeItemData->new( { id => $id } ) ) ); } sub OnImageViewerEndLabelEdit { my( $self, $event ) = @_; my $image = $self->imagelist->GetImage($event->GetIndex); $image->site_name( $event->GetLabel ); $self->dlg_piwigo_photo_properties->SetProperties; } sub OnImageViewerItemActivated { my( $self, $event ) = @_; $self->current_imageviewer_index( $event->GetIndex ); $self->OnPhotoProperties; } sub OnImageViewerItemSelected { my( $self, $event ) = @_; my $bc = Wx::BusyCursor->new; my $indx = $event->GetIndex; $self->dlg_piwigo_photo_properties->{_properties_notebook}->Enable(1) if !$self->dlg_piwigo_photo_properties->{_properties_notebook}->IsEnabled; $self->_on_imageviewer_item_selected($indx); $event->Skip; } sub OnImageViewerItemDeSelected { my( $self, $event ) = @_; my $bc = Wx::BusyCursor->new; $self->_on_imageviewer_item_selection_changed; $event->Skip; } sub _on_imageviewer_item_selected { my ( $self, $index ) = @_; $self->current_imageviewer_index($index); $self->imagelist->SetCurrentImage($index); $self->_on_imageviewer_item_selection_changed; } sub _on_imageviewer_item_selection_changed { my ( $self ) = @_; $self->imagelist->image_selection( $self->imageviewer->GetSelectedItems ); # for batch mode : reset the batch buffer if single selection if($self->multi_selection_mode){ $self->OnUpdateMultiSelectionModeUI; $self->imagelist->SetImageSelectionTags([]); $self->imagelist->image_selection_privacy_level(-1); $self->imagelist->image_selection_name(""); $self->imagelist->image_selection_author(""); $self->imagelist->image_selection_comment(""); $self->imagelist->image_selection_create_date(-1); } else{ $self->OnUpdateSingleSelectionModeUI; } # process image_preview in idle time # and when current event is processed # see call to EVT_IDLE $self->image_preview_refresh(1); $self->dlg_piwigo_photo_properties->SetProperties if defined $self->dlg_piwigo_photo_properties; $self->image_prop_exif->Refresh; $self->piwigo_photo_properties_tags->Refresh; } sub multi_selection_mode { my ( $self ) = @_; scalar @{$self->imagelist->image_selection} > 1; } sub OnUpdateMultiSelectionModeUI{ my( $self ) = @_; $self->dlg_piwigo_photo_properties->{_multi_selection_mode_panel}{_text1}->SetLabel( sprintf(gettext("You have selected a batch of %s photos"), $self->imageviewer->GetSelectectItemsCount ) ); $self->dlg_piwigo_photo_properties->{_multi_selection_mode_panel}{_text2}->SetLabel( gettext("Changes apply to the whole batch") ); $self->dlg_piwigo_photo_properties->{_multi_selection_mode_panel}->Show(1); $self->dlg_piwigo_photo_properties->Layout; } sub OnUpdateSingleSelectionModeUI{ my( $self ) = @_; $self->dlg_piwigo_photo_properties->{_multi_selection_mode_panel}->Show(0); $self->dlg_piwigo_photo_properties->Layout; } sub set_preview_image { my ( $self ) = @_; my $current_image = $self->imagelist->current_image; my $image = Wx::Image->new; $image->LoadFile( $current_image->file, wxBITMAP_TYPE_ANY ); if($self->imagelist->auto_rotate){ # exif from original image my $orientation = $current_image->exif_metadata->{Orientation}; # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW if( $orientation =~ m/Rotate (\d+)/ ){ for(my $i=0; $i < floor($1/90) ; $i++){ $image = $image->Rotate90; } } } $self->image_preview->image_size( [$image->GetWidth, $image->GetHeight, ] ); $self->image_preview->image( $image ); } sub OnImageViewerKeyDown { my( $self, $event ) = @_; if(WXK_DELETE == $event->GetKeyCode){ $self->OnRemoveImages(); my $index = $self->current_imageviewer_index < $self->imageviewer->GetItemCount ? $self->current_imageviewer_index : $self->imageviewer->GetItemCount -1 ; $self->imageviewer->SelectItem( $index ); $self->imageviewer->EnsureVisible( $index ); } } sub OnUploadImages { my( $self, $event ) = @_; eval { $self->ProcessImageSelection(); }; } # remove image from imagelist when uploaded sub UploadImagesViewerRefresh { my ( $self ) = @_; $self->imageviewer->Refresh; if(!$self->imageviewer->GetItemCount){ $self->image_preview->image(0); $self->OnUpdateImageviewerEmpty; } # reset previous selection $self->imagelist->image_selection( [] ); if(!$self->multi_selection_mode){ $self->OnUpdateSingleSelectionModeUI; } $self->image_preview->Refresh; Wx::Yield(); } sub UploadProgressMessageRefresh { my ( $self, $msg ) = @_; Wx::Yield(); $self->upload_progressdlg->processing( $msg ); $self->upload_progressdlg->LogProgress(); Wx::Yield(); } sub UploadProgressMessageDetailsRefresh { my ( $self, $msg ) = @_; Wx::Yield(); $self->upload_progressdlg->processing_details( $msg ); $self->upload_progressdlg->LogProgress(); Wx::Yield(); } sub UploadProgressThumbnailRefresh { my ( $self ) = @_; my $imagelist = $self->imagelist ; $self->upload_progressdlg->image->SetBitmap(wxNullBitmap); $self->upload_progressdlg->image->SetBitmap( Wx::Bitmap->new( $self->imagelist->current_image->wx_thumb_file, $self->GetWxBitmapType($self->imagelist->type), ) ); Wx::Yield(); } sub UploadProgressBarRefresh { my ( $self, $value ) = @_; eval { $self->upload_progressdlg->progress( $value ); $self->upload_progressdlg->LogProgress(); }; #croak gettext("Upload cancelled") if $@; Wx::Yield(); } sub SetNewFilesDisplayEndInfo { my ( $self, $msg ) = @_; $self->progressdlg->DisplayEndInfo($msg); } sub UploadDisplayEndInfo { my ( $self, $msg ) = @_; my $imagelist = $self->imagelist ; $self->upload_progressdlg->DisplayEndInfo($msg); } sub ShowImageViewer { my ( $self ) = @_; if(!$self->imageviewer->IsShown){ $self->imageviewer->Show(1); } } sub ActivateImageViewer { my ( $self ) = @_; } sub SetNewFilesViewerRefresh { my ( $self ) = @_; my $wximagelist = $self->imagelist->wx_thumb_imglist; #print Dumper "SetNewFilesViewerRefresh", $self->imagelist->current_image; my $indx = $wximagelist->Add( Wx::Bitmap->new( $self->imagelist->current_image->wx_thumb_file, $self->GetWxBitmapType($self->imagelist->type), ) ) if defined $self->imagelist->current_image->wx_thumb_file; #print $self->imagelist->current_image->wx_thumb_file, " added with index ", $indx, "\n"; $self->imageviewer->Refresh( $wximagelist ); $self->OnUpdateImageviewerNotEmpty if $self->imageviewer->GetItemCount; Wx::Yield(); } # prepare and upload image_selection sub ProcessImageSelection { my ( $self ) = @_; return if !scalar @{$self->imagelist->sums}; if( scalar @{$self->imagelist->categories} ){ # all selected is implicit if(!scalar @{$self->imageviewer->GetSelectedItems}){ $self->imagelist->image_selection( $self->imageviewer->GetAllItems ); } return if( !defined $self->imagelist->image_selection ); return if( !scalar @{$self->imagelist->image_selection} ); $self->upload_progressdlg->Destroy if defined $self->upload_progressdlg; $self->upload_progressdlg( Uploader::GUI::wxImageProcessingProgressDlg->new( { title => gettext("Image upload progress information"), bt_label => gettext("Cancel upload"), bt_close_label => gettext("Close"), stop_processing => sub { $self->imagelist->stop_processing(1); Wx::Yield(); }, } ) ); # modeless dialog $self->upload_progressdlg->Show(1); Wx::Yield(); eval { $self->imagelist->UploadSelection; }; if($@){ Wx::MessageBox( sprintf( gettext("Upload cancelled"), ), gettext("Piwigo upload information"), wxOK | wxICON_INFORMATION, ); } } else { Wx::MessageBox( sprintf( "%s", wxTheApp->branding->{'What is the destination category?'} ), gettext("Piwigo upload error"), wxOK | wxICON_EXCLAMATION, ); } } sub SetNewFilesProgress { my ( $self ) = @_; my $imagelist = $self->imagelist; $self->progressdlg->processing( sprintf( $imagelist->progress_msg, $imagelist->current_image->file, ) ); eval { $self->progressdlg->image->SetSize([ $imagelist->wx_thumb_size, $imagelist->wx_thumb_size]); $self->progressdlg->image->SetBitmap(wxNullBitmap); $self->progressdlg->image->SetBitmap( Wx::Bitmap->new( $imagelist->current_image->wx_thumb_file, $self->GetWxBitmapType( $imagelist->type ) ) ); $self->progressdlg->progress( $imagelist->count * ( 100/scalar @{$imagelist->new_files} ) ); $self->progressdlg->LogProgress(); }; Wx::Yield(); } sub OnClose { my $self = shift; # Restaure previous log wnd Wx::Log::SetActiveTarget( $self->oldlogwnd ); # allways store wxTheApp->StoreConnectionProperties; $self->imagelist->Store; wxTheApp->login_dlg->Destroy; wxTheApp->imageviewerIndex( $self->current_imageviewer_index ); my $frameLayout = {}; ( $frameLayout->{pX}, $frameLayout->{pY}, $frameLayout->{W}, $frameLayout->{H} ) = ( $self->GetPositionXY, $self->GetSizeWH ) ; wxTheApp->frameLayout( $frameLayout ); wxTheApp->StoreLayoutProperties; #destroy hidden dialogs $self->global_settings_panel->Destroy; $self->image_preview->Destroy; $self->image_prop_exif->Destroy; $self->progressdlg->Destroy if defined $self->progressdlg; $self->upload_progressdlg->Destroy if defined $self->upload_progressdlg; $self->Destroy; } sub create_toolbar { my( $self ) = @_; my $tb = Wx::ToolBar->new( $self, -1, wxDefaultPosition, [600, -1], wxTB_FLAT|wxTB_TEXT ); $tb->SetToolBitmapSize( wxSIZE( 32, 32 ) ); map { my $icon1 = Wx::Icon->new(); eval { $icon1->LoadFile($_->[2], $_->[3]); }; my $tb_icon1 = Wx::Bitmap->new( $icon1 ); my $icon2 = Wx::Icon->new(); eval { $icon2->LoadFile($_->[5], $_->[3]); }; my $tb_icon2 = Wx::Bitmap->new( $icon2 ); $tb->AddTool( $_->[0], $_->[1], $tb_icon1, $tb_icon2, wxITEM_NORMAL, $_->[1] ); $tb->EnableTool( $_->[0], $_->[4]); } ( [ 101, gettext("Add photo"), wxTheApp->resource_path('tb_add.png'), wxBITMAP_TYPE_PNG, 1, wxTheApp->resource_path('tb_add.png'), gettext("Add photo for resizing and uploading") ], [ 102, gettext("Remove selected photos"), wxTheApp->resource_path('tb_remove.png'), wxBITMAP_TYPE_PNG, 1, wxTheApp->resource_path('tb_remove.png'), gettext("Remove photo from selection. Files are not deleted ") ], # [ # 103, # gettext("Upload to Piwigo"), # wxTheApp->resource_path('tb_upload.png'), # wxBITMAP_TYPE_PNG, # wxTheApp->use_offline ? 0 : 1, # wxTheApp->resource_path('tb_upload.png'), # gettext("Upload photos to Piwigo.") # ], [ 104, gettext("Preferences"), wxTheApp->resource_path('tb_settings.png'), wxBITMAP_TYPE_PNG, 0, wxTheApp->resource_path('tb_settings.png'), gettext("Change global settings.") ], # [ # 105, # gettext("Language choice"), # wxTheApp->resource_path('tb_i18n.png'), # wxBITMAP_TYPE_PNG, # 1, # wxTheApp->resource_path('tb_i18n.png'), # gettext("Language choice") # ], ); $tb->AddSeparator; $tb->AddControl( Wx::Choice->new( $tb, 106, wxDefaultPosition, [300, -1], [], ) ); my $ch = $tb->FindWindow(106); $ch->SetToolTip(gettext("How photo selection is displayed")); map { $ch->Append(gettext($_), $_); }( "Thumbnail and caption", "Thumbnail", "Property list" ); $ch->SetStringSelection(gettext($self->imagelist->display_mode)); $tb->Realize; $self->toolbar( $tb ); $self->SetToolBar($tb); return $tb; } sub OnPhotoSelMode { my ( $self, $event )= @_; $self->imagelist->display_mode( $event->GetClientData ); $self->imageviewer->change_display_mode(1); } sub _create_textctrl { my( $self, $parent, $text, $size ) = @_; return Wx::TextCtrl->new( $parent, -1, $text, [0, 0], $size, wxNO_BORDER | wxTE_MULTILINE | wxTE_READONLY ); } sub create_textctrl { my( $self, $text, $size ) = @_; return $self->_create_textctrl( $self, $text, $size ); } sub DESTROY { my( $self ) = @_; } 1; package DNDImageListDropTarget; use Wx qw/wxTheApp/; use base qw(Wx::FileDropTarget Class::Accessor::Fast); __PACKAGE__->mk_accessors( qw/ imageviewer / ); sub new { my $class = shift; my $imageviewer = shift; my $self = $class->SUPER::new( @_ ); $self->imageviewer($imageviewer); return $self; } sub OnDropFiles { my( $self, $x, $y, $files ) = @_; wxTheApp->frame->SetNewFiles($files) ; } 1; package DNDCategoryTreeDropTarget; use base qw(Wx::TextDropTarget Class::Accessor::Fast); use Data::Dumper; use Wx qw/ wxDragNone wxDragCopy wxDragMove wxTheApp /; __PACKAGE__->mk_accessors( qw/ tree / ); sub new { my ( $class, $tree ) = @_; my $self = $class->SUPER::new(); $self->tree($tree); return $self; } sub OnDropText { my( $self, $x, $y, $textdata ) = @_; # must be $VAR1 because $textdata is the result of Data::Dumper my $VAR1; eval $textdata; eval { if(scalar @$VAR1){ my @items; if(scalar @items < 2) { my ($dropItem, $flag) = $self->tree->HitTest([$x, $y]); push @items, $dropItem; } else { @items = $self->tree->GetSelections; } # remove root item which is not a valid category @items = grep { $self->tree->GetPlData( $_ ) != -1 } @items; wxTheApp->frame->imagelist->categories( [ map { $self->tree->GetPlData( $_ )->{id}; } @items ] ); wxTheApp->frame->imagelist->image_selection($VAR1); wxTheApp->frame->ProcessImageSelection ; } }; } 1;