source: extensions/pLoader/trunk/src/Uploader/GUI/wxFrameAUI.pm @ 4504

Last change on this file since 4504 was 4504, checked in by ronosman, 14 years ago

Feature 1332 added : new list and thumbnail display mode for photo selection.

  • Property svn:eol-style set to LF
File size: 63.3 KB
Line 
1# +-----------------------------------------------------------------------+
2# | pLoader - a Perl photo uploader for Piwigo                            |
3# +-----------------------------------------------------------------------+
4# | Copyright(C) 2008      Piwigo Team                  http://piwigo.org |
5# +-----------------------------------------------------------------------+
6# | This program is free software; you can redistribute it and/or modify  |
7# | it under the terms of the GNU General Public License as published by  |
8# | the Free Software Foundation                                          |
9# |                                                                       |
10# | This program is distributed in the hope that it will be useful, but   |
11# | WITHOUT ANY WARRANTY; without even the implied warranty of            |
12# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
13# | General Public License for more details.                              |
14# |                                                                       |
15# | You should have received a copy of the GNU General Public License     |
16# | along with this program; if not, write to the Free Software           |
17# | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
18# | USA.                                                                  |
19# +-----------------------------------------------------------------------+
20package Uploader::GUI::wxFrameAUI;
21use strict;
22use Carp;
23use Wx;
24use Wx::DND;
25use Wx qw/
26             wxYES_NO
27             wxYES
28             wxICON_QUESTION
29             wxITEM_NORMAL
30             wxNullBitmap
31             wxID_OK
32             wxDEFAULT_FRAME_STYLE
33             wxVERTICAL
34             wxGROW
35             wxBITMAP_TYPE_JPEG
36             wxBITMAP_TYPE_GIF
37             wxBITMAP_TYPE_PNG
38                         wxBITMAP_TYPE_ANY
39             wxTB_FLAT
40             wxSIZE
41             wxWHITE
42             wxBLACK
43             wxID_CANCEL
44             wxFD_OPEN
45             wxFD_MULTIPLE
46             wxLI_HORIZONTAL
47             wxALIGN_CENTER_VERTICAL
48             wxALL
49             wxDefaultPosition
50             wxDefaultSize
51             wxTheApp
52             wxIMAGE_LIST_NORMAL
53             wxAUI_NB_TAB_MOVE
54             wxAUI_NB_TAB_SPLIT
55             wxNO_BORDER
56             wxTE_MULTILINE
57             wxTE_READONLY
58             wxITEM_NORMAL
59             wxCLIP_CHILDREN
60             wxBORDER_NONE
61             wxNullBitmap
62             wxTR_MULTIPLE
63             wxTR_EXTENDED
64             wxTR_HIDE_ROOT
65             wxTR_HAS_BUTTONS
66             wxTR_EDIT_LABELS
67             wxMAXIMIZE
68             wxOK
69             wxICON_EXCLAMATION
70             wxICON_INFORMATION
71             WXK_DELETE
72         /;
73use base qw/Wx::Frame Class::Accessor::Fast/;
74use File::Spec;
75use Wx::Locale qw/:default/;
76use POSIX qw(ceil floor);
77
78require Win32 if($^O =~ /MSWin32/);
79
80
81my @properties = 
82    qw/
83          progressdlg
84          upload_progressdlg
85          imageviewer
86                  imageviewer_img
87          tree
88          tree_root
89          treeimglist
90          tree_item_default
91          topsizer
92          pwg
93          manager
94          logwnd
95          oldlogwnd
96          htmlhome
97          notebook
98          categories
99          imagelist
100          image_preview
101          image_prop_piwigo
102          image_prop_exif
103          image_prop_tags
104          notebook_image_properties
105          notebook_global_settings
106          general_settings_panel
107          resized_settings_panel
108          thumbnail_settings_panel
109                  hd_settings_panel
110          advanced_settings_panel
111          watermark_settings_panel
112          piwigo_properties
113          exif_properties
114          general_settings
115          resized_settings
116          thumbnail_settings
117                  hd_settings
118          advanced_settings
119          watermark_settings
120          toolbar
121          branding
122          perspective
123          current_imageviewer_index
124          imageviewer_mnu
125          tree_mnu
126          imageviewer_select_multi
127          frameLayout
128          piwigo_tags
129          image_tags
130                  piwigo_photo_properties
131                  dlg_piwigo_photo_properties
132                  piwigo_photo_properties_tags
133                  image_preview_refresh
134                  imageviewer_refresh
135                  imageviewer_item_refresh
136      /;
137__PACKAGE__->mk_accessors( @properties );
138
139use Wx::Event 
140    qw/
141          EVT_MENU
142          EVT_TREE_SEL_CHANGED
143          EVT_TREE_END_LABEL_EDIT
144          EVT_CLOSE
145          EVT_LIST_END_LABEL_EDIT
146          EVT_LIST_ITEM_SELECTED
147          EVT_LIST_ITEM_ACTIVATED
148          EVT_LIST_ITEM_RIGHT_CLICK
149          EVT_TREE_ITEM_RIGHT_CLICK
150          EVT_LIST_KEY_DOWN
151          EVT_UPDATE_UI       
152      /;
153     
154use Uploader::GUI::wxImageListCtrl;
155use Uploader::GUI::wxImageProcessingProgressDlg;
156use Uploader::GUI::wxChoiceFilteredPanel;
157use Uploader::GUI::wxImageReuploadDlg;
158use Wx::Html;
159use Uploader::GUI::wxImagePreview;
160use Uploader::GUI::wxHtmlWindow;
161use Data::Dumper;
162use Wx::AUI;
163use Storable;
164use Uploader::GUI::wxPropertyGridPanel;
165use Uploader::GUI::wxPhotoProperties;
166use utf8;
167$|=1;
168
169my $ID_TREE_CTX_MENU = 20000 ;
170my $ID_IMAGEVIEWER_CTX_MENU = 20100 ;
171
172sub new {
173  my( $class, $params ) = @_;
174  my( $self ) = $class->SUPER::new( 
175                                      undef, 
176                                      -1, 
177                                      $params->{title},
178                                      wxDefaultPosition,
179                                      wxDefaultSize, 
180                                      wxDEFAULT_FRAME_STYLE
181                                   );
182
183    $self->perspective(
184        $params->{perspective}
185    );
186
187   
188    $self->current_imageviewer_index(
189        $params->{imageviewer_index}||0
190    );
191   
192    $self->frameLayout(
193        $params->{frameLayout} || { 'pX' => -1, 'pY' => -1, W => 800, H => 600 }
194    );
195
196    $self->pwg( $params->{pwg} );
197    $self->imagelist( $params->{imagelist} );
198
199    # callback for GUI refresh : add thumbnail images to the imageviewer control
200    $self->imagelist->SetNewFilesViewerRefreshCallback(
201        sub { $self->SetNewFilesViewerRefresh(@_) }
202    );
203
204    # callback for GUI refresh : progress dialog display of thumbnail image being created
205    $self->imagelist->SetNewFilesProgressCallback(
206        sub { $self->SetNewFilesProgress(@_) }
207    );
208
209    $self->imagelist->SetNewFilesDisplayEndInfoCallback(
210        sub { $self->SetNewFilesDisplayEndInfo(@_) }
211    );
212
213
214    # callback for GUI refresh : remove thumbnail images from imageviewer control
215    $self->imagelist->UploadImagesViewerCallback(
216        sub { $self->UploadImagesViewerRefresh(@_) }
217    );
218       
219        $self->imagelist->ReuploadCallback(
220            sub {
221                    Uploader::GUI::wxImageReuploadDlg->new(
222            { 
223                                title      => gettext("Photo update management"),
224                properties => {
225                                        $main::ID_REUPLOAD_ACTION_FILES        => { 
226                                                                                                                    selection=>sub {$self->imagelist->reupload_action_files(@_)},
227                                                                                                                                                                label=>gettext("What shall we do with files? (thumbnail, resized, high resolution)"),
228                                                                                labels=>[
229                                                                                                                                                                           gettext("nothing"),
230                                                                                                                                                                           gettext("replace"),
231                                                                                                                                                                       ],                                                                                                                                                               
232                                                                                                            },
233                                                                    $main::ID_REUPLOAD_ACTION_PROPERTIES   => { 
234                                                                                                                    selection=>sub{$self->imagelist->reupload_action_properties(@_)},
235                                                                                                                                                                label=>gettext("What shall we do with single value properties?(caption, comment, author, create date)"),
236                                                                                labels=>[
237                                                                                                                                                                           gettext("nothing"),
238                                                                                                                                                                           gettext("fill if empty (only replace properties currently empty in Piwigo)"),
239                                                                                                                                                                           gettext("replace"),
240                                                                                                                                                                       ],                                                                                                                                                               
241                                                                                                                  },
242                                                                        $main::ID_REUPLOAD_ACTION_PROPERTIES_M => { 
243                                                                                                                    selection=>sub{$self->imagelist->reupload_action_properties_m(@_)},
244                                                                                                                                                                label=>gettext("What shall we do with multiple values properties? (categories, tags)"),
245                                                                                labels=>[
246                                                                                                                                                                           gettext("nothing"),
247                                                                                                                                                                           gettext("append (keep existing and add new)"),
248                                                                                                                                                                           gettext("replace"),
249                                                                                                                                                                       ],                                                                                                                                                               
250                                                                                                                  },
251                                                                        $main::ID_REUPLOAD_NOT_ASK             => { 
252                                                                                                                    value=>sub{$self->imagelist->reupload_not_ask(@_)}, 
253                                                                                label=>gettext("Do not ask me again"),                                                                                                                                                         
254                                                                                                                  },
255                                                                        $main::ID_REUPLOAD_TEXT                => { 
256                                                                                label=>gettext("A least one photo has already been added in the past."),                                                                                                                                                               
257                                                                                                                  },
258                                                },
259            }
260                        )->ShowModal();
261                }
262        );
263
264
265    # callback for GUI refresh : progress dialog display current uploaded image
266    $self->imagelist->progress_thumbnail_refresh(
267        sub { $self->UploadProgressThumbnailRefresh(@_) }
268    );
269
270    $self->imagelist->progress_msg_refresh(
271        sub { $self->UploadProgressMessageRefresh(@_) }
272    );
273
274    $self->imagelist->progress_msg_details_refresh(
275        sub { $self->UploadProgressMessageDetailsRefresh(@_) }
276    );
277
278    $self->imagelist->progressbar_refresh(
279        sub { $self->UploadProgressBarRefresh(@_) }
280    );
281   
282    $self->imagelist->progress_endinfo_refresh(
283        sub { $self->UploadDisplayEndInfo(@_) }
284    );
285
286
287    $self->imagelist->pwg(
288        $self->pwg
289    );
290
291    $self->imagelist->categories(
292        []
293    );
294
295
296    $self->manager( Wx::AuiManager->new );
297    $self->manager->SetManagedWindow( $self );
298    $self->_set_setting_properties;
299    $self->_initFrame;
300    $self->_initMenus;
301    $self->_initEventHandlers;
302    $self->_initImgTypes;   
303
304        # only refresh when calling event is finished
305        Wx::Event::EVT_UPDATE_UI(
306            $self,
307            $self,
308                sub {
309            my ( $self, $event ) = @_;
310                if ( $self->image_preview_refresh and $self->image_preview->IsShown ){
311                $self->_image_preview_refresh; 
312                $self->image_preview->Refresh;
313                                $self->image_preview_refresh(0);
314                    }
315                       
316                        if($self->imageviewer_refresh){
317                            $self->imageviewer->Refresh;
318                                $self->imageviewer_refresh(0);
319                        }
320
321                        if($self->imageviewer_item_refresh){
322                            $self->imageviewer->ItemRefresh(
323                                    $self->current_imageviewer_index
324                                );
325                                $self->imageviewer_item_refresh(0);
326                        }
327                },
328        );
329
330    $self->imageviewer->SelectItem(
331        $self->current_imageviewer_index
332    ) if $self->imageviewer->GetItemCount;
333   
334    $self;
335}
336
337
338sub _initImgTypes {
339    my ( $self ) = @_;
340
341    $self->{IMGTYPE} = {
342             'jpg' => wxBITMAP_TYPE_JPEG,
343             'gif' => wxBITMAP_TYPE_GIF,
344             'png' => wxBITMAP_TYPE_PNG,
345    };
346}
347
348
349sub GetWxBitmapType {
350    my ( $self, $type ) = @_;
351   
352    $self->{IMGTYPE}->{$type};
353}
354
355
356
357sub _set_setting_properties {
358    my ( $self ) = @_;
359
360    $self->piwigo_photo_properties(
361        {
362                    $main::CAPTION => { label=>gettext("Photo caption :")},
363                        $main::PHOTO_PROPERTIES_CAPTION => { 
364                                                               value => sub { $self->imagelist->current_image->site_name(@_) },
365                                                                                                   frame_callback => sub { $self->imageviewer_item_refresh(1); },
366                                                           },
367                    $main::COMMENT => { label=>gettext("Comment :")},
368                        $main::PHOTO_PROPERTIES_COMMENT => { 
369                                                               value => sub { $self->imagelist->current_image->site_comment(@_) },
370                                                                                                   frame_callback => sub { $self->imageviewer_item_refresh(1); },
371                                                           },
372                    $main::AUTHOR => { label=>gettext("Author :")},
373                        $main::PHOTO_PROPERTIES_AUTHOR => { 
374                                                               value => sub { $self->imagelist->current_image->site_author(@_) },
375                                                                                                   frame_callback => sub { $self->imageviewer_item_refresh(1); },
376                                                           },
377                    $main::TAGS => { label=>gettext("Tags :")},
378                    $main::CREATE_DATE => { label=>gettext("Create date :")},
379                        $main::PHOTO_PROPERTIES_CREATE_DATE => { 
380                                                               value => sub { $self->imagelist->current_image->create_date(@_) },
381                                                                                                   frame_callback => sub { $self->imageviewer_item_refresh(1); },
382                                                           },
383                    $main::PRIVACY_LEVEL => { label=>gettext("Who can see the photo?")},
384                        $main::PHOTO_PROPERTIES_PRIVACY_LEVEL => {
385                                                         selection => sub { $self->imagelist->current_image->privacy_level(@_)},
386                                                         choices => wxTheApp->privacy_level_choices,                                                                                                                       ,                                                                                                             
387                                                                 },
388                }
389    ); 
390
391    $self->piwigo_properties(
392        [
393            {
394                label          => gettext("Photo caption :"),
395                value          => sub { $self->imagelist->current_image->site_name(@_) },
396                frame_callback => sub { $self->imageviewer_item_refresh(1) },
397            },
398            {
399                label => gettext("Comment :"),
400                value => sub { $self->imagelist->current_image->site_comment(@_) },
401                type  => "LongText",
402            },
403            {
404                label => gettext("Author :"),
405                value => sub { $self->imagelist->current_image->site_author(@_) },
406            },
407            {
408                label    => gettext("File name :"),
409                value    => sub { $self->imagelist->current_image->file(@_) },
410                readonly => 1,
411            },
412            {
413                label    => gettext("Create date :"),
414                value    => sub { $self->imagelist->current_image->create_date(@_) },
415                readonly => 1,
416            },
417        ]   
418    );
419
420    $self->exif_properties(
421        [
422            {
423                label    => gettext("Create date :"),
424                value    => sub { $self->imagelist->current_image->create_date }, 
425                readonly => 1,
426            }, 
427            {
428                label    => gettext("Model :"),
429                value    => sub { $self->imagelist->current_image->exif_tag('Model') }, 
430                readonly => 1,
431            }, 
432            {
433                label    => gettext("Width :"),
434                value    => sub { $self->imagelist->current_image->exif_tag('ImageWidth') }, 
435                readonly => 1,
436            }, 
437            {
438                label    => gettext("Height :"),
439                value    => sub { $self->imagelist->current_image->exif_tag('ImageHeight') }, 
440                readonly => 1,
441            }, 
442            {
443                label    => gettext("Orientation :"),
444                value    => sub { $self->imagelist->current_image->exif_tag('Orientation') }, 
445                readonly => 1,
446            }, 
447            {
448                label    => "ISO :",
449                value    => sub { $self->imagelist->current_image->exif_tag('ISO') }, 
450                readonly => 1,
451            }, 
452            {
453                label    => gettext("Shutter speed :"),
454                value    => sub { $self->imagelist->current_image->exif_tag('ExposureTime') }, 
455                readonly => 1,
456            }, 
457            {
458                label    => gettext("Aperture :"),
459                value    => sub { $self->imagelist->current_image->exif_tag('ApertureValue') }, 
460                readonly => 1,
461            }, 
462            {
463                label    => gettext("Focal length :"),
464                value    => sub { $self->imagelist->current_image->exif_tag('FocalLength') }, 
465                readonly => 1,
466            }, 
467            {
468                label    => gettext("Lens :"),
469                value    => sub { $self->imagelist->current_image->exif_tag('Lens') }, 
470                readonly => 1,
471            }, 
472        ]
473    );   
474
475
476    $self->general_settings(
477        [
478            {
479                label     => gettext("Default author :"),
480                value   => sub { $self->imagelist->author(@_) },
481            },
482            {
483                label     => gettext("Default photo caption :"),
484                type      => 'Choice',
485                value   => sub { $self->imagelist->default_photo_name(@_) },
486                choice  => [
487                               map { gettext $_ } @{wxTheApp->default_photo_names}
488                           ],
489                pre_process => sub { my ( $value ) = @_; wxTheApp->eng_default_photo_names->{$value} },
490            },
491            {
492                label     => gettext("Photo caption  prefix :"),
493                value   => sub { $self->imagelist->default_name_prefix(@_) },
494            },
495            {
496                label     => gettext("Resize site image :"),
497                type      => 'Bool',
498                value   => sub { $self->imagelist->create_resized(@_) },
499            },
500            {
501                label     => gettext("Auto rotate image :"),
502                type      => 'Bool',
503                value   => sub { $self->imagelist->auto_rotate(@_) },
504            },
505            {
506                label     => gettext("Upload high definition  :"),
507                type      => 'Choice',
508                choice  => [
509                               map { gettext $_ } @{wxTheApp->upload_hd}
510                           ],
511                pre_process => sub { my ( $value ) = @_; wxTheApp->eng_upload_hd->{$value} },
512                value   => sub { $self->imagelist->upload_hd(@_) },
513            },
514            {
515                label     => gettext("Remove uploaded photo from selection :"),
516                type      => 'Bool',
517                value   => sub { $self->imagelist->remove_uploaded_from_selection(@_) },
518            },
519        ]   
520    );
521   
522    $self->resized_settings(
523        [
524            {
525                label     => gettext("Site image width :"),
526                type      => 'Number',
527                value   => sub { $self->imagelist->resize_w(@_) },
528            },
529            {
530                label     => gettext("Site image height :"),
531                type      => 'Number',
532                value   => sub { $self->imagelist->resize_h(@_) },
533            },
534            {
535                label     => gettext("Site image jpeg quality :"),
536                type      => 'Number',
537                value   => sub { $self->imagelist->quality(@_) },
538            },
539            {
540                label     => gettext("Site image filter :"),
541                type      => 'Choice',
542                value   => sub { $self->imagelist->filter(@_) },
543                choice    => [ qw/Point Box Triangle Hermite Hanning Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos Bessel Sinc/ ],
544            },
545            {
546                label     => gettext("Site image blur :"),
547                type      => 'Float',
548                value   => sub { $self->imagelist->blur(@_) },
549            },
550            {
551                label     => gettext("Site image interlace :"),
552                type      => 'Choice',
553                value   => sub { $self->imagelist->interlace(@_) },
554                choice    => [ qw/None Line Plane Partition JPEG GIF PNG/ ],
555            },
556        ]   
557    );
558
559    $self->hd_settings(
560        [
561            {
562                label     => gettext("HD image width :"),
563                type      => 'Number',
564                value   => sub { $self->imagelist->hd_w(@_) },
565            },
566            {
567                label     => gettext("HD image height :"),
568                type      => 'Number',
569                value   => sub { $self->imagelist->hd_h(@_) },
570            },
571            {
572                label     => gettext("HD image jpeg quality :"),
573                type      => 'Number',
574                value   => sub { $self->imagelist->hd_quality(@_) },
575            },
576            {
577                label     => gettext("HD image filter :"),
578                type      => 'Choice',
579                value   => sub { $self->imagelist->hd_filter(@_) },
580                choice    => [ qw/Point Box Triangle Hermite Hanning Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos Bessel Sinc/ ],
581            },
582            {
583                label     => gettext("HD image blur :"),
584                type      => 'Float',
585                value   => sub { $self->imagelist->hd_blur(@_) },
586            },
587            {
588                label     => gettext("HD image interlace :"),
589                type      => 'Choice',
590                value   => sub { $self->imagelist->hd_interlace(@_) },
591                choice    => [ qw/None Line Plane Partition JPEG GIF PNG/ ],
592            },
593        ]   
594    );
595       
596    $self->thumbnail_settings(
597        [
598            {
599                label     => gettext("Site thumbnail size :"),
600                type      => 'Number',
601                value   => sub { $self->imagelist->thumb_size(@_) },
602            },
603            {
604                label     => gettext("Site thumbnail jpeg quality :"),
605                type      => 'Number',
606                value   => sub { $self->imagelist->th_quality(@_) },
607            },
608            {
609                label     => gettext("Photo selection thumbnail size :"),
610                type      => 'Number',
611                value   => sub { $self->imagelist->wx_thumb_size(@_) },
612            },
613            {
614                label     => gettext("Photo selection thumbnail jpeg quality :"),
615                type      => 'Number',
616                value   => sub { $self->imagelist->wx_quality(@_) },
617            },
618        ]   
619    );
620   
621
622    $self->advanced_settings(
623        [
624            {
625                label     => gettext("Transfert chunk size :"),
626                type      => 'Number',
627                value   => sub { wxTheApp->chunk_size(@_) },
628            },
629        ]   
630    );
631
632    $self->watermark_settings(
633        [
634            {
635              label  => gettext("Activate watermark :"),
636              type   => 'Bool',
637              value  => sub { $self->imagelist->watermark_activate(@_) },
638            },
639            {
640              label => gettext("Activate watermark on high definition :"),
641              type  => 'Bool',
642              value => sub { $self->imagelist->watermark_activate_pwg_high(@_) },
643            },
644            {
645              label  => gettext("Text :"),
646              value  => sub { $self->imagelist->watermark_text(@_) },
647            },
648            {
649                label     => gettext("Text size :"),
650                type      => 'Number',
651                value   => sub { $self->imagelist->watermark_text_size(@_) },
652            },
653            {
654                label     => gettext("Color :"),
655                type      => 'Choice',
656                value     => sub { $self->imagelist->watermark_color(@_) },
657                choice    => [
658                               map { gettext $_ } @{wxTheApp->colors}
659                             ],
660                pre_process => sub { my ( $value ) = @_; wxTheApp->eng_colors->{$value} },
661            },           
662            {
663                label     => gettext("Position :"),
664                type      => 'Choice',
665                value   => sub { $self->imagelist->watermark_position(@_) },
666                choice  => [
667                               map { gettext $_ } @{wxTheApp->positions}
668                           ],
669                pre_process => sub { my ( $value ) = @_; wxTheApp->eng_positions->{$value} },
670            },
671            {
672                label     => gettext("Top margin :"),
673                type      => 'Number',
674                value   => sub { $self->imagelist->watermark_y(@_) },
675            },
676            {
677                label     => gettext("Left margin :"),
678                type      => 'Number',
679                value   => sub { $self->imagelist->watermark_x(@_) },
680            },           
681        ]
682    );
683
684    $self->image_tags(
685        sub { eval { $self->imagelist->current_image->site_tags(@_) } }
686    );
687
688    $self->piwigo_tags(
689        sub { wxTheApp->pwg->tags }
690    ); 
691}
692
693sub _create_piwigo_tag {
694    my ( $self, $name ) = @_;
695   
696    if(
697        Wx::MessageBox( 
698            sprintf(
699                gettext("Do you want to create \"%s\" ?"), 
700                $name,
701            ),
702            gettext("Piwigo search information"),
703            wxYES_NO | wxICON_QUESTION, 
704        ) == wxYES
705    ){   
706        $self->pwg->AddTags($name);
707        $self->pwg->RefreshTags;
708    }
709}
710
711sub _refreshFrame {
712    my ( $self ) = @_;
713   
714    $self->_set_setting_properties;
715    $self->_refresh_settings_panels_properties;
716    map {
717        $_->Refresh;   
718    }
719    (
720        $self->image_prop_piwigo,
721        $self->image_prop_exif,
722        $self->image_prop_tags,
723        $self->general_settings_panel,
724        $self->resized_settings_panel,
725        $self->thumbnail_settings_panel,
726        $self->hd_settings_panel,
727        $self->advanced_settings_panel,
728        $self->watermark_settings_panel,
729                $self->piwigo_photo_properties_tags
730    );
731   
732    $self->manager->Update;
733}
734
735#
736sub _initFrame {
737    my ( $self ) = @_;
738   
739 
740    $self->init_panels;
741
742    $self->init_aui;
743    $self->init_dnd_targets;
744
745    if( $self->imagelist->wx_thumb_imglist->GetImageCount){
746        printf("%s images\n", $self->imagelist->wx_thumb_imglist->GetImageCount); 
747        $self->ShowImageViewer;
748       
749        $self->imageviewer->Refresh(
750            $self->imagelist->wx_thumb_imglist
751        );
752       
753    }
754
755}
756
757sub _refresh_settings_panels_properties {
758    my ( $self ) = @_; 
759
760        $self->dlg_piwigo_photo_properties->properties(
761        $self->piwigo_photo_properties
762        );
763       
764    $self->image_prop_piwigo->properties(
765        $self->piwigo_properties
766    );
767   
768    $self->image_prop_exif->properties(
769        $self->exif_properties
770    );
771
772
773    $self->general_settings_panel->properties(
774        $self->general_settings
775    );   
776
777    $self->resized_settings_panel->properties(
778        $self->resized_settings
779    );   
780
781    $self->thumbnail_settings_panel->properties(
782        $self->thumbnail_settings,
783    );   
784
785    $self->hd_settings_panel->properties(
786        $self->hd_settings,
787    );   
788
789    $self->advanced_settings_panel->properties(
790        $self->advanced_settings,
791    );   
792
793    $self->watermark_settings_panel->properties(
794        $self->watermark_settings,
795    ); 
796       
797}
798
799sub _init_settings_panels {
800    my ( $self ) = @_; 
801
802    $self->image_prop_piwigo(
803        Uploader::GUI::wxPropertyGridPanel->new( 
804            { 
805                parentwnd       => $self,
806                properties      => $self->piwigo_properties,
807            }
808        )
809    );
810
811    $self->image_prop_exif(
812        Uploader::GUI::wxPropertyGridPanel->new( 
813            { 
814                parentwnd       => $self,
815                properties      => $self->exif_properties,
816            }
817        )
818    );
819
820
821    $self->general_settings_panel(
822        Uploader::GUI::wxPropertyGridPanel->new( 
823            { 
824                parentwnd       => $self,
825                properties      => $self->general_settings,
826            }
827        )
828    );   
829
830    $self->resized_settings_panel(
831        Uploader::GUI::wxPropertyGridPanel->new( 
832            { 
833                parentwnd       => $self,
834                properties      => $self->resized_settings,
835
836            }
837        )   
838    );   
839
840    $self->thumbnail_settings_panel(
841        Uploader::GUI::wxPropertyGridPanel->new( 
842            { 
843                parentwnd       => $self,
844                properties      => $self->thumbnail_settings,
845            }
846        )   
847    );   
848    $self->hd_settings_panel(
849        Uploader::GUI::wxPropertyGridPanel->new( 
850            { 
851                parentwnd       => $self,
852                properties      => $self->hd_settings,
853            }
854        )   
855    );   
856
857    $self->watermark_settings_panel(
858        Uploader::GUI::wxPropertyGridPanel->new(
859            {
860                parentwnd   => $self,
861                properties  => $self->watermark_settings,
862            }
863        )
864    );
865       
866    $self->advanced_settings_panel(
867        Uploader::GUI::wxPropertyGridPanel->new( 
868            { 
869                parentwnd       => $self,
870                properties      => $self->advanced_settings,
871            }
872        )   
873    );   
874
875    $self->image_prop_tags(
876        Uploader::GUI::wxChoiceFilteredPanel->new( 
877            { 
878                parentwnd    => $self,
879                choices      => $self->piwigo_tags,
880                selection    => $self->image_tags,
881                creation_callback => sub { $self->_create_piwigo_tag(@_) }, 
882            }
883        )   
884    );   
885
886    $self->dlg_piwigo_photo_properties(
887        Uploader::GUI::wxPhotoProperties->new(
888                    {
889                parentwnd       => $self,
890                properties      => $self->piwigo_photo_properties,
891                                tags            => {
892                                                        id => $main::PHOTO_PROPERTIES_TAG,
893                                        choices => $self->piwigo_tags,
894                                        selection => $self->image_tags,
895                                        creation_callback => sub { $self->_create_piwigo_tag(@_) },
896                                                                   }, 
897                        }
898                )
899    ); 
900
901        $self->piwigo_photo_properties_tags(
902            $self->dlg_piwigo_photo_properties->FindWindow($main::PHOTO_PROPERTIES_TAG)
903        );
904
905   
906    $self->general_settings_panel->Show(0);
907
908    $self->image_preview(
909        Uploader::GUI::wxImagePreview->new(
910            { 
911                parentwnd    => $self,
912            }
913        )
914    );
915
916    $self->image_preview->Show(0);
917    $self->image_prop_piwigo->Show(0);
918    $self->image_prop_exif->Show(0);
919       
920}
921
922sub init_panels {
923    my ( $self ) = @_; 
924
925    my $file = sprintf(
926        "../locale/%s/gs.html",
927        wxTheApp->locale->GetCanonicalName
928    );
929
930    $self->htmlhome(
931        Uploader::GUI::wxHtmlWindow->new(
932            $self, -1, [-1, -1], [450, 450]
933        )
934    );
935   
936    $self->htmlhome->LoadPage($file) if -e $file ;
937   
938    $self->htmlhome->InitHrefCallbacks(
939        {
940            new_album => sub {$self->OnAddCategories(@_) },
941            add_photos => sub { $self->OnAddImages(@_) },
942            upload_photos => sub { $self->ProcessImageSelection(@_)},   
943        }
944    );
945   
946    $self->imageviewer(
947        Uploader::GUI::wxImageListCtrl->new( 
948            { 
949                parentwnd => $self,
950                imagelist => $self->imagelist,
951                                image_size => $self->imagelist->wx_thumb_size,
952                                columns => $self->piwigo_properties,
953            }
954        )
955    );
956   
957    $self->_init_settings_panels;       
958}
959
960sub init_dnd_targets {
961    my ( $self ) = @_; 
962
963    $self->imageviewer->SetDropTarget( 
964        DNDImageListDropTarget->new(
965            $self->imageviewer
966        ) 
967    );
968
969    $self->tree->SetDropTarget( 
970        DNDCategoryTreeDropTarget->new(
971            $self->tree
972        )
973    );
974       
975}
976
977sub init_aui {
978    my ( $self ) = @_;
979
980    my $url = wxTheApp->site_url;
981   
982    $url = gettext("empty - work Offline") if wxTheApp->use_offline;
983
984    $self->manager->AddPane
985      ( $self->create_notebook_imagelist, Wx::AuiPaneInfo->new->Name( "ImageViewer" )
986        ->CenterPane->Resizable->CloseButton(0) );
987
988        $self->manager->AddPane( 
989        $self->dlg_piwigo_photo_properties, 
990        Wx::AuiPaneInfo->new->Name( "piwigo_photo_properties" )
991        ->Right->Position( 0 )->Resizable->CloseButton(0) 
992    );
993               
994    $self->manager->AddPane( 
995        $self->create_tree, 
996        Wx::AuiPaneInfo->new->Name( "categories" )
997        ->Right->Position( 1 )->Resizable->CloseButton(0), 
998    );
999
1000
1001
1002    $self->_init_aui_settings_panels;
1003
1004    $self->toolbar(
1005        $self->create_toolbar
1006    );
1007
1008    $self->manager->AddPane
1009      ( $self->toolbar, Wx::AuiPaneInfo->new->Name( "tb1" )
1010        ->ToolbarPane->Top->Row( 1 )->LeftDockable( 0 )->RightDockable( 0 ) ) if defined $self->toolbar;
1011
1012    $self->SetSize( 
1013            $self->frameLayout->{pX}, 
1014            $self->frameLayout->{pY}, 
1015            $self->frameLayout->{W}, 
1016            $self->frameLayout->{H}, 
1017    );
1018
1019
1020    if($self->perspective){
1021        $self->manager->LoadPerspective($self->perspective);
1022    }
1023    else {
1024        $self->manager->GetPane("piwigo_photo_properties")->MinSize(600,350);
1025        $self->manager->GetPane("categories")->MinSize(600,100);
1026
1027        $self->manager->GetPane("tb1")->Caption( gettext("Tools") );
1028        $self->manager->GetPane("image_preview")->Caption(gettext("Preview"))->Show(0);
1029        $self->manager->GetPane("getting_started")->Caption(gettext("Getting started"))->Float->Show(1);
1030        $self->manager->GetPane("photo_properties")->Caption(gettext("Photo properties"))->Float->Show(0);
1031        $self->manager->GetPane("global_settings")->Caption(gettext("Global settings"))->Float->Show(0);
1032    }
1033
1034    $self->manager->GetPane("categories")->Caption(
1035          sprintf("%s - %s", sprintf("Piwigo %s", wxTheApp->branding->{categories}), $url )
1036    );
1037   
1038    $self->manager->Update;
1039
1040}
1041
1042
1043sub _init_aui_settings_panels {
1044    my ( $self ) = @_; 
1045
1046    $self->manager->AddPane
1047      ( $self->image_preview, Wx::AuiPaneInfo->new->Name( "image_preview" )
1048        ->Floatable(1)->Resizable->CloseButton(1));
1049
1050    $self->manager->AddPane
1051      ( $self->htmlhome, Wx::AuiPaneInfo->new->Name( "getting_started" )
1052       ->Floatable(1)->Resizable->CloseButton(1) );
1053
1054    $self->manager->AddPane
1055      ( $self->create_notebook_image_properties, Wx::AuiPaneInfo->new->Name( "photo_properties" )
1056        ->Floatable(1)->Resizable->CloseButton(1) );
1057
1058    $self->manager->AddPane
1059      ( $self->create_notebook_global_settings, Wx::AuiPaneInfo->new->Name( "global_settings" )
1060        ->Floatable(1)->Resizable->CloseButton(1) );
1061
1062}
1063
1064sub OnPhotoProperties {
1065    my ( $self ) = @_;
1066
1067    $self->manager->GetPane("photo_properties")->Show(1);
1068    $self->manager->Update();   
1069       
1070}
1071
1072sub OnPreview {
1073    my ( $self ) = @_;
1074
1075        my $preview_pane = $self->manager->GetPane("image_preview");
1076    if (! $preview_pane->IsShown){
1077            $preview_pane->MinSize(100,75)->Float->Show(1);
1078        $self->manager->Update();   
1079
1080        $self->_image_preview_refresh; 
1081        $self->image_preview->Refresh;         
1082        };
1083       
1084}
1085
1086sub OnGettingStarted {
1087    my ( $self ) = @_;
1088
1089    $self->toolbar->EnableTool(100, 0 );
1090    $self->manager->GetPane("getting_started")->Float->Show(1);
1091    $self->manager->Update();   
1092       
1093}
1094
1095sub OnGlobalSettings {
1096    my ( $self ) = @_;
1097
1098    $self->toolbar->EnableTool(104, 0 );
1099    $self->manager->GetPane("global_settings")->Float->Show(1);
1100    $self->manager->Update();   
1101}
1102
1103sub OnChooseLanguage {
1104    my ( $self ) = @_; 
1105
1106  my $languages = wxTheApp->available_languages;
1107
1108
1109  my $dialog = new Wx::SingleChoiceDialog( 
1110    undef, 
1111    gettext( "Choose a language" ), 
1112    gettext( "Choose a language" ),
1113    [ map { sprintf($_->[0], gettext($_->[2])) } @$languages ] 
1114  );
1115
1116  if( $dialog->ShowModal() == wxID_OK ) {
1117    wxTheApp->current_language(
1118        $languages->[$dialog->GetSelection][1]
1119    );
1120
1121    Wx::LogMessage(
1122        sprintf(
1123            "%s : %s", 
1124            gettext("pLoader needs to be restarted to display the new selected language"),
1125            gettext($languages->[$dialog->GetSelection][2])
1126        )
1127    );
1128    wxTheApp->layout_clean(1);
1129  }
1130
1131  $dialog->Destroy;
1132
1133}
1134
1135sub OnDefaultPhotoNameChanged {
1136    my ( $self ) = @_;
1137   
1138    Wx::LogMessage("New default_photo_name %s", $self->imagelist->default_photo_name); 
1139}
1140
1141
1142sub create_notebook_imagelist {
1143    my( $self ) = @_;
1144    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [300, 450],
1145                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);
1146
1147        my $imglistpage = [
1148            [
1149                $self->imageviewer, 
1150                gettext("Photo selection"),
1151                '../res/images.png', 
1152                wxBITMAP_TYPE_PNG,
1153            ],
1154        ];
1155
1156    $self->notebook($book);
1157    $self->_populate_notebook($self->notebook, $imglistpage, 0);
1158    return $book;
1159}
1160
1161sub create_notebook_image_properties {
1162    my( $self ) = @_;
1163    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [450, 450],
1164                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);
1165    my $pages = [   
1166        [
1167            $self->image_prop_piwigo, 
1168            "Piwigo",
1169        ],
1170        [
1171            $self->image_prop_tags, 
1172            "Tags",
1173        ],
1174        [
1175            $self->image_prop_exif, 
1176            "Exif",
1177        ],
1178    ];
1179   
1180    $self->_populate_notebook( $book, $pages );
1181
1182    $self->notebook_image_properties($book);
1183
1184    return $book;
1185}
1186
1187sub create_notebook_global_settings {
1188    my( $self ) = @_;
1189    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [450, 450],
1190                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);
1191    my $pages = [   
1192        [
1193            $self->general_settings_panel, 
1194            gettext("General"),
1195        ],
1196        [
1197            $self->resized_settings_panel, 
1198            gettext("Resized"),
1199        ],
1200        [
1201            $self->thumbnail_settings_panel, 
1202            gettext("Thumbnail"),
1203        ],
1204        [
1205            $self->hd_settings_panel, 
1206            gettext("High definition"),
1207        ],
1208        [
1209            $self->watermark_settings_panel,
1210            gettext("Watermark"),
1211        ],   
1212        [
1213            $self->advanced_settings_panel, 
1214            gettext("Advanced"),
1215        ],
1216    ];
1217   
1218    $self->_populate_notebook( $book, $pages );
1219
1220    $self->notebook_global_settings($book);
1221
1222    return $book;
1223}
1224
1225
1226
1227
1228sub create_tree {
1229    my ( $self ) = @_;
1230
1231    my $images = [
1232        map {
1233            Wx::Bitmap->new( $_, wxBITMAP_TYPE_PNG )
1234               
1235        }
1236        (
1237          '../res/tree_pwg.png',
1238          '../res/tree_folder.png',
1239        )   
1240    ];
1241
1242    $self->treeimglist( Wx::ImageList->new( 16, 16, 1 ) );
1243    map {
1244        $self->treeimglist->Add($_);
1245    }
1246    @$images;
1247   
1248    $self->tree( 
1249        Wx::TreeCtrl->new( 
1250           $self, 
1251           -1, 
1252           wxDefaultPosition, 
1253           wxDefaultSize, 
1254           wxBORDER_NONE|
1255           wxCLIP_CHILDREN|
1256           wxTR_HAS_BUTTONS|
1257           wxTR_EDIT_LABELS
1258        ) 
1259    );
1260
1261    $self->tree->SetImageList( $self->treeimglist );
1262    $self->populate_tree_categories($self->tree) if !wxTheApp->use_offline;
1263    $self->tree ;
1264}
1265
1266
1267sub populate_tree_categories {
1268    my ( $self, $tree ) = @_;
1269
1270    $self->populate_tree(
1271        $tree,
1272        wxTheApp->pwg->categories,
1273    ) if defined wxTheApp->pwg ;
1274   
1275
1276}
1277
1278
1279# returns a valid itemData
1280sub itemData { Wx::TreeItemData->new( $_[0] ) }
1281
1282sub populate_tree {
1283    my ( $self, $tree, $tree_items ) = @_;
1284    my $root = shift @{$tree_items};
1285
1286    $self->tree_root(
1287        $tree->AddRoot( 
1288            $root->[0], 
1289            $root->[3], 
1290            $root->[4], 
1291            itemData( $root->[2] ) 
1292        )
1293    );
1294
1295  $self->populate_tree_helper( $tree, $self->tree_root, $tree_items );
1296 
1297  $tree->SelectItem( $self->tree_root );
1298  $tree->Expand( $self->tree_root );
1299}
1300
1301sub populate_tree_helper {
1302  my ( $self, $tree, $parent_id, $tree_items ) = @_;
1303
1304  my $id;
1305
1306  map {
1307      my $name = $_->[0];
1308
1309      $id = $tree->AppendItem( 
1310                                   $parent_id, 
1311                                   $name,
1312                                   defined($_->[3]) ? $_->[3] : 0, 
1313                                   defined($_->[4]) ? $_->[4] : 0, 
1314                                   itemData( $_->[2]) 
1315                              );
1316      $self->tree_item_default($id) if ! defined $self->tree_item_default;
1317      # current item has children
1318      if( ref( $_->[1] ) eq 'ARRAY' ) {
1319          $self->populate_tree_helper( $tree, $id, $_->[1] );
1320      } 
1321  }
1322  @{$tree_items};
1323
1324}
1325
1326
1327
1328
1329sub _populate_notebook {
1330    my ( $self, $book, $pages, $position ) = @_;       
1331
1332    my $i = 0;
1333    map {
1334        my $icon = Wx::Icon->new();
1335        eval { $icon->LoadFile($_->[2], $_->[3]) ; }
1336            if defined $_->[2];
1337        my $nb_icon = Wx::Bitmap->new( $icon );
1338        defined $position ?
1339            $book->InsertPage($position, $_->[0],
1340                    $_->[1], 1, $nb_icon )
1341                          :
1342            $book->AddPage($_->[0],
1343                    $_->[1], 0, $nb_icon );
1344
1345        $i++;
1346    } @$pages;
1347
1348}
1349
1350
1351sub _initMenus {
1352    my ( $self ) = @_ ;
1353
1354    $self->_tree_mnu;
1355    $self->_imageviewer_mnu;   
1356}
1357
1358
1359sub _tree_mnu {
1360    my ( $self ) = @_; 
1361
1362    my $ctx_mnu = Wx::Menu->new;
1363   
1364    map {
1365        $ctx_mnu->Append(
1366            @$_[0..2], wxITEM_NORMAL
1367        )->SetBitmap(Wx::Bitmap->new($_->[3],wxBITMAP_TYPE_PNG));
1368    }
1369    (
1370        # workaround : first item does not show bitmap
1371        [
1372            0, 
1373            "",
1374            "",
1375            '../res/mnu_folder_new.png',
1376        ],
1377        [
1378            1+$ID_TREE_CTX_MENU, 
1379            wxTheApp->branding->{'Add new category'},
1380            sprintf(
1381                "%s %s %s %s", 
1382                gettext("Add a new"), 
1383                wxTheApp->branding->{category},
1384                gettext("to the currently selected"),
1385                wxTheApp->branding->{category},
1386            ),
1387            '../res/mnu_folder_new.png',
1388        ],
1389        [
1390            2+$ID_TREE_CTX_MENU, 
1391            gettext("Refresh"),
1392            sprintf(
1393                "Refresh %s list.",
1394                wxTheApp->branding->{category},
1395            ),
1396            '../res/mnu_refresh.png',
1397        ],
1398        [
1399            3+$ID_TREE_CTX_MENU, 
1400            gettext("Expand all"),
1401            sprintf(
1402                "Expand %s list.",
1403                wxTheApp->branding->{category},
1404            ),
1405            '../res/mnu_expandall.png',
1406        ],
1407        [
1408            4+$ID_TREE_CTX_MENU, 
1409            gettext("Collapse all"),
1410            sprintf(
1411                "Collapse %s list.",
1412                wxTheApp->branding->{category},
1413            ),
1414            '../res/mnu_collapseall.png',
1415        ],
1416    );
1417
1418    $ctx_mnu->Delete(0);
1419    $self->tree_mnu(
1420         $ctx_mnu
1421    ); 
1422}       
1423
1424sub _imageviewer_mnu {
1425    my ( $self ) = @_; 
1426
1427    my $ctx_mnu = Wx::Menu->new;
1428   
1429    map {
1430        $ctx_mnu->Append(
1431            @$_[0..2]
1432        )->SetBitmap(Wx::Bitmap->new($_->[3],wxBITMAP_TYPE_PNG));
1433    }
1434    (
1435        # workaround : first item does not show bitmap
1436        [
1437            0, 
1438            "",
1439            "",
1440            '../res/mnu_properties.png',
1441        ],
1442        [
1443            1+$ID_IMAGEVIEWER_CTX_MENU, 
1444            gettext("Properties"),
1445            gettext("Modify photo properties"),
1446            '../res/mnu_properties.png',
1447        ],
1448        [
1449            2+$ID_IMAGEVIEWER_CTX_MENU, 
1450            gettext("Preview"),
1451            gettext("Display photo preview"),
1452            '../res/mnu_preview.png',
1453        ],
1454    );
1455       
1456    $ctx_mnu->Delete(0);
1457    $self->imageviewer_mnu(
1458         $ctx_mnu
1459    ); 
1460}
1461
1462sub _initEventHandlers {
1463    my ( $self ) = @_ ;
1464       
1465    Wx::Event::EVT_MENU( $self, 100, \&OnGettingStarted );
1466    Wx::Event::EVT_MENU( $self, 101, \&OnAddImages );
1467    Wx::Event::EVT_MENU( $self, 102, \&OnRemoveImages );
1468    Wx::Event::EVT_MENU( $self, 103, \&OnUploadImages );
1469    Wx::Event::EVT_MENU( $self, 104, \&OnGlobalSettings );
1470    Wx::Event::EVT_MENU( $self, 105, \&OnChooseLanguage );
1471    Wx::Event::EVT_CHOICE( $self, 106, \&OnPhotoSelMode );
1472    EVT_TREE_SEL_CHANGED( $self, $self->tree, \&OnTreeSelChanged );
1473    EVT_TREE_ITEM_RIGHT_CLICK( $self, $self->tree, \&OnTreeItemRightClick );
1474    EVT_TREE_END_LABEL_EDIT( $self, $self->tree, \&OnTreeEndLabelEdit );
1475
1476    EVT_LIST_END_LABEL_EDIT( $self, $self->imageviewer, \&OnImageViewerEndLabelEdit );
1477    EVT_LIST_ITEM_ACTIVATED( $self, $self->imageviewer, \&OnImageViewerItemActivated );
1478    EVT_LIST_ITEM_SELECTED($self, $self->imageviewer, \&OnImageViewerItemSelected) ;
1479    EVT_LIST_ITEM_RIGHT_CLICK($self, $self->imageviewer, \&OnImageViewerItemRightClick) ;
1480
1481    EVT_LIST_KEY_DOWN($self, $self->imageviewer, \&OnImageViewerKeyDown) ;
1482
1483    EVT_CLOSE( $self, \&OnClose );
1484    Wx::Event::EVT_UPDATE_UI( $self, $self, \&OnUpdateUI );
1485
1486
1487    Wx::Event::EVT_MENU( $self, 1+$ID_TREE_CTX_MENU, \&OnAddCategories );
1488    Wx::Event::EVT_MENU( $self, 2+$ID_TREE_CTX_MENU, \&OnRefreshCategories );
1489    Wx::Event::EVT_MENU( $self, 3+$ID_TREE_CTX_MENU, \&OnExpandCategories );
1490    Wx::Event::EVT_MENU( $self, 4+$ID_TREE_CTX_MENU, \&OnCollapseCategories );
1491
1492    Wx::Event::EVT_MENU( $self, 1+$ID_IMAGEVIEWER_CTX_MENU, \&OnPhotoProperties );
1493    Wx::Event::EVT_MENU( $self, 2+$ID_IMAGEVIEWER_CTX_MENU, \&OnPreview );
1494
1495
1496}
1497
1498{
1499  my $prevdir;
1500  my $prevfile;
1501
1502  sub OnAddImages {
1503    my( $self, $event ) = @_;
1504    my $dialog = Wx::FileDialog->new
1505      ( $self, gettext("Select photos for upload"), $prevfile, $prevdir,
1506        sprintf("%s (*.jpg)|*.jpg|All(*.*)|*.*", gettext("JPEG files")),
1507        wxFD_OPEN|wxFD_MULTIPLE );
1508
1509    my $file_paths = [];
1510    if( $dialog->ShowModal != wxID_CANCEL ) {
1511        @$file_paths = $dialog->GetPaths;
1512        $self->SetNewFiles($file_paths) ;
1513    }
1514    $dialog->Destroy;
1515#    $event->Skip;
1516  }
1517}
1518
1519sub OnUpdateUI {
1520    my( $self, $event ) = @_;
1521   
1522    if( $self->manager ){
1523        if($self->manager->GetPane("global_settings")->IsShown){
1524            $self->toolbar->EnableTool(104, 0);                 
1525        }
1526        else{
1527            $self->toolbar->EnableTool(104, 1);                 
1528        }
1529
1530        if($self->manager->GetPane("getting_started")->IsShown){
1531            $self->toolbar->EnableTool(100, 0);                 
1532        }
1533        else{
1534            $self->toolbar->EnableTool(100, 1);                 
1535        }
1536    }
1537
1538}
1539
1540sub OnRemoveImages {
1541    my( $self, $event ) = @_;
1542
1543   
1544    $self->imagelist->RemoveImageSelection;
1545    $self->imageviewer->Refresh;       
1546
1547        if (!$self->imageviewer->GetItemCount){
1548        $self->image_preview->image(
1549            0
1550        ); 
1551            # have to reset
1552                $self->dlg_piwigo_photo_properties->ClearProperties;
1553        $self->piwigo_photo_properties_tags->ClearAllSelection;
1554                $self->imagelist->SetCurrentImage(-1);
1555        }
1556
1557    $self->image_preview->Refresh;
1558}
1559
1560sub SetNewFiles {
1561    my ( $self, $file_paths ) = @_;
1562
1563    $self->ShowImageViewer();
1564    $self->progressdlg( 
1565        Uploader::GUI::wxImageProcessingProgressDlg->new(
1566            { 
1567                title => gettext("Image processing progress information"),
1568                bt_label => gettext("Cancel image processing"), 
1569                bt_close_label => gettext("Close"), 
1570             }
1571        )       
1572    );
1573    $self->progressdlg->Show(1);
1574    Wx::Yield();
1575
1576   
1577    my $files = [
1578        map {
1579            # to make sure that unicode chars in filenames are supported
1580            {
1581                ANSIPathName => $^O =~ /MSWin32/ ? Win32::GetANSIPathName($_) : $_,
1582                PathName => $_,
1583            },
1584        }@$file_paths   
1585    ];
1586
1587    @$files = sort { $a->{PathName} cmp $b->{PathName} } @$files;   
1588
1589    $self->imagelist->SetNewFiles(
1590        $files
1591    );
1592
1593   
1594}
1595
1596sub OnTreeSelChanged {
1597    my( $self, $event ) = @_;
1598 
1599    my @items = $self->tree->GetSelections;
1600
1601    $self->imagelist->categories(
1602        [
1603            map {
1604                my $category = $self->tree->GetPlData( $_ );
1605                $category->{id} if $category != -1;
1606            }
1607            @items
1608        ]
1609    );
1610}
1611
1612sub OnTreeItemRightClick {
1613    my( $self, $event ) = @_;
1614
1615
1616    $self->PopupMenu($self->tree_mnu, wxDefaultPosition);
1617       
1618}
1619
1620sub OnTreeEndLabelEdit {
1621    my( $self, $event ) = @_;
1622
1623    my $label = $event->GetLabel;
1624   
1625    $label =~ s/^\s+$//;
1626
1627    if(defined($label) and !( "" eq $label )){
1628        $self->_SetLabel($event)
1629    }
1630    else{
1631        $event->Veto;
1632    }
1633}
1634
1635sub _SetLabel {
1636    my( $self, $event ) = @_;
1637       
1638    my $category = $self->tree->GetPlData($event->GetItem);
1639    my $category_id;
1640   
1641    $category_id = $category->{id} if 'HASH' eq ref($category) ;
1642    my $comment;
1643    my ( $success, $status_msg, $content ) = $self->pwg->SetInfoCategories( 
1644        $event->GetLabel, 
1645        $comment, 
1646        $category_id
1647    );
1648
1649    my $ok = 1;
1650   
1651    if(!$success){
1652        $ok = 0;
1653    }
1654
1655    if('fail' eq $content->{stat}){
1656        $ok = 0;
1657    }
1658
1659    # method call failed
1660    if(!$ok){
1661        $event->Veto;
1662        Wx::MessageBox( 
1663            sprintf(
1664                "%s %s", 
1665                gettext("Update failed : "),
1666                $status_msg
1667            ),
1668            gettext("Piwigo update error"),
1669            wxOK | wxICON_EXCLAMATION, 
1670        );
1671        Wx::LogMessage("%s\n\n%s", Dumper($content), gettext("This function is not available. A Piwigo upgrade may resolve this issue."));
1672    }
1673}
1674
1675sub OnImageViewerItemRightClick {
1676    my( $self, $event ) = @_;
1677
1678   
1679    $self->PopupMenu($self->imageviewer_mnu, wxDefaultPosition);
1680       
1681       
1682}
1683
1684sub OnExpandCategories {
1685    my ( $self, $event ) = @_;
1686
1687    my $parent_item = $self->tree->GetSelection;
1688    $self->tree->ExpandAllChildren($parent_item);
1689    $self->tree->EnsureVisible($parent_item);
1690}
1691
1692sub OnCollapseCategories {
1693    my ( $self, $event ) = @_;
1694
1695    my $parent_item = $self->tree->GetSelection;
1696    $self->tree->CollapseAllChildren($parent_item);
1697    $self->tree->Expand($parent_item) if -1 == $self->tree->GetPlData($parent_item);
1698}
1699
1700sub OnAddCategories {
1701    my ( $self, $event ) = @_;
1702
1703    my $parent_item = $self->tree->GetSelection;
1704
1705    my $category = $self->tree->GetPlData($parent_item);
1706    my $category_id;
1707   
1708    $category_id = $category->{id} if 'HASH' eq ref($category) ;
1709
1710    my $dialog = Wx::TextEntryDialog->new( 
1711        $self, 
1712        wxTheApp->branding->{'Category name'}, 
1713        wxTheApp->branding->{'Add new category'},
1714        wxTheApp->branding->{'New category'}, 
1715    );
1716
1717    if( $dialog->ShowModal != wxID_CANCEL ) {
1718        my $name = $dialog->GetValue;
1719        my ( $success, $status_msg, $content ) = $self->pwg->AddCategories( $name, $category_id);
1720
1721        if($success){
1722            $self->_append_category($parent_item, $name, $content->{result}{id});
1723        }
1724    }
1725    $dialog->Destroy;
1726}
1727
1728sub OnRefreshCategories {
1729    my ( $self, $event ) = @_;
1730
1731    $self->_refresh_all_categories_helper;
1732}
1733
1734
1735sub _refresh_all_categories_helper {
1736    my ( $self ) = @_; 
1737
1738    my $busycursor = Wx::BusyCursor->new();
1739    $self->tree->CollapseAll;
1740    $self->tree->DeleteAllItems;
1741    $self->imagelist->categories([]);
1742    $self->pwg->RefreshCategories();
1743    $self->populate_tree_categories;
1744}
1745
1746sub _append_category {
1747    my ( $self, $parent_id, $name, $id ) = @_;
1748
1749    $self->tree->SelectItem(
1750        $self->tree->AppendItem(
1751            $parent_id, 
1752            $name, 
1753            1, 
1754            -1, 
1755            Wx::TreeItemData->new( { id => $id } )
1756        )
1757    );
1758}
1759
1760sub OnImageViewerEndLabelEdit {
1761    my( $self, $event ) = @_;
1762 
1763    my $image = $self->imagelist->GetImage($event->GetIndex);
1764    $image->site_name(
1765        $event->GetLabel
1766    );
1767       
1768    $self->dlg_piwigo_photo_properties->SetProperties;
1769    $self->image_prop_piwigo->Refresh;
1770}
1771
1772sub OnImageViewerItemActivated {
1773    my( $self, $event ) = @_;
1774   
1775    $self->current_imageviewer_index(
1776        $event->GetIndex
1777    );
1778
1779    $self->OnPhotoProperties;
1780}
1781
1782
1783sub OnImageViewerItemSelected {
1784    my( $self, $event ) = @_;
1785
1786    my $bc = Wx::BusyCursor->new;
1787    my $indx = $event->GetIndex;
1788    $self->_on_imageviewer_item_selected($indx);
1789
1790    $event->Skip;
1791
1792}
1793
1794sub _on_imageviewer_item_selected {
1795    my ( $self, $index ) = @_; 
1796    $self->current_imageviewer_index($index);
1797    $self->imagelist->SetCurrentImage($index);
1798   
1799    $self->imagelist->image_selection(
1800        $self->imageviewer->GetSelectedItems
1801    );
1802       
1803        # process image_preview in idle time
1804        # and when current event is processed
1805        # see call to EVT_IDLE
1806    $self->image_preview_refresh(1);
1807
1808    $self->dlg_piwigo_photo_properties->SetProperties;
1809    $self->image_prop_piwigo->Refresh;
1810    $self->image_prop_exif->Refresh;
1811    $self->image_prop_tags->Refresh;
1812        $self->piwigo_photo_properties_tags->Refresh;
1813
1814}
1815
1816sub _image_preview_refresh {
1817    my ( $self ) = @_; 
1818
1819        my $current_image = $self->imagelist->current_image;
1820    my $image = Wx::Image->new;
1821    $image->LoadFile(
1822        $current_image->file, 
1823        wxBITMAP_TYPE_ANY
1824    );
1825 
1826    if($self->imagelist->auto_rotate){
1827        # exif from original image
1828        my $orientation = $current_image->exif_metadata->{Orientation};
1829
1830        # Valid for Rotate 180, Rotate 90 CW, Rotate 270 CW
1831        if( $orientation =~ m/Rotate (\d+)/ ){
1832                        for(my $i=0; $i < floor($1/90) ; $i++){
1833                $image = $image->Rotate90;
1834            }                           
1835        }
1836    }
1837
1838  $self->image_preview->image_size(
1839      [$image->GetWidth, $image->GetHeight, ]
1840  );       
1841
1842  $self->image_preview->image(
1843      $image
1844  );       
1845 
1846}
1847
1848sub OnImageViewerKeyDown {
1849    my( $self, $event ) = @_;
1850
1851    if(WXK_DELETE == $event->GetKeyCode){
1852        $self->OnRemoveImages();
1853       
1854        my $index = $self->current_imageviewer_index < $self->imageviewer->GetItemCount ?
1855            $self->current_imageviewer_index : $self->imageviewer->GetItemCount -1 ;
1856        $self->imageviewer->SelectItem(
1857            $index
1858        );
1859        $self->imageviewer->EnsureVisible(
1860            $index
1861        );
1862    }   
1863
1864}
1865
1866sub OnUploadImages {
1867    my( $self, $event ) = @_;
1868
1869    eval {
1870        $self->ProcessImageSelection();   
1871    };
1872}
1873
1874# remove image from imagelist when uploaded
1875sub UploadImagesViewerRefresh {
1876    my ( $self ) = @_; 
1877
1878
1879    $self->imageviewer->Refresh;
1880
1881    $self->image_preview->image(
1882        0
1883    ) if !$self->imageviewer->GetItemCount;
1884
1885
1886    $self->image_preview->Refresh;
1887    Wx::Yield();
1888}
1889
1890sub UploadProgressMessageRefresh {
1891    my ( $self, $msg ) = @_;   
1892
1893    Wx::Yield();
1894
1895    $self->upload_progressdlg->processing(
1896        $msg   
1897    ); 
1898    $self->upload_progressdlg->LogProgress();
1899
1900    Wx::Yield();
1901}
1902
1903sub UploadProgressMessageDetailsRefresh {
1904    my ( $self, $msg ) = @_;   
1905
1906    Wx::Yield();
1907
1908    $self->upload_progressdlg->processing_details(
1909        $msg   
1910    ); 
1911    $self->upload_progressdlg->LogProgress();
1912
1913    Wx::Yield();
1914}
1915
1916
1917sub UploadProgressThumbnailRefresh {
1918    my ( $self ) = @_; 
1919
1920    my $imagelist = $self->imagelist ;
1921
1922 
1923    $self->upload_progressdlg->image->SetBitmap(wxNullBitmap);
1924    $self->upload_progressdlg->image->SetBitmap(
1925        Wx::Bitmap->new( 
1926            $self->imagelist->current_image->wx_thumb_file, 
1927            $self->GetWxBitmapType($self->imagelist->type), 
1928        )
1929    );
1930
1931    Wx::Yield();
1932}
1933
1934sub UploadProgressBarRefresh {
1935    my ( $self, $value ) = @_; 
1936
1937    eval {
1938        $self->upload_progressdlg->progress(
1939            $value
1940        );
1941        $self->upload_progressdlg->LogProgress();
1942    };
1943    #croak gettext("Upload cancelled") if $@;
1944
1945    Wx::Yield();
1946}
1947
1948sub SetNewFilesDisplayEndInfo {
1949    my ( $self, $msg ) = @_;   
1950       
1951    $self->progressdlg->DisplayEndInfo($msg);
1952}
1953
1954sub UploadDisplayEndInfo {
1955    my ( $self, $msg ) = @_;   
1956   
1957    my $imagelist = $self->imagelist ;
1958   
1959    $self->upload_progressdlg->DisplayEndInfo($msg);
1960}
1961
1962sub ShowImageViewer {
1963    my ( $self ) = @_; 
1964
1965    if(!$self->imageviewer->IsShown){
1966        $self->imageviewer->Show(1);
1967    }
1968}
1969
1970
1971sub ActivateImageViewer {
1972    my ( $self ) = @_; 
1973       
1974}
1975
1976
1977sub SetNewFilesViewerRefresh {
1978
1979    my ( $self ) = @_; 
1980
1981    my $wximagelist = $self->imagelist->wx_thumb_imglist;
1982    #print Dumper "SetNewFilesViewerRefresh", $self->imagelist->current_image;
1983    my $indx = $wximagelist->Add(
1984        Wx::Bitmap->new( 
1985            $self->imagelist->current_image->wx_thumb_file, 
1986            $self->GetWxBitmapType($self->imagelist->type), 
1987        )
1988    ) if defined $self->imagelist->current_image->wx_thumb_file;
1989    print $self->imagelist->current_image->wx_thumb_file, " added with index ", $indx, "\n";   
1990       
1991    $self->imageviewer->Refresh(
1992        $wximagelist
1993    );
1994
1995    Wx::Yield();
1996}
1997
1998
1999
2000# prepare and upload image_selection
2001sub ProcessImageSelection {
2002    my ( $self ) = @_;
2003
2004    return if !scalar @{$self->imagelist->sums};
2005
2006    if( scalar @{$self->imagelist->categories} ){
2007        # all selected is implicit
2008        if(!scalar @{$self->imageviewer->GetSelectedItems}){
2009       
2010            $self->imagelist->image_selection(
2011                $self->imageviewer->GetAllItems
2012            );
2013        }
2014       
2015        return if( !defined $self->imagelist->image_selection );
2016        return if( !scalar @{$self->imagelist->image_selection} );
2017       
2018        $self->upload_progressdlg(
2019            Uploader::GUI::wxImageProcessingProgressDlg->new(
2020                { 
2021                    title    => gettext("Image upload progress information"),
2022                    bt_label => gettext("Cancel upload"),
2023                    bt_close_label => gettext("Close"), 
2024                 }
2025            )       
2026        );
2027        # modeless dialog
2028        $self->upload_progressdlg->Show(1);
2029        Wx::Yield();
2030        eval {
2031            $self->imagelist->UploadSelection;
2032        };
2033        if($@){
2034            Wx::MessageBox( 
2035                sprintf(
2036                    gettext("Upload cancelled"),
2037                ),
2038                gettext("Piwigo upload information"),
2039                wxOK | wxICON_INFORMATION, 
2040            );
2041        }
2042    }
2043    else {
2044        Wx::MessageBox( 
2045            sprintf(
2046                "%s %s", 
2047                gettext("Please select a valid target"),
2048                wxTheApp->branding->{category}
2049            ),
2050            gettext("Piwigo upload error"),
2051            wxOK | wxICON_EXCLAMATION, 
2052        );
2053    }
2054}
2055
2056
2057sub SetNewFilesProgress {
2058    my ( $self ) = @_;
2059
2060    my $imagelist = $self->imagelist;
2061
2062    $self->progressdlg->processing(
2063        sprintf(
2064            $imagelist->progress_msg, 
2065            $imagelist->current_image->file,
2066        )
2067    );
2068
2069    eval {
2070        $self->progressdlg->image->SetSize([ $imagelist->wx_thumb_size, $imagelist->wx_thumb_size]);
2071        $self->progressdlg->image->SetBitmap(wxNullBitmap);
2072        $self->progressdlg->image->SetBitmap(
2073            Wx::Bitmap->new( 
2074                $imagelist->current_image->wx_thumb_file,
2075                $self->GetWxBitmapType( $imagelist->type )
2076            )
2077        );
2078        $self->progressdlg->progress(
2079            $imagelist->count * ( 100/scalar @{$imagelist->new_files} )
2080        );
2081        $self->progressdlg->LogProgress();
2082    };
2083    Wx::Yield();
2084}
2085
2086sub OnClose {
2087  my $self = shift;
2088
2089
2090    # Restaure previous log wnd
2091    Wx::Log::SetActiveTarget( $self->oldlogwnd );
2092
2093    # allways store
2094 
2095    wxTheApp->StoreConnectionProperties;
2096   
2097    $self->imagelist->Store;
2098    wxTheApp->login_dlg->Destroy;       
2099
2100    wxTheApp->perspective(
2101        $self->manager->SavePerspective
2102    );
2103   
2104    wxTheApp->imageviewerIndex(
2105        $self->current_imageviewer_index
2106    );
2107   
2108    my $frameLayout = {};
2109   
2110    ( $frameLayout->{pX}, $frameLayout->{pY}, $frameLayout->{W}, $frameLayout->{H} ) = ( $self->GetPositionXY, $self->GetSizeWH ) ; 
2111   
2112    wxTheApp->frameLayout(
2113        $frameLayout
2114    );
2115
2116    wxTheApp->StoreLayoutProperties;
2117
2118    $self->manager->UnInit;
2119    $self->Destroy;
2120}
2121
2122
2123sub create_toolbar {
2124    my( $self ) = @_;
2125
2126    my $tb = Wx::ToolBar->new( $self, -1, wxDefaultPosition, [600, -1], wxTB_FLAT );
2127    $tb->SetToolBitmapSize( wxSIZE( 32, 32 ) );
2128    map {
2129        my $icon1 = Wx::Icon->new();
2130        eval {
2131            $icon1->LoadFile($_->[2], $_->[3]);
2132        };
2133        my $tb_icon1 = Wx::Bitmap->new( $icon1 );
2134
2135        my $icon2 = Wx::Icon->new();
2136        eval {
2137            $icon2->LoadFile($_->[5], $_->[3]);
2138        };
2139        my $tb_icon2 = Wx::Bitmap->new( $icon2 );
2140
2141
2142        $tb->AddTool( $_->[0], $_->[1], $tb_icon1, $tb_icon2, wxITEM_NORMAL, $_->[1] );
2143        $tb->EnableTool( $_->[0], $_->[4]);
2144    }
2145    (
2146        [
2147            100, 
2148            gettext("Getting started"), 
2149            '../res/tb_getting_started.png', 
2150            wxBITMAP_TYPE_PNG, 
2151            1, 
2152            '../res/tb_getting_started.png', 
2153            gettext("Display getting started panel")
2154        ],
2155        [
2156            101, 
2157            gettext("Add photo to selection"), 
2158            '../res/tb_add.png', 
2159            wxBITMAP_TYPE_PNG, 
2160            1, 
2161            '../res/tb_add.png', 
2162            gettext("Add photo to selection for resizing and uploading")
2163        ],
2164        [
2165            102, 
2166            gettext("Remove photo from selection"), 
2167            '../res/tb_remove.png', 
2168            wxBITMAP_TYPE_PNG, 
2169            1, 
2170            '../res/tb_remove.png',
2171            gettext("Remove photo from selection. Files are not deleted ")
2172        ],
2173        [
2174            103, 
2175            gettext("Upload to Piwigo"), 
2176            '../res/tb_upload.png', 
2177            wxBITMAP_TYPE_PNG, 
2178            wxTheApp->use_offline ? 0 : 1, 
2179            '../res/tb_upload.png',
2180            gettext("Upload photos to Piwigo.")
2181        ],
2182        [
2183            104, 
2184            gettext("Global settings"), 
2185            '../res/tb_settings.png', 
2186            wxBITMAP_TYPE_PNG, 
2187            0, 
2188            '../res/tb_settings.png',
2189            gettext("Change global settings.")
2190        ],
2191        [
2192            105, 
2193            gettext("Language choice"), 
2194            '../res/tb_i18n.png', 
2195            wxBITMAP_TYPE_PNG, 
2196            1, 
2197            '../res/tb_i18n.png',
2198            gettext("Language choice")
2199        ],
2200   
2201    );
2202       
2203        $tb->AddSeparator;
2204       
2205        $tb->AddControl(
2206            Wx::Choice->new(
2207                    $tb,
2208                        106,
2209                        wxDefaultPosition,
2210                        wxDefaultSize,
2211                        [],
2212                )
2213        );
2214        my $ch = $tb->FindWindow(106);
2215    $ch->SetToolTip(gettext("How photo selection is displayed"));
2216        map {
2217            $ch->Append(gettext($_), $_);
2218        }(
2219            "Thumbnail and caption",
2220                "Thumbnail",
2221                "Property list"
2222        );
2223       
2224        $ch->SetStringSelection(gettext($self->imagelist->display_mode));
2225    $tb->Realize;
2226
2227    return $tb;
2228}
2229
2230sub OnPhotoSelMode {
2231    my ( $self, $event )= @_;
2232       
2233        $self->imagelist->display_mode(
2234            $event->GetClientData
2235        );
2236
2237        $self->imageviewer->change_display_mode(1);
2238}
2239
2240sub _create_textctrl {
2241    my( $self, $parent, $text, $size ) = @_;
2242
2243    return Wx::TextCtrl->new( $parent, -1, $text, [0, 0], $size,
2244                              wxNO_BORDER | wxTE_MULTILINE | wxTE_READONLY  );
2245}
2246
2247sub create_textctrl {
2248    my( $self, $text, $size ) = @_;
2249
2250    return $self->_create_textctrl( $self, $text, $size );
2251}
2252
2253sub DESTROY {
2254    my( $self ) = @_;
2255
2256}
2257
2258
2259
22601;
2261
2262
2263
2264
2265
2266package DNDImageListDropTarget;
2267use Wx qw/wxTheApp/;
2268use base qw(Wx::FileDropTarget Class::Accessor::Fast);
2269
2270__PACKAGE__->mk_accessors( 
2271    qw/
2272          imageviewer
2273      /
2274);
2275
2276sub new {
2277  my $class = shift;
2278  my $imageviewer = shift;
2279  my $self = $class->SUPER::new( @_ );
2280
2281  $self->imageviewer($imageviewer);
2282
2283  return $self;
2284}
2285
2286sub OnDropFiles {
2287  my( $self, $x, $y, $files ) = @_;
2288
2289  wxTheApp->frame->SetNewFiles($files) ;
2290}
2291
2292
2293
2294
22951;
2296
2297
2298package DNDCategoryTreeDropTarget;
2299
2300use base qw(Wx::TextDropTarget Class::Accessor::Fast);
2301use Data::Dumper;
2302use Wx qw/
2303              wxDragNone
2304              wxDragCopy
2305              wxDragMove
2306         /;
2307
2308__PACKAGE__->mk_accessors( 
2309    qw/
2310          tree
2311          frame
2312      /
2313);
2314
2315sub new {
2316  my ( $class, $tree ) = @_;
2317  my $self = $class->SUPER::new();
2318
2319  $self->tree($tree);
2320  $self->frame($tree->GetParent);
2321  return $self;
2322}
2323
2324
2325
2326sub OnDropText {
2327  my( $self, $x, $y, $textdata ) = @_;
2328
2329  # must be $VAR1 because $textdata is the result of Data::Dumper
2330  my $VAR1;
2331  eval $textdata;
2332  eval {
2333      if(scalar @$VAR1){
2334           my @items;
2335           if(scalar @items < 2) {
2336               my ($dropItem, $flag) = $self->tree->HitTest([$x, $y]);
2337                push @items, $dropItem;
2338           }
2339           else {
2340                @items = $self->tree->GetSelections;
2341           }
2342           
2343           # remove root item which is not a valid category
2344           @items = grep { $self->tree->GetPlData( $_ ) != -1 } @items;
2345           
2346           $self->frame->imagelist->categories(
2347               [
2348                   map {
2349                       $self->tree->GetPlData( $_ )->{id};
2350                   }
2351                   @items
2352               ]
2353           );
2354           
2355           $self->frame->imagelist->image_selection($VAR1);
2356           $self->frame->ProcessImageSelection ;
2357      } 
2358  };
2359}
2360
23611;
Note: See TracBrowser for help on using the repository browser.