﻿# +-----------------------------------------------------------------------+
# | pLoader - a Perl photo uploader for Piwigo                            |
# +-----------------------------------------------------------------------+
# | Copyright(C) 2008      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::wxFrameAUI;
use strict;
use Carp;
use Wx;
use Win32;
use Wx::DND;
use Wx qw/
             wxYES_NO
             wxYES
             wxICON_QUESTION
             wxITEM_NORMAL
             wxNullBitmap
             wxID_OK
             wxDEFAULT_FRAME_STYLE
             wxVERTICAL
             wxGROW
             wxBITMAP_TYPE_JPEG
             wxBITMAP_TYPE_GIF
             wxBITMAP_TYPE_PNG
             wxTB_FLAT
             wxSIZE
             wxWHITE
             wxBLACK
             wxID_CANCEL
             wxFD_OPEN
             wxFD_MULTIPLE
             wxLI_HORIZONTAL
             wxALIGN_CENTER_VERTICAL
             wxALL
             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
             wxLANGUAGE_ABKHAZIAN   
             wxLANGUAGE_AFAR   
             wxLANGUAGE_AFRIKAANS   
             wxLANGUAGE_ALBANIAN   
             wxLANGUAGE_AMHARIC   
             wxLANGUAGE_ARABIC   
             wxLANGUAGE_ARABIC_ALGERIA   
             wxLANGUAGE_ARABIC_BAHRAIN   
             wxLANGUAGE_ARABIC_EGYPT   
             wxLANGUAGE_ARABIC_IRAQ   
             wxLANGUAGE_ARABIC_JORDAN   
             wxLANGUAGE_ARABIC_KUWAIT   
             wxLANGUAGE_ARABIC_LEBANON   
             wxLANGUAGE_ARABIC_LIBYA   
             wxLANGUAGE_ARABIC_MOROCCO   
             wxLANGUAGE_ARABIC_OMAN   
             wxLANGUAGE_ARABIC_QATAR   
             wxLANGUAGE_ARABIC_SAUDI_ARABIA   
             wxLANGUAGE_ARABIC_SUDAN   
             wxLANGUAGE_ARABIC_SYRIA   
             wxLANGUAGE_ARABIC_TUNISIA   
             wxLANGUAGE_ARABIC_UAE   
             wxLANGUAGE_ARABIC_YEMEN   
             wxLANGUAGE_ARMENIAN   
             wxLANGUAGE_ASSAMESE   
             wxLANGUAGE_AYMARA   
             wxLANGUAGE_AZERI   
             wxLANGUAGE_AZERI_CYRILLIC   
             wxLANGUAGE_AZERI_LATIN   
             wxLANGUAGE_BASHKIR   
             wxLANGUAGE_BASQUE   
             wxLANGUAGE_BELARUSIAN   
             wxLANGUAGE_BENGALI   
             wxLANGUAGE_BHUTANI   
             wxLANGUAGE_BIHARI   
             wxLANGUAGE_BISLAMA   
             wxLANGUAGE_BRETON   
             wxLANGUAGE_BULGARIAN   
             wxLANGUAGE_BURMESE   
             wxLANGUAGE_CAMBODIAN   
             wxLANGUAGE_CATALAN   
             wxLANGUAGE_CHINESE   
             wxLANGUAGE_CHINESE_SIMPLIFIED   
             wxLANGUAGE_CHINESE_TRADITIONAL   
             wxLANGUAGE_CHINESE_HONGKONG   
             wxLANGUAGE_CHINESE_MACAU   
             wxLANGUAGE_CHINESE_SINGAPORE   
             wxLANGUAGE_CHINESE_TAIWAN   
             wxLANGUAGE_CORSICAN   
             wxLANGUAGE_CROATIAN   
             wxLANGUAGE_CZECH   
             wxLANGUAGE_DANISH   
             wxLANGUAGE_DUTCH   
             wxLANGUAGE_DUTCH_BELGIAN   
             wxLANGUAGE_ENGLISH   
             wxLANGUAGE_ENGLISH_UK   
             wxLANGUAGE_ENGLISH_US   
             wxLANGUAGE_ENGLISH_AUSTRALIA   
             wxLANGUAGE_ENGLISH_BELIZE   
             wxLANGUAGE_ENGLISH_BOTSWANA   
             wxLANGUAGE_ENGLISH_CANADA   
             wxLANGUAGE_ENGLISH_CARIBBEAN   
             wxLANGUAGE_ENGLISH_DENMARK   
             wxLANGUAGE_ENGLISH_EIRE   
             wxLANGUAGE_ENGLISH_JAMAICA   
             wxLANGUAGE_ENGLISH_NEW_ZEALAND   
             wxLANGUAGE_ENGLISH_PHILIPPINES   
             wxLANGUAGE_ENGLISH_SOUTH_AFRICA   
             wxLANGUAGE_ENGLISH_TRINIDAD   
             wxLANGUAGE_ENGLISH_ZIMBABWE   
             wxLANGUAGE_ESPERANTO   
             wxLANGUAGE_ESTONIAN   
             wxLANGUAGE_FAEROESE   
             wxLANGUAGE_FARSI   
             wxLANGUAGE_FIJI   
             wxLANGUAGE_FINNISH   
             wxLANGUAGE_FRENCH   
             wxLANGUAGE_FRENCH_BELGIAN   
             wxLANGUAGE_FRENCH_CANADIAN   
             wxLANGUAGE_FRENCH_LUXEMBOURG   
             wxLANGUAGE_FRENCH_MONACO   
             wxLANGUAGE_FRENCH_SWISS   
             wxLANGUAGE_FRISIAN   
             wxLANGUAGE_GALICIAN   
             wxLANGUAGE_GEORGIAN   
             wxLANGUAGE_GERMAN   
             wxLANGUAGE_GERMAN_AUSTRIAN   
             wxLANGUAGE_GERMAN_BELGIUM   
             wxLANGUAGE_GERMAN_LIECHTENSTEIN   
             wxLANGUAGE_GERMAN_LUXEMBOURG   
             wxLANGUAGE_GERMAN_SWISS   
             wxLANGUAGE_GREEK   
             wxLANGUAGE_GREENLANDIC   
             wxLANGUAGE_GUARANI   
             wxLANGUAGE_GUJARATI   
             wxLANGUAGE_HAUSA   
             wxLANGUAGE_HEBREW   
             wxLANGUAGE_HINDI   
             wxLANGUAGE_HUNGARIAN   
             wxLANGUAGE_ICELANDIC   
             wxLANGUAGE_INDONESIAN   
             wxLANGUAGE_INTERLINGUA   
             wxLANGUAGE_INTERLINGUE   
             wxLANGUAGE_INUKTITUT   
             wxLANGUAGE_INUPIAK   
             wxLANGUAGE_IRISH   
             wxLANGUAGE_ITALIAN   
             wxLANGUAGE_ITALIAN_SWISS   
             wxLANGUAGE_JAPANESE   
             wxLANGUAGE_JAVANESE   
             wxLANGUAGE_KANNADA   
             wxLANGUAGE_KASHMIRI   
             wxLANGUAGE_KASHMIRI_INDIA   
             wxLANGUAGE_KAZAKH   
             wxLANGUAGE_KERNEWEK   
             wxLANGUAGE_KINYARWANDA   
             wxLANGUAGE_KIRGHIZ   
             wxLANGUAGE_KIRUNDI   
             wxLANGUAGE_KONKANI   
             wxLANGUAGE_KOREAN   
             wxLANGUAGE_KURDISH   
             wxLANGUAGE_LAOTHIAN   
             wxLANGUAGE_LATIN   
             wxLANGUAGE_LATVIAN   
             wxLANGUAGE_LINGALA   
             wxLANGUAGE_LITHUANIAN   
             wxLANGUAGE_MACEDONIAN   
             wxLANGUAGE_MALAGASY   
             wxLANGUAGE_MALAY   
             wxLANGUAGE_MALAYALAM   
             wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM   
             wxLANGUAGE_MALAY_MALAYSIA   
             wxLANGUAGE_MALTESE   
             wxLANGUAGE_MANIPURI   
             wxLANGUAGE_MAORI   
             wxLANGUAGE_MARATHI   
             wxLANGUAGE_MOLDAVIAN   
             wxLANGUAGE_MONGOLIAN   
             wxLANGUAGE_NAURU   
             wxLANGUAGE_NEPALI   
             wxLANGUAGE_NEPALI_INDIA   
             wxLANGUAGE_NORWEGIAN_BOKMAL   
             wxLANGUAGE_NORWEGIAN_NYNORSK   
             wxLANGUAGE_OCCITAN   
             wxLANGUAGE_ORIYA   
             wxLANGUAGE_OROMO   
             wxLANGUAGE_PASHTO   
             wxLANGUAGE_POLISH   
             wxLANGUAGE_PORTUGUESE   
             wxLANGUAGE_PORTUGUESE_BRAZILIAN   
             wxLANGUAGE_PUNJABI   
             wxLANGUAGE_QUECHUA   
             wxLANGUAGE_RHAETO_ROMANCE   
             wxLANGUAGE_ROMANIAN   
             wxLANGUAGE_RUSSIAN   
             wxLANGUAGE_RUSSIAN_UKRAINE   
             wxLANGUAGE_SAMI   
             wxLANGUAGE_SAMOAN   
             wxLANGUAGE_SANGHO   
             wxLANGUAGE_SANSKRIT   
             wxLANGUAGE_SCOTS_GAELIC   
             wxLANGUAGE_SERBIAN   
             wxLANGUAGE_SERBIAN_CYRILLIC   
             wxLANGUAGE_SERBIAN_LATIN   
             wxLANGUAGE_SERBO_CROATIAN   
             wxLANGUAGE_SESOTHO   
             wxLANGUAGE_SETSWANA   
             wxLANGUAGE_SHONA   
             wxLANGUAGE_SINDHI   
             wxLANGUAGE_SINHALESE   
             wxLANGUAGE_SISWATI   
             wxLANGUAGE_SLOVAK   
             wxLANGUAGE_SLOVENIAN   
             wxLANGUAGE_SOMALI   
             wxLANGUAGE_SPANISH   
             wxLANGUAGE_SPANISH_ARGENTINA   
             wxLANGUAGE_SPANISH_BOLIVIA   
             wxLANGUAGE_SPANISH_CHILE   
             wxLANGUAGE_SPANISH_COLOMBIA   
             wxLANGUAGE_SPANISH_COSTA_RICA   
             wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC   
             wxLANGUAGE_SPANISH_ECUADOR   
             wxLANGUAGE_SPANISH_EL_SALVADOR   
             wxLANGUAGE_SPANISH_GUATEMALA   
             wxLANGUAGE_SPANISH_HONDURAS   
             wxLANGUAGE_SPANISH_MEXICAN   
             wxLANGUAGE_SPANISH_MODERN   
             wxLANGUAGE_SPANISH_NICARAGUA   
             wxLANGUAGE_SPANISH_PANAMA   
             wxLANGUAGE_SPANISH_PARAGUAY   
             wxLANGUAGE_SPANISH_PERU   
             wxLANGUAGE_SPANISH_PUERTO_RICO   
             wxLANGUAGE_SPANISH_URUGUAY   
             wxLANGUAGE_SPANISH_US   
             wxLANGUAGE_SPANISH_VENEZUELA   
             wxLANGUAGE_SUNDANESE   
             wxLANGUAGE_SWAHILI   
             wxLANGUAGE_SWEDISH   
             wxLANGUAGE_SWEDISH_FINLAND   
             wxLANGUAGE_TAGALOG   
             wxLANGUAGE_TAJIK   
             wxLANGUAGE_TAMIL   
             wxLANGUAGE_TATAR   
             wxLANGUAGE_TELUGU   
             wxLANGUAGE_THAI   
             wxLANGUAGE_TIBETAN   
             wxLANGUAGE_TIGRINYA   
             wxLANGUAGE_TONGA   
             wxLANGUAGE_TSONGA   
             wxLANGUAGE_TURKISH   
             wxLANGUAGE_TURKMEN   
             wxLANGUAGE_TWI   
             wxLANGUAGE_UIGHUR   
             wxLANGUAGE_UKRAINIAN   
             wxLANGUAGE_URDU   
             wxLANGUAGE_URDU_INDIA   
             wxLANGUAGE_URDU_PAKISTAN   
             wxLANGUAGE_UZBEK   
             wxLANGUAGE_UZBEK_CYRILLIC   
             wxLANGUAGE_UZBEK_LATIN   
             wxLANGUAGE_VALENCIAN   
             wxLANGUAGE_VIETNAMESE   
             wxLANGUAGE_VOLAPUK   
             wxLANGUAGE_WELSH   
             wxLANGUAGE_WOLOF   
             wxLANGUAGE_XHOSA   
             wxLANGUAGE_YIDDISH   
             wxLANGUAGE_YORUBA   
             wxLANGUAGE_ZHUANG   
             wxLANGUAGE_ZULU  
         /;
use base qw/Wx::Frame Class::Accessor::Fast/;
use File::Spec;
use Wx::Locale qw/:default/;
use Encode qw/encode decode is_utf8/;;


my @properties = 
    qw/
          progressdlg
          upload_progressdlg
          imageviewer
          tree
          tree_root
          treeimglist
          tree_item_default
          topsizer
          pwg
          manager
          logwnd
          oldlogwnd
          htmlhome
          notebook
          categories
          imagelist
          image_preview
          image_prop_piwigo
          image_prop_exif
          image_prop_tags
          notebook_image_properties
          notebook_global_settings
          general_settings_panel
          resized_settings_panel
          thumbnail_settings_panel
          preview_settings_panel
          advanced_settings_panel
          watermark_settings_panel
          piwigo_properties
          exif_properties
          general_settings
          resized_settings
          thumbnail_settings
          preview_settings
          advanced_settings
          watermark_settings
          toolbar
          branding
          perspective
          current_imageviewer_index
          imageviewer_mnu
          tree_mnu
          imageviewer_select_multi
          frameLayout
          piwigo_tags
          image_tags
      /;
__PACKAGE__->mk_accessors( @properties );

use Wx::Event 
    qw/
          EVT_MENU
          EVT_TREE_SEL_CHANGED
          EVT_TREE_END_LABEL_EDIT
          EVT_CLOSE 
          EVT_LIST_END_LABEL_EDIT
          EVT_LIST_ITEM_SELECTED
          EVT_LIST_ITEM_ACTIVATED
          EVT_LIST_ITEM_RIGHT_CLICK
          EVT_TREE_ITEM_RIGHT_CLICK
          EVT_LIST_KEY_DOWN
          EVT_UPDATE_UI       
      /;
      
use Uploader::GUI::wxImageListCtrl;
use Uploader::GUI::wxImageProcessingProgressDlg;
use Uploader::GUI::wxChoiceFilteredPanel;
use Wx::Html;
use Uploader::GUI::wxHtmlWindow;
use Data::Dumper;
use Wx::AUI;
use Storable;
use Uploader::GUI::wxPropertyGridPanel;
use Encode qw/encode decode is_utf8/;
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->perspective(
        $params->{perspective}
    );
    
    $self->current_imageviewer_index(
        $params->{imageviewer_index}||0
    );
    
    $self->frameLayout(
        $params->{frameLayout} || { 'pX' => -1, 'pY' => -1, W => 800, H => 600 }
    );

    $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(@_) }
    );


    # 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->progressbar_refresh(
        sub { $self->UploadProgressBarRefresh(@_) }
    );
    
    $self->imagelist->progress_endinfo_refresh(
        sub { $self->UploadDisplayEndInfo(@_) }
    );


    $self->imagelist->pwg(
        $self->pwg
    );

    $self->imagelist->categories(
        []
    );


    $self->manager( Wx::AuiManager->new );
    $self->manager->SetManagedWindow( $self );
    $self->_set_setting_properties;
    $self->_initFrame;
    $self->_initMenus;
    $self->_initEventHandlers;
    $self->_initImgTypes;   


    $self->imageviewer->SelectItem(
        $self->current_imageviewer_index
    ) if $self->imageviewer->GetItemCount;
   
    $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_properties(
        [
            {
                label => gettext("Photo caption :"),
                value => sub { $self->imagelist->current_image->site_name(@_) },
            },
            {
                label => gettext("Comment :"),
                value => sub { $self->imagelist->current_image->site_comment(@_) },
                type  => "LongText",
            },
            {
                label => gettext("Author :"),
                value => sub { $self->imagelist->current_image->site_author(@_) },
            },
            {
                label    => gettext("File name :"),
                value    => sub { $self->imagelist->current_image->file(@_) },
                readonly => 1,
            },
            {
                label    => gettext("Create date :"),
                value    => sub { $self->imagelist->current_image->create_date(@_) },
                readonly => 1,
            },
        ]    
    );

    $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->general_settings(
        [
            {
                label     => gettext("Default author :"),
                value	=> sub { $self->imagelist->author(@_) },
            },
            {
                label     => gettext("Default photo caption :"),
                type      => 'Choice',
                value	=> sub { $self->imagelist->default_photo_name(@_) },
                choice  => [
                                  gettext('None'),
                                  gettext('File name'),
                                  gettext('File path and name'),
                                  gettext('Prefix'),
                                  gettext('Prefix + rank number'),
                                  gettext('Rank number + prefix'),
                                  gettext('Prefix + create date chrono'),
                                  gettext('Create date chrono + prefix'),
                              ],
            },
            {
                label     => gettext("Photo caption  prefix :"),
                value	=> sub { $self->imagelist->default_name_prefix(@_) },
            },
            {
                label     => gettext("Resize site image :"),
                type      => 'Bool',
                value	=> sub { $self->imagelist->create_resized(@_) },
            },
            {
                label     => gettext("Auto rotate image :"),
                type      => 'Bool',
                value	=> sub { $self->imagelist->auto_rotate(@_) },
            },
            {
                label     => gettext("Upload high (original size) :"),
                type      => 'Bool',
                value	=> sub { $self->imagelist->upload_high(@_) },
            },
            {
                label     => gettext("Remove uploaded photo from selection :"),
                type      => 'Bool',
                value	=> sub { $self->imagelist->remove_uploaded_from_selection(@_) },
            },
        ]    
    );
    
    $self->resized_settings(
        [
            {
                label     => gettext("Site image width :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->resize_w(@_) },
            },
            {
                label     => gettext("Site image height :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->resize_h(@_) },
            },
            {
                label     => gettext("Site image jpeg quality :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->quality(@_) },
            },
            {
                label     => gettext("Site image filter :"),
                type      => 'Choice',
                value	=> sub { $self->imagelist->filter(@_) },
                choice    => [ qw/Point Box Triangle Hermite Hanning Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos Bessel Sinc/ ],
            },
            {
                label     => gettext("Site image blur :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->blur(@_) },
            },
            {
                label     => gettext("Site image interlace :"),
                type      => 'Choice',
                value	=> sub { $self->imagelist->interlace(@_) },
                choice    => [ qw/None Line Plane Partition JPEG GIF PNG/ ],
            },
        ]    
    );

    $self->thumbnail_settings(
        [
            {
                label     => gettext("Site thumbnail size :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->thumb_size(@_) },
            },
            {
                label     => gettext("Site thumbnail jpeg quality :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->th_quality(@_) },
            },
            {
                label     => gettext("Photo selection thumbnail size :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->wx_thumb_size(@_) },
            },
            {
                label     => gettext("Photo selection thumbnail jpeg quality :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->wx_quality(@_) },
            },
        ]    
    );
    
    $self->preview_settings(
        [
            {
                label     => gettext("Use exif preview when available :"),
                type      => 'Bool',
                value	=> sub { $self->imagelist->use_exif_preview(@_) },
            },
            {
                label     => gettext("Custom preview ratio :"),
                type      => 'Number',
                value	=> sub { $self->imagelist->preview_ratio(@_) },
            },
        ]    
    );

    $self->advanced_settings(
        [
            {
                label     => gettext("Transfert chunk size :"),
                type      => 'Number',
                value	=> sub { wxTheApp->chunk_size(@_) },
            },
        ]    
    );

    $self->watermark_settings(
        [
            {
              label  => gettext("Activate watermark :"),
              type   => 'Bool',
              value  => sub { $self->imagelist->watermark_activate(@_) },
            },
            {
              label => gettext("Activate watermark on high definition :"),
              type  => 'Bool',
              value => sub { $self->imagelist->watermark_activate_pwg_high(@_) },
            },
            {
              label  => gettext("Text :"),
              value  => sub { $self->imagelist->watermark_text(@_) },
            },
            {
                label     => gettext("Text size :"),
                type      => 'Number',
                value   => sub { $self->imagelist->watermark_text_size(@_) },
            },
            {
                label     => gettext("Color :"),
                type      => 'Choice',
                value   => sub { $self->imagelist->watermark_color(@_) },
                choice  => [
                                  gettext("White"),
                                  gettext("Black"),
                           ],
            },            
            {
                label     => gettext("Position :"),
                type      => 'Choice',
                value   => sub { $self->imagelist->watermark_position(@_) },
                choice  => [
                                  gettext("Top"),
                                  gettext("Top left"),
                                  gettext("Top right"),
                                  gettext("Bottom"),
                                  gettext("Bottom left"),
                                  gettext("Bottom right"),
                                  gettext("Center"),
                                  gettext("Left"),
                                  gettext("Right"),
                           ],
            },
            {
                label     => gettext("Top margin :"),
                type      => 'Number',
                value   => sub { $self->imagelist->watermark_y(@_) },
            },
            {
                label     => gettext("Left margin :"),
                type      => 'Number',
                value   => sub { $self->imagelist->watermark_x(@_) },
            },            
        ]
    );

    $self->image_tags(
        sub { eval { $self->imagelist->current_image->site_tags(@_) } }
    );

    $self->piwigo_tags(
        sub { wxTheApp->pwg->tags }
    );	
}

sub _create_piwigo_tag {
    my ( $self, $name ) = @_;
    
    if(
        Wx::MessageBox( 
            sprintf(
                gettext("Do you want to create \"%s\" ?"), 
                $name,
            ),
            gettext("Piwigo search information"),
            wxYES_NO | wxICON_QUESTION, 
        ) == wxYES 
    ){    
    	$self->pwg->AddTags($name);
        $self->pwg->RefreshTags;
    }
}

sub _refreshFrame {
    my ( $self ) = @_;
    
    $self->_set_setting_properties;
    $self->_refresh_settings_panels_properties;
    map {
        $_->Refresh;	
    }
    (
        $self->image_prop_piwigo,
        $self->image_prop_exif,
        $self->image_prop_tags,
        $self->general_settings_panel,
        $self->resized_settings_panel,
        $self->thumbnail_settings_panel,
        $self->preview_settings_panel,
        $self->advanced_settings_panel,
        $self->watermark_settings_panel,
    );
    
    $self->manager->Update;
}


sub _destroy_settings_panels {
    my ( $self ) = @_;



    map {
        $self->manager->DetachPane(
            $_
        );
        $_->Show(0);
        $_->Destroy;
    }(
        $self->notebook_global_settings,
        $self->notebook_image_properties,
    );
}

# 
sub _initFrame {
    my ( $self ) = @_;
    
 
    $self->init_panels;

    $self->init_aui;
    $self->init_dnd_targets;

    if( $self->imagelist->wx_thumb_imglist->GetImageCount){
        printf("%s images\n", $self->imagelist->wx_thumb_imglist->GetImageCount); 
    	$self->ShowImageViewer;
        
        $self->imageviewer->Refresh(
            $self->imagelist->wx_thumb_imglist
        );
       
    }

}

sub _refresh_settings_panels_properties {
    my ( $self ) = @_;	

    $self->image_prop_piwigo->properties(
        $self->piwigo_properties
    );
    
    $self->image_prop_exif->properties(
        $self->exif_properties
    );


    $self->general_settings_panel->properties(
        $self->general_settings
    );    

    $self->resized_settings_panel->properties(
        $self->resized_settings
    );    

    $self->thumbnail_settings_panel->properties(
        $self->thumbnail_settings,
    );    

    $self->preview_settings_panel->properties(
        $self->preview_settings,
    );    

    $self->advanced_settings_panel->properties(
        $self->advanced_settings,
    );    

    $self->watermark_settings_panel->properties(
        $self->watermark_settings,
    );	
	
}

sub _init_settings_panels {
    my ( $self ) = @_;	

    $self->image_prop_piwigo(
        Uploader::GUI::wxPropertyGridPanel->new( 
            { 
                parentwnd       => $self,
                properties      => $self->piwigo_properties,
                frame_callbacks => [ 
                                          sub {
                                              $self->imageviewer->Refresh();
                                          },
                	           ],
            }
        )
    );

    $self->image_prop_exif(
        Uploader::GUI::wxPropertyGridPanel->new( 
            { 
                parentwnd       => $self,
                frame_callbacks => [],
                properties      => $self->exif_properties,
            }
        )
    );


    $self->general_settings_panel(
        Uploader::GUI::wxPropertyGridPanel->new( 
            { 
                parentwnd       => $self,
                properties      => $self->general_settings,
                frame_callbacks => [], 
            }
        )
    );    

    $self->resized_settings_panel(
        Uploader::GUI::wxPropertyGridPanel->new( 
            { 
                parentwnd       => $self,
                properties      => $self->resized_settings,
                frame_callbacks => [],

            }
        )    
    );    

    $self->thumbnail_settings_panel(
        Uploader::GUI::wxPropertyGridPanel->new( 
            { 
                parentwnd       => $self,
                properties      => $self->thumbnail_settings,
                frame_callbacks => [],

            }
        )    
    );    
    $self->preview_settings_panel(
        Uploader::GUI::wxPropertyGridPanel->new( 
            { 
                parentwnd       => $self,
                properties      => $self->preview_settings,
                frame_callbacks => [],

            }
        )    
    );    

    $self->advanced_settings_panel(
        Uploader::GUI::wxPropertyGridPanel->new( 
            { 
                parentwnd       => $self,
                properties      => $self->advanced_settings,
                frame_callbacks => [],

            }
        )    
    );    

    $self->watermark_settings_panel(
        Uploader::GUI::wxPropertyGridPanel->new(
            {
                parentwnd   => $self,
                properties  => $self->watermark_settings,
                frame_callbacks => [],
            }
        )
    );

    $self->image_prop_tags(
        Uploader::GUI::wxChoiceFilteredPanel->new( 
            { 
                parentwnd    => $self,
                choices      => $self->piwigo_tags,
                selection    => $self->image_tags,
                creation_callback => sub { $self->_create_piwigo_tag(@_) }, 
            }
        )    
    );    

    
    $self->general_settings_panel->Show(0);

    $self->image_preview(
        Wx::HtmlWindow->new(
            $self,
            -1,
            [-1,-1],
            [-1,-1],
        )
    );


    $self->image_prop_piwigo->Show(0);
    
    $self->image_prop_exif->Show(0);
	
}

sub init_panels {
    my ( $self ) = @_;	

    my $file = sprintf(
        "../locale/%s/gs.html",
        wxTheApp->locale->GetCanonicalName
    );

    $self->htmlhome(
        Uploader::GUI::wxHtmlWindow->new(
            $self, -1, [-1, -1], [450, 450]
        )
    );
    
    $self->htmlhome->LoadPage($file) if -e $file ;
    
    $self->htmlhome->InitHrefCallbacks(
        {
            new_album => sub {$self->OnAddCategories(@_) },
            add_photos => sub { $self->OnAddImages(@_) },
            upload_photos => sub { $self->ProcessImageSelection(@_)},	
        }
    );
    
    $self->imageviewer(
        Uploader::GUI::wxImageListCtrl->new( 
            { 
                parentwnd => $self,
                imagelist => $self->imagelist,
            }
        )
    );
    
    $self->_init_settings_panels;	
}

sub init_dnd_targets {
    my ( $self ) = @_;	

    $self->imageviewer->SetDropTarget( 
        DNDImageListDropTarget->new(
            $self->imageviewer 
        ) 
    );

    $self->tree->SetDropTarget( 
        DNDCategoryTreeDropTarget->new(
            $self->tree
        )
    );
	
}

sub init_aui {
    my ( $self ) = @_;

    my $url = wxTheApp->site_url;
    
    $url = gettext("empty - work Offline") if wxTheApp->use_offline;

    $self->manager->AddPane
      ( $self->create_notebook_imagelist, Wx::AuiPaneInfo->new->Name( "ImageViewer" )
        ->CenterPane->Resizable->CloseButton(0) );

    $self->manager->AddPane( 
        $self->create_tree, 
        Wx::AuiPaneInfo->new->Name( "categories" )
        ->Right->Position( 0 )->Resizable->CloseButton(0), 
    );



    $self->_init_aui_settings_panels;

    $self->toolbar(
        $self->create_toolbar
    );

    $self->manager->AddPane
      ( $self->toolbar, Wx::AuiPaneInfo->new->Name( "tb1" )
        ->ToolbarPane->Top->Row( 1 )->LeftDockable( 0 )->RightDockable( 0 ) ) if defined $self->toolbar;

    $self->SetSize( 
            $self->frameLayout->{pX}, 
            $self->frameLayout->{pY}, 
            $self->frameLayout->{W}, 
            $self->frameLayout->{H}, 
    );


    if($self->perspective){
        $self->manager->LoadPerspective($self->perspective);
    }
    else {
        $self->manager->GetPane("categories")->MinSize(300,100);

        $self->manager->GetPane("tb1")->Caption( gettext("Tools") );
        $self->manager->GetPane("image_preview")->Caption(gettext("Preview"))->Show(0);
        $self->manager->GetPane("getting_started")->Caption(gettext("Getting started"))->Float->Show(1);
        $self->manager->GetPane("photo_properties")->Caption(gettext("Photo properties"))->Float->Show(0);
        $self->manager->GetPane("global_settings")->Caption(gettext("Global settings"))->Float->Show(0);
    }

    $self->manager->GetPane("categories")->Caption(
          sprintf("%s - %s", sprintf("Piwigo %s", wxTheApp->branding->{categories}), $url )
    );
    
    $self->manager->Update;

}


sub _init_aui_settings_panels {
    my ( $self ) = @_;	

    $self->manager->AddPane
      ( $self->image_preview, Wx::AuiPaneInfo->new->Name( "image_preview" )
        ->Floatable(1)->Resizable->CloseButton(1));

    $self->manager->AddPane
      ( $self->htmlhome, Wx::AuiPaneInfo->new->Name( "getting_started" )
       ->Floatable(1)->Resizable->CloseButton(1) );

    $self->manager->AddPane
      ( $self->create_notebook_image_properties, Wx::AuiPaneInfo->new->Name( "photo_properties" )
        ->Floatable(1)->Resizable->CloseButton(1) );

    $self->manager->AddPane
      ( $self->create_notebook_global_settings, Wx::AuiPaneInfo->new->Name( "global_settings" )
        ->Floatable(1)->Resizable->CloseButton(1) );

}

sub OnPhotoProperties {
    my ( $self ) = @_;

    $self->manager->GetPane("photo_properties")->Show(1);
    $self->manager->Update();    
	
}

sub OnPreview {
    my ( $self ) = @_;

    $self->manager->GetPane("image_preview")->Float->Show(1);
    $self->manager->Update();    
	
}

sub OnGettingStarted {
    my ( $self ) = @_;

    $self->toolbar->EnableTool(100, 0 );
    $self->manager->GetPane("getting_started")->Float->Show(1);
    $self->manager->Update();    
	
}

sub OnGlobalSettings {
    my ( $self ) = @_;

    $self->toolbar->EnableTool(104, 0 );
    $self->manager->GetPane("global_settings")->Float->Show(1);
    $self->manager->Update();    
}

sub OnChooseLanguage {
    my ( $self ) = @_;	

  my $languages = [
             ["中文 (%s)", wxLANGUAGE_CHINESE, 'Chinese'],   
             ["Česky (%s)", wxLANGUAGE_CZECH, 'Czech'],   
             ["Dansk (%s)", wxLANGUAGE_DANISH, 'Danish'],   
             ["Deutsch (%s)", wxLANGUAGE_GERMAN, 'German'],   
             ["English (%s)", wxLANGUAGE_ENGLISH, 'English'],   
             ["Español (%s)", wxLANGUAGE_SPANISH, 'Spanish'],   
             ["Français (%s)", wxLANGUAGE_FRENCH, 'French'],   
             ["Italiano (%s)", wxLANGUAGE_ITALIAN, 'Italian'],   
             ["日本語 (にほんご) (%s)", wxLANGUAGE_JAPANESE, 'Japanese'],   
             ["Nederlands (%s)", wxLANGUAGE_DUTCH, 'Dutch'],   
             ["Polski (%s)", wxLANGUAGE_POLISH, 'Polish'],   
             ["Português Brasileiro (%s)", wxLANGUAGE_PORTUGUESE_BRAZILIAN, 'Portuguese Brazil'],   
             ["Português Portugal (%s)", wxLANGUAGE_PORTUGUESE, 'Portuguese Portugal'],   
             ["Русский (%s)", wxLANGUAGE_RUSSIAN, 'Russian'],
             ["Slovenčina (%s)", wxLANGUAGE_SLOVAK, 'Slovak'],
  ];

  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])
        )
    );
  }

  $dialog->Destroy;

}

sub OnDefaultPhotoNameChanged {
    my ( $self ) = @_;
    
    Wx::LogMessage("New default_photo_name %s", $self->imagelist->default_photo_name);	
}


sub create_notebook_imagelist {
    my( $self ) = @_;
    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [300, 450],
                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);

        my $imglistpage = [
            [
                $self->imageviewer, 
                gettext("Photo selection"),
                '../res/images.png', 
                wxBITMAP_TYPE_PNG,
            ],
        ];

    $self->notebook($book);
    $self->_populate_notebook($self->notebook, $imglistpage, 0);
    return $book;
}

sub create_notebook_image_properties {
    my( $self ) = @_;
    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [450, 450],
                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);
    my $pages = [    
        [
            $self->image_prop_piwigo, 
            "Piwigo",
        ],
        [
            $self->image_prop_tags, 
            "Tags",
        ],
        [
            $self->image_prop_exif, 
            "Exif",
        ],
    ];
    
    $self->_populate_notebook( $book, $pages );

    $self->notebook_image_properties($book);

    return $book;
}

sub create_notebook_global_settings {
    my( $self ) = @_;
    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [450, 450],
                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);
    my $pages = [    
        [
            $self->general_settings_panel, 
            gettext("General"),
        ],
        [
            $self->resized_settings_panel, 
            gettext("Resized"),
        ],
        [
            $self->thumbnail_settings_panel, 
            gettext("Thumbnail"),
        ],
        [
            $self->preview_settings_panel, 
            gettext("Preview"),
        ],
        [
            $self->advanced_settings_panel, 
            gettext("Advanced"),
        ],
        [
            $self->watermark_settings_panel,
            gettext("Watermark"),
        ]    
    ];
    
    $self->_populate_notebook( $book, $pages );

    $self->notebook_global_settings($book);

    return $book;
}




sub create_tree {
    my ( $self ) = @_;

    my $images = [
        map {
            Wx::Bitmap->new( $_, wxBITMAP_TYPE_PNG )
        	
        }
        (
          '../res/tree_pwg.png',
          '../res/tree_folder.png',
        )    
    ];

    $self->treeimglist( Wx::ImageList->new( 16, 16, 1 ) );
    map {
    	$self->treeimglist->Add($_);
    }
    @$images;

    
    $self->tree( 
        Wx::TreeCtrl->new( 
           $self, 
           -1, 
           wxDefaultPosition, 
           wxDefaultSize, 
           wxBORDER_NONE|
           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 ;
    
    #$self->tree->ExpandAll;

}


# 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];
      eval {
      	$name = is_utf8($name) ?  decode('UTF-8', $name) : $name;
      };
      if($@){
          $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 _populate_notebook {
    my ( $self, $book, $pages, $position ) = @_;	

    my $i = 0;
    map {
        my $icon = Wx::Icon->new();
        eval { $icon->LoadFile($_->[2], $_->[3]) ; }
            if defined $_->[2];
        my $nb_icon = Wx::Bitmap->new( $icon );
        defined $position ?
            $book->InsertPage($position, $_->[0],
                    $_->[1], 1, $nb_icon )
                          :
            $book->AddPage($_->[0],
                    $_->[1], 0, $nb_icon );

        $i++;
    } @$pages;

}


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
    	)->SetBitmap(Wx::Bitmap->new($_->[3],wxBITMAP_TYPE_PNG));
    }
    (
        # workaround : first item does not show bitmap
        [
            0, 
            "",
            "",
            '../res/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},
            ),
            '../res/mnu_folder_new.png',
        ],
        [
            2+$ID_TREE_CTX_MENU, 
            gettext("Refresh"),
            sprintf(
                "Refresh %s list.",
                wxTheApp->branding->{category},
            ),
            '../res/mnu_refresh.png',
        ],
        [
            3+$ID_TREE_CTX_MENU, 
            gettext("Expand all"),
            sprintf(
                "Expand %s list.",
                wxTheApp->branding->{category},
            ),
            '../res/mnu_expandall.png',
        ],
        [
            4+$ID_TREE_CTX_MENU, 
            gettext("Collapse all"),
            sprintf(
                "Collapse %s list.",
                wxTheApp->branding->{category},
            ),
            '../res/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]
    	)->SetBitmap(Wx::Bitmap->new($_->[3],wxBITMAP_TYPE_PNG));
    }
    (
        # workaround : first item does not show bitmap
        [
            0, 
            "",
            "",
            '../res/mnu_properties.png',
        ],
        [
            1+$ID_IMAGEVIEWER_CTX_MENU, 
            gettext("Properties"),
            gettext("Modify photo properties"),
            '../res/mnu_properties.png',
        ],
        [
            2+$ID_IMAGEVIEWER_CTX_MENU, 
            gettext("Preview"),
            gettext("Display photo preview"),
            '../res/mnu_preview.png',
        ],
    );
	
    $ctx_mnu->Delete(0);
    $self->imageviewer_mnu(
         $ctx_mnu
    );	
}

sub _initEventHandlers {
    my ( $self ) = @_ ;
	
    Wx::Event::EVT_MENU( $self, 100, \&OnGettingStarted );
    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 );
    EVT_TREE_SEL_CHANGED( $self, $self->tree, \&OnTreeSelChanged );
    EVT_TREE_ITEM_RIGHT_CLICK( $self, $self->tree, \&OnTreeItemRightClick );
    EVT_TREE_END_LABEL_EDIT( $self, $self->tree, \&OnTreeEndLabelEdit );

    EVT_LIST_END_LABEL_EDIT( $self, $self->imageviewer, \&OnImageViewerEndLabelEdit );
    EVT_LIST_ITEM_ACTIVATED( $self, $self->imageviewer, \&OnImageViewerItemActivated );
    EVT_LIST_ITEM_SELECTED($self, $self->imageviewer, \&OnImageViewerItemSelected) ;
    EVT_LIST_ITEM_RIGHT_CLICK($self, $self->imageviewer, \&OnImageViewerItemRightClick) ;

    EVT_LIST_KEY_DOWN($self, $self->imageviewer, \&OnImageViewerKeyDown) ;

    EVT_CLOSE( $self, \&OnClose );
    Wx::Event::EVT_UPDATE_UI( $self, $self, \&OnUpdateUI );


    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 );


}

{
  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|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;
#    $event->Skip;
  }
}

sub OnUpdateUI {
    my( $self, $event ) = @_;
    
    if( $self->manager ){
        if($self->manager->GetPane("global_settings")->IsShown){
            $self->toolbar->EnableTool(104, 0);         	
        }
        else{
            $self->toolbar->EnableTool(104, 1);         	
        }

        if($self->manager->GetPane("getting_started")->IsShown){
            $self->toolbar->EnableTool(100, 0);         	
        }
        else{
            $self->toolbar->EnableTool(100, 1);         	
        }
    }

}

sub OnRemoveImages {
    my( $self, $event ) = @_;

    
    $self->imagelist->RemoveImageSelection;
    $self->imageviewer->Refresh;	

    $self->image_preview->SetPage(
        "<html></html>"
    ) if !$self->imageviewer->GetItemCount;

}

sub SetNewFiles {
    my ( $self, $file_paths ) = @_;

    $self->ShowImageViewer();
    $self->progressdlg( 
        Uploader::GUI::wxImageProcessingProgressDlg->new(
            { 
                title => gettext("Image processing progress information"),
                bt_label => gettext("Cancel image processing"), 
             }
        )        
    );
    $self->progressdlg->Show(1);
    Wx::Yield();

    
    my $files = [
        map {
            # to make sure that unicode chars in filenames are supported
            {
                ANSIPathName => $^O =~ /MSWin32/ ? Win32::GetANSIPathName($_) : encode('iso-8859-1', $_),
                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->image_prop_piwigo->Refresh;
}

sub OnImageViewerItemActivated {
    my( $self, $event ) = @_;
    
    $self->current_imageviewer_index(
        $event->GetIndex
    );

    $self->OnPhotoProperties;
}


sub OnImageViewerItemSelected {
    my( $self, $event ) = @_;
  
    my $indx = $event->GetIndex;

    $self->_on_imageviewer_item_selected($indx);

    $event->Skip;
}

sub _on_imageviewer_item_selected {
    my ( $self, $index ) = @_;	

    $self->current_imageviewer_index($index);
    $self->imagelist->SetCurrentImage($index);
    
    $self->imagelist->image_selection(
        $self->imageviewer->GetSelectedItems
    );

    $self->_image_preview_refresh if @{$self->imagelist->image_selection} < 2;
    
    $self->manager->Update;
    
    $self->image_prop_piwigo->Refresh;
    $self->image_prop_exif->Refresh;
    $self->image_prop_tags->Refresh;

}

sub _image_preview_refresh {
    my ( $self ) = @_;	


    my $html_src = sprintf("
      <html>
         <body>
             <img src=\"%s\"/>
         </body>
      </html>
      ",
      $self->imagelist->current_image->preview_file, 
    );
        
    $self->image_preview->SetPage(
        $html_src
    );

    my $bmp = Wx::Bitmap->new( 
            $self->imagelist->current_image->preview_file, 
            $self->GetWxBitmapType($self->imagelist->type), 
        );

    my $size = [40+$bmp->GetWidth, 60+$bmp->GetHeight];

    $self->manager->GetPane("image_preview")->FloatingSize($size);
    
}

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
        );
    }	

}

sub OnUploadImages {
    my( $self, $event ) = @_;

    eval {
        $self->ProcessImageSelection();    
    };
}

# remove image from imagelist when uploaded
sub UploadImagesViewerRefresh {
    my ( $self ) = @_;	

    $self->imageviewer->Refresh;
    Wx::Yield();
}

sub UploadProgressMessageRefresh {
    my ( $self, $msg ) = @_;	

    $self->upload_progressdlg->processing(
        $msg   
    );	

    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, $ratio ) = @_;	

    $ratio = $self->imagelist->count > 1 ? 1 : $ratio; 
    eval {
        $self->upload_progressdlg->progress(
            $ratio*$self->imagelist->count * ( 100/scalar @{$self->imagelist->image_selection} )
        );
        $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;

    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
    );

    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(
            Uploader::GUI::wxImageProcessingProgressDlg->new(
                { 
                    title    => gettext("Image upload progress information"),
                    bt_label => gettext("Cancel upload"), 
                 }
            )        
        );
        # 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 %s", 
                gettext("Please select a valid target"),
                wxTheApp->branding->{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->perspective(
        $self->manager->SavePerspective
    );
    
    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;

    $self->Destroy;
}


sub create_toolbar {
    my( $self ) = @_;

    my $tb = Wx::ToolBar->new( $self, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT );
    $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]);
    }
    (
        [
            100, 
            gettext("Getting started"), 
            '../res/tb_getting_started.png', 
            wxBITMAP_TYPE_PNG, 
            1, 
            '../res/tb_getting_started.png', 
            gettext("Display getting started panel")
        ],
        [
            101, 
            gettext("Add photo to selection"), 
            '../res/tb_add.png', 
            wxBITMAP_TYPE_PNG, 
            1, 
            '../res/tb_add.png', 
            gettext("Add photo to selection for resizing and uploading")
        ],
        [
            102, 
            gettext("Remove photo from selection"), 
            '../res/tb_remove.png', 
            wxBITMAP_TYPE_PNG, 
            1, 
            '../res/tb_remove.png',
            gettext("Remove photo from selection. Files are not deleted ")
        ],
        [
            103, 
            gettext("Upload to Piwigo"), 
            '../res/tb_upload.png', 
            wxBITMAP_TYPE_PNG, 
            wxTheApp->use_offline ? 0 : 1, 
            '../res/tb_upload.png',
            gettext("Upload photos to Piwigo.")
        ],
        [
            104, 
            gettext("Global settings"), 
            '../res/tb_settings.png', 
            wxBITMAP_TYPE_PNG, 
            0, 
            '../res/tb_settings.png',
            gettext("Change global settings.")
        ],
        [
            105, 
            gettext("Language choice"), 
            '../res/tb_i18n.png', 
            wxBITMAP_TYPE_PNG, 
            1, 
            '../res/tb_i18n.png',
            gettext("Language choice")
        ],
    
    );

    if($@){
    	undef $tb;
    }
    else{
        $tb->Realize;
    }

    return $tb;
}


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 ) = @_;

    $self->manager->UnInit;
}



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
         /;

__PACKAGE__->mk_accessors( 
    qw/
          tree
          frame
      /
);

sub new {
  my ( $class, $tree ) = @_;
  my $self = $class->SUPER::new();

  $self->tree($tree);
  $self->frame($tree->GetParent);
  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;
      	   
           $self->frame->imagelist->categories(
               [
                   map {
                       $self->tree->GetPlData( $_ )->{id};
                   }
                   @items
               ]
           );
           
      	   $self->frame->imagelist->image_selection($VAR1);
      	   $self->frame->ProcessImageSelection ;
      }	
  };
}

1;