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

Last change on this file since 3472 was 3472, checked in by ronosman, 15 years ago

Feature 993 added : set Piwigo tags. Only existing tags are supported.

  • Property svn:eol-style set to LF
File size: 59.7 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             wxITEM_NORMAL
27             wxNullBitmap
28             wxID_OK
29             wxDEFAULT_FRAME_STYLE
30             wxVERTICAL
31             wxGROW
32             wxBITMAP_TYPE_JPEG
33             wxBITMAP_TYPE_GIF
34             wxBITMAP_TYPE_PNG
35             wxTB_FLAT
36             wxSIZE
37             wxWHITE
38             wxBLACK
39             wxID_CANCEL
40             wxFD_OPEN
41             wxFD_MULTIPLE
42             wxLI_HORIZONTAL
43             wxALIGN_CENTER_VERTICAL
44             wxALL
45             wxDefaultPosition
46             wxDefaultSize
47             wxTheApp
48             wxIMAGE_LIST_NORMAL
49             wxAUI_NB_TAB_MOVE
50             wxAUI_NB_TAB_SPLIT
51             wxNO_BORDER
52             wxTE_MULTILINE
53             wxTE_READONLY
54             wxITEM_NORMAL
55             wxCLIP_CHILDREN
56             wxBORDER_NONE
57             wxNullBitmap
58             wxTR_MULTIPLE
59             wxTR_EXTENDED
60             wxTR_HIDE_ROOT
61             wxTR_HAS_BUTTONS
62             wxTR_EDIT_LABELS
63             wxMAXIMIZE
64             wxOK
65             wxICON_EXCLAMATION
66             wxICON_INFORMATION
67             WXK_DELETE
68             wxLANGUAGE_ABKHAZIAN   
69             wxLANGUAGE_AFAR   
70             wxLANGUAGE_AFRIKAANS   
71             wxLANGUAGE_ALBANIAN   
72             wxLANGUAGE_AMHARIC   
73             wxLANGUAGE_ARABIC   
74             wxLANGUAGE_ARABIC_ALGERIA   
75             wxLANGUAGE_ARABIC_BAHRAIN   
76             wxLANGUAGE_ARABIC_EGYPT   
77             wxLANGUAGE_ARABIC_IRAQ   
78             wxLANGUAGE_ARABIC_JORDAN   
79             wxLANGUAGE_ARABIC_KUWAIT   
80             wxLANGUAGE_ARABIC_LEBANON   
81             wxLANGUAGE_ARABIC_LIBYA   
82             wxLANGUAGE_ARABIC_MOROCCO   
83             wxLANGUAGE_ARABIC_OMAN   
84             wxLANGUAGE_ARABIC_QATAR   
85             wxLANGUAGE_ARABIC_SAUDI_ARABIA   
86             wxLANGUAGE_ARABIC_SUDAN   
87             wxLANGUAGE_ARABIC_SYRIA   
88             wxLANGUAGE_ARABIC_TUNISIA   
89             wxLANGUAGE_ARABIC_UAE   
90             wxLANGUAGE_ARABIC_YEMEN   
91             wxLANGUAGE_ARMENIAN   
92             wxLANGUAGE_ASSAMESE   
93             wxLANGUAGE_AYMARA   
94             wxLANGUAGE_AZERI   
95             wxLANGUAGE_AZERI_CYRILLIC   
96             wxLANGUAGE_AZERI_LATIN   
97             wxLANGUAGE_BASHKIR   
98             wxLANGUAGE_BASQUE   
99             wxLANGUAGE_BELARUSIAN   
100             wxLANGUAGE_BENGALI   
101             wxLANGUAGE_BHUTANI   
102             wxLANGUAGE_BIHARI   
103             wxLANGUAGE_BISLAMA   
104             wxLANGUAGE_BRETON   
105             wxLANGUAGE_BULGARIAN   
106             wxLANGUAGE_BURMESE   
107             wxLANGUAGE_CAMBODIAN   
108             wxLANGUAGE_CATALAN   
109             wxLANGUAGE_CHINESE   
110             wxLANGUAGE_CHINESE_SIMPLIFIED   
111             wxLANGUAGE_CHINESE_TRADITIONAL   
112             wxLANGUAGE_CHINESE_HONGKONG   
113             wxLANGUAGE_CHINESE_MACAU   
114             wxLANGUAGE_CHINESE_SINGAPORE   
115             wxLANGUAGE_CHINESE_TAIWAN   
116             wxLANGUAGE_CORSICAN   
117             wxLANGUAGE_CROATIAN   
118             wxLANGUAGE_CZECH   
119             wxLANGUAGE_DANISH   
120             wxLANGUAGE_DUTCH   
121             wxLANGUAGE_DUTCH_BELGIAN   
122             wxLANGUAGE_ENGLISH   
123             wxLANGUAGE_ENGLISH_UK   
124             wxLANGUAGE_ENGLISH_US   
125             wxLANGUAGE_ENGLISH_AUSTRALIA   
126             wxLANGUAGE_ENGLISH_BELIZE   
127             wxLANGUAGE_ENGLISH_BOTSWANA   
128             wxLANGUAGE_ENGLISH_CANADA   
129             wxLANGUAGE_ENGLISH_CARIBBEAN   
130             wxLANGUAGE_ENGLISH_DENMARK   
131             wxLANGUAGE_ENGLISH_EIRE   
132             wxLANGUAGE_ENGLISH_JAMAICA   
133             wxLANGUAGE_ENGLISH_NEW_ZEALAND   
134             wxLANGUAGE_ENGLISH_PHILIPPINES   
135             wxLANGUAGE_ENGLISH_SOUTH_AFRICA   
136             wxLANGUAGE_ENGLISH_TRINIDAD   
137             wxLANGUAGE_ENGLISH_ZIMBABWE   
138             wxLANGUAGE_ESPERANTO   
139             wxLANGUAGE_ESTONIAN   
140             wxLANGUAGE_FAEROESE   
141             wxLANGUAGE_FARSI   
142             wxLANGUAGE_FIJI   
143             wxLANGUAGE_FINNISH   
144             wxLANGUAGE_FRENCH   
145             wxLANGUAGE_FRENCH_BELGIAN   
146             wxLANGUAGE_FRENCH_CANADIAN   
147             wxLANGUAGE_FRENCH_LUXEMBOURG   
148             wxLANGUAGE_FRENCH_MONACO   
149             wxLANGUAGE_FRENCH_SWISS   
150             wxLANGUAGE_FRISIAN   
151             wxLANGUAGE_GALICIAN   
152             wxLANGUAGE_GEORGIAN   
153             wxLANGUAGE_GERMAN   
154             wxLANGUAGE_GERMAN_AUSTRIAN   
155             wxLANGUAGE_GERMAN_BELGIUM   
156             wxLANGUAGE_GERMAN_LIECHTENSTEIN   
157             wxLANGUAGE_GERMAN_LUXEMBOURG   
158             wxLANGUAGE_GERMAN_SWISS   
159             wxLANGUAGE_GREEK   
160             wxLANGUAGE_GREENLANDIC   
161             wxLANGUAGE_GUARANI   
162             wxLANGUAGE_GUJARATI   
163             wxLANGUAGE_HAUSA   
164             wxLANGUAGE_HEBREW   
165             wxLANGUAGE_HINDI   
166             wxLANGUAGE_HUNGARIAN   
167             wxLANGUAGE_ICELANDIC   
168             wxLANGUAGE_INDONESIAN   
169             wxLANGUAGE_INTERLINGUA   
170             wxLANGUAGE_INTERLINGUE   
171             wxLANGUAGE_INUKTITUT   
172             wxLANGUAGE_INUPIAK   
173             wxLANGUAGE_IRISH   
174             wxLANGUAGE_ITALIAN   
175             wxLANGUAGE_ITALIAN_SWISS   
176             wxLANGUAGE_JAPANESE   
177             wxLANGUAGE_JAVANESE   
178             wxLANGUAGE_KANNADA   
179             wxLANGUAGE_KASHMIRI   
180             wxLANGUAGE_KASHMIRI_INDIA   
181             wxLANGUAGE_KAZAKH   
182             wxLANGUAGE_KERNEWEK   
183             wxLANGUAGE_KINYARWANDA   
184             wxLANGUAGE_KIRGHIZ   
185             wxLANGUAGE_KIRUNDI   
186             wxLANGUAGE_KONKANI   
187             wxLANGUAGE_KOREAN   
188             wxLANGUAGE_KURDISH   
189             wxLANGUAGE_LAOTHIAN   
190             wxLANGUAGE_LATIN   
191             wxLANGUAGE_LATVIAN   
192             wxLANGUAGE_LINGALA   
193             wxLANGUAGE_LITHUANIAN   
194             wxLANGUAGE_MACEDONIAN   
195             wxLANGUAGE_MALAGASY   
196             wxLANGUAGE_MALAY   
197             wxLANGUAGE_MALAYALAM   
198             wxLANGUAGE_MALAY_BRUNEI_DARUSSALAM   
199             wxLANGUAGE_MALAY_MALAYSIA   
200             wxLANGUAGE_MALTESE   
201             wxLANGUAGE_MANIPURI   
202             wxLANGUAGE_MAORI   
203             wxLANGUAGE_MARATHI   
204             wxLANGUAGE_MOLDAVIAN   
205             wxLANGUAGE_MONGOLIAN   
206             wxLANGUAGE_NAURU   
207             wxLANGUAGE_NEPALI   
208             wxLANGUAGE_NEPALI_INDIA   
209             wxLANGUAGE_NORWEGIAN_BOKMAL   
210             wxLANGUAGE_NORWEGIAN_NYNORSK   
211             wxLANGUAGE_OCCITAN   
212             wxLANGUAGE_ORIYA   
213             wxLANGUAGE_OROMO   
214             wxLANGUAGE_PASHTO   
215             wxLANGUAGE_POLISH   
216             wxLANGUAGE_PORTUGUESE   
217             wxLANGUAGE_PORTUGUESE_BRAZILIAN   
218             wxLANGUAGE_PUNJABI   
219             wxLANGUAGE_QUECHUA   
220             wxLANGUAGE_RHAETO_ROMANCE   
221             wxLANGUAGE_ROMANIAN   
222             wxLANGUAGE_RUSSIAN   
223             wxLANGUAGE_RUSSIAN_UKRAINE   
224             wxLANGUAGE_SAMI   
225             wxLANGUAGE_SAMOAN   
226             wxLANGUAGE_SANGHO   
227             wxLANGUAGE_SANSKRIT   
228             wxLANGUAGE_SCOTS_GAELIC   
229             wxLANGUAGE_SERBIAN   
230             wxLANGUAGE_SERBIAN_CYRILLIC   
231             wxLANGUAGE_SERBIAN_LATIN   
232             wxLANGUAGE_SERBO_CROATIAN   
233             wxLANGUAGE_SESOTHO   
234             wxLANGUAGE_SETSWANA   
235             wxLANGUAGE_SHONA   
236             wxLANGUAGE_SINDHI   
237             wxLANGUAGE_SINHALESE   
238             wxLANGUAGE_SISWATI   
239             wxLANGUAGE_SLOVAK   
240             wxLANGUAGE_SLOVENIAN   
241             wxLANGUAGE_SOMALI   
242             wxLANGUAGE_SPANISH   
243             wxLANGUAGE_SPANISH_ARGENTINA   
244             wxLANGUAGE_SPANISH_BOLIVIA   
245             wxLANGUAGE_SPANISH_CHILE   
246             wxLANGUAGE_SPANISH_COLOMBIA   
247             wxLANGUAGE_SPANISH_COSTA_RICA   
248             wxLANGUAGE_SPANISH_DOMINICAN_REPUBLIC   
249             wxLANGUAGE_SPANISH_ECUADOR   
250             wxLANGUAGE_SPANISH_EL_SALVADOR   
251             wxLANGUAGE_SPANISH_GUATEMALA   
252             wxLANGUAGE_SPANISH_HONDURAS   
253             wxLANGUAGE_SPANISH_MEXICAN   
254             wxLANGUAGE_SPANISH_MODERN   
255             wxLANGUAGE_SPANISH_NICARAGUA   
256             wxLANGUAGE_SPANISH_PANAMA   
257             wxLANGUAGE_SPANISH_PARAGUAY   
258             wxLANGUAGE_SPANISH_PERU   
259             wxLANGUAGE_SPANISH_PUERTO_RICO   
260             wxLANGUAGE_SPANISH_URUGUAY   
261             wxLANGUAGE_SPANISH_US   
262             wxLANGUAGE_SPANISH_VENEZUELA   
263             wxLANGUAGE_SUNDANESE   
264             wxLANGUAGE_SWAHILI   
265             wxLANGUAGE_SWEDISH   
266             wxLANGUAGE_SWEDISH_FINLAND   
267             wxLANGUAGE_TAGALOG   
268             wxLANGUAGE_TAJIK   
269             wxLANGUAGE_TAMIL   
270             wxLANGUAGE_TATAR   
271             wxLANGUAGE_TELUGU   
272             wxLANGUAGE_THAI   
273             wxLANGUAGE_TIBETAN   
274             wxLANGUAGE_TIGRINYA   
275             wxLANGUAGE_TONGA   
276             wxLANGUAGE_TSONGA   
277             wxLANGUAGE_TURKISH   
278             wxLANGUAGE_TURKMEN   
279             wxLANGUAGE_TWI   
280             wxLANGUAGE_UIGHUR   
281             wxLANGUAGE_UKRAINIAN   
282             wxLANGUAGE_URDU   
283             wxLANGUAGE_URDU_INDIA   
284             wxLANGUAGE_URDU_PAKISTAN   
285             wxLANGUAGE_UZBEK   
286             wxLANGUAGE_UZBEK_CYRILLIC   
287             wxLANGUAGE_UZBEK_LATIN   
288             wxLANGUAGE_VALENCIAN   
289             wxLANGUAGE_VIETNAMESE   
290             wxLANGUAGE_VOLAPUK   
291             wxLANGUAGE_WELSH   
292             wxLANGUAGE_WOLOF   
293             wxLANGUAGE_XHOSA   
294             wxLANGUAGE_YIDDISH   
295             wxLANGUAGE_YORUBA   
296             wxLANGUAGE_ZHUANG   
297             wxLANGUAGE_ZULU 
298         /;
299use base qw/Wx::Frame Class::Accessor::Fast/;
300use File::Spec;
301use Wx::Locale qw/:default/;
302use Encode qw/encode decode is_utf8/;;
303
304
305my @properties = 
306    qw/
307          progressdlg
308          upload_progressdlg
309          imageviewer
310          tree
311          tree_root
312          treeimglist
313          tree_item_default
314          topsizer
315          pwg
316          manager
317          logwnd
318          oldlogwnd
319          htmlhome
320          notebook
321          categories
322          imagelist
323          image_preview
324          image_prop_piwigo
325          image_prop_exif
326          image_prop_tags
327          notebook_image_properties
328          notebook_global_settings
329          general_settings_panel
330          resized_settings_panel
331          thumbnail_settings_panel
332          preview_settings_panel
333          advanced_settings_panel
334          piwigo_properties
335          exif_properties
336          general_settings
337          resized_settings
338          thumbnail_settings
339          preview_settings
340          advanced_settings
341          toolbar
342          branding
343          perspective
344          current_imageviewer_index
345          imageviewer_mnu
346          tree_mnu
347          imageviewer_select_multi
348          frameLayout
349          piwigo_tags
350          image_tags
351      /;
352__PACKAGE__->mk_accessors( @properties );
353
354use Wx::Event 
355    qw/
356          EVT_MENU
357          EVT_TREE_SEL_CHANGED
358          EVT_TREE_END_LABEL_EDIT
359          EVT_CLOSE
360          EVT_LIST_END_LABEL_EDIT
361          EVT_LIST_ITEM_SELECTED
362          EVT_LIST_ITEM_ACTIVATED
363          EVT_LIST_ITEM_RIGHT_CLICK
364          EVT_TREE_ITEM_RIGHT_CLICK
365          EVT_LIST_KEY_DOWN
366          EVT_UPDATE_UI       
367      /;
368     
369use Uploader::GUI::wxImageListCtrl;
370use Uploader::GUI::wxImageProcessingProgressDlg;
371use Uploader::GUI::wxChoiceGridPanel;
372use Wx::Html;
373use Uploader::GUI::wxHtmlWindow;
374use Data::Dumper;
375use Wx::AUI;
376use Storable;
377use Uploader::GUI::wxPropertyGridPanel;
378use Encode qw/encode decode is_utf8/;
379
380$|=1;
381
382my $ID_TREE_CTX_MENU = 20000 ;
383my $ID_IMAGEVIEWER_CTX_MENU = 20100 ;
384
385sub new {
386  my( $class, $params ) = @_;
387  my( $self ) = $class->SUPER::new( 
388                                      undef, 
389                                      -1, 
390                                      $params->{title},
391                                      wxDefaultPosition,
392                                      wxDefaultSize, 
393                                      wxDEFAULT_FRAME_STYLE
394                                   );
395
396    $self->perspective(
397        $params->{perspective}
398    );
399   
400    $self->current_imageviewer_index(
401        $params->{imageviewer_index}||0
402    );
403   
404    $self->frameLayout(
405        $params->{frameLayout} || { 'pX' => -1, 'pY' => -1, W => 800, H => 600 }
406    );
407
408    $self->pwg( $params->{pwg} );
409    $self->imagelist( $params->{imagelist} );
410
411    # callback for GUI refresh : add thumbnail images to the imageviewer control
412    $self->imagelist->SetNewFilesViewerRefreshCallback(
413        sub { $self->SetNewFilesViewerRefresh(@_) }
414    );
415
416    # callback for GUI refresh : progress dialog display of thumbnail image being created
417    $self->imagelist->SetNewFilesProgressCallback(
418        sub { $self->SetNewFilesProgress(@_) }
419    );
420
421    $self->imagelist->SetNewFilesDisplayEndInfoCallback(
422        sub { $self->SetNewFilesDisplayEndInfo(@_) }
423    );
424
425
426    # callback for GUI refresh : remove thumbnail images from imageviewer control
427    $self->imagelist->UploadImagesViewerCallback(
428        sub { $self->UploadImagesViewerRefresh(@_) }
429    );
430
431
432
433    # callback for GUI refresh : progress dialog display current uploaded image
434    $self->imagelist->progress_thumbnail_refresh(
435        sub { $self->UploadProgressThumbnailRefresh(@_) }
436    );
437
438    $self->imagelist->progress_msg_refresh(
439        sub { $self->UploadProgressMessageRefresh(@_) }
440    );
441
442
443    $self->imagelist->progressbar_refresh(
444        sub { $self->UploadProgressBarRefresh(@_) }
445    );
446   
447    $self->imagelist->progress_endinfo_refresh(
448        sub { $self->UploadDisplayEndInfo(@_) }
449    );
450
451
452    $self->imagelist->pwg(
453        $self->pwg
454    );
455
456    $self->imagelist->categories(
457        []
458    );
459
460
461    $self->manager( Wx::AuiManager->new );
462    $self->manager->SetManagedWindow( $self );
463    $self->_set_setting_properties;
464    $self->_initFrame;
465    $self->_initMenus;
466    $self->_initEventHandlers;
467    $self->_initImgTypes;   
468
469
470    $self->imageviewer->SelectItem(
471        $self->current_imageviewer_index
472    ) if $self->imageviewer->GetItemCount;
473   
474    $self;
475}
476
477
478sub _initImgTypes {
479    my ( $self ) = @_;
480
481    $self->{IMGTYPE} = {
482             'jpg' => wxBITMAP_TYPE_JPEG,
483             'gif' => wxBITMAP_TYPE_GIF,
484             'png' => wxBITMAP_TYPE_PNG,
485    };
486}
487
488
489sub GetWxBitmapType {
490    my ( $self, $type ) = @_;
491   
492    $self->{IMGTYPE}->{$type};
493}
494
495
496
497sub _set_setting_properties {
498    my ( $self ) = @_;
499
500    $self->piwigo_properties(
501        [
502            {
503                label => gettext("Photo caption :"),
504                value => sub { $self->imagelist->current_image->site_name(@_) },
505            },
506            {
507                label => gettext("Comment :"),
508                value => sub { $self->imagelist->current_image->site_comment(@_) },
509                type  => "LongText",
510            },
511            {
512                label => gettext("Author :"),
513                value => sub { $self->imagelist->current_image->site_author(@_) },
514            },
515            {
516                label    => gettext("File name :"),
517                value    => sub { $self->imagelist->current_image->file(@_) },
518                readonly => 1,
519            },
520            {
521                label    => gettext("Create date :"),
522                value    => sub { $self->imagelist->current_image->create_date(@_) },
523                readonly => 1,
524            },
525        ]   
526    );
527
528    $self->exif_properties(
529        [
530            {
531                label    => gettext("Create date :"),
532                value    => sub { $self->imagelist->current_image->create_date }, 
533                readonly => 1,
534            }, 
535            {
536                label    => gettext("Model :"),
537                value    => sub { $self->imagelist->current_image->exif_tag('Model') }, 
538                readonly => 1,
539            }, 
540            {
541                label    => gettext("Width :"),
542                value    => sub { $self->imagelist->current_image->exif_tag('ImageWidth') }, 
543                readonly => 1,
544            }, 
545            {
546                label    => gettext("Height :"),
547                value    => sub { $self->imagelist->current_image->exif_tag('ImageHeight') }, 
548                readonly => 1,
549            }, 
550            {
551                label    => gettext("Orientation :"),
552                value    => sub { $self->imagelist->current_image->exif_tag('Orientation') }, 
553                readonly => 1,
554            }, 
555            {
556                label    => "ISO :",
557                value    => sub { $self->imagelist->current_image->exif_tag('ISO') }, 
558                readonly => 1,
559            }, 
560            {
561                label    => gettext("Shutter speed :"),
562                value    => sub { $self->imagelist->current_image->exif_tag('ExposureTime') }, 
563                readonly => 1,
564            }, 
565            {
566                label    => gettext("Aperture :"),
567                value    => sub { $self->imagelist->current_image->exif_tag('ApertureValue') }, 
568                readonly => 1,
569            }, 
570            {
571                label    => gettext("Focal length :"),
572                value    => sub { $self->imagelist->current_image->exif_tag('FocalLength') }, 
573                readonly => 1,
574            }, 
575            {
576                label    => gettext("Lens :"),
577                value    => sub { $self->imagelist->current_image->exif_tag('Lens') }, 
578                readonly => 1,
579            }, 
580        ]
581    );   
582
583
584    $self->general_settings(
585        [
586            {
587                label     => gettext("Default author :"),
588                value   => sub { $self->imagelist->author(@_) },
589            },
590            {
591                label     => gettext("Default photo caption :"),
592                type      => 'Choice',
593                value   => sub { $self->imagelist->default_photo_name(@_) },
594                choice  => [
595                                  gettext('None'),
596                                  gettext('File name'),
597                                  gettext('File path and name'),
598                                  gettext('Prefix'),
599                                  gettext('Prefix + rank number'),
600                                  gettext('Rank number + prefix'),
601                                  gettext('Prefix + create date chrono'),
602                                  gettext('Create date chrono + prefix'),
603                              ],
604            },
605            {
606                label     => gettext("Photo caption  prefix :"),
607                value   => sub { $self->imagelist->default_name_prefix(@_) },
608            },
609            {
610                label     => gettext("Resize site image :"),
611                type      => 'Bool',
612                value   => sub { $self->imagelist->create_resized(@_) },
613            },
614            {
615                label     => gettext("Auto rotate image :"),
616                type      => 'Bool',
617                value   => sub { $self->imagelist->auto_rotate(@_) },
618            },
619            {
620                label     => gettext("Upload high (original size) :"),
621                type      => 'Bool',
622                value   => sub { $self->imagelist->upload_high(@_) },
623            },
624            {
625                label     => gettext("Remove uploaded photo from selection :"),
626                type      => 'Bool',
627                value   => sub { $self->imagelist->remove_uploaded_from_selection(@_) },
628            },
629        ]   
630    );
631   
632    $self->resized_settings(
633        [
634            {
635                label     => gettext("Site image width :"),
636                type      => 'Number',
637                value   => sub { $self->imagelist->resize_w(@_) },
638            },
639            {
640                label     => gettext("Site image height :"),
641                type      => 'Number',
642                value   => sub { $self->imagelist->resize_h(@_) },
643            },
644            {
645                label     => gettext("Site image jpeg quality :"),
646                type      => 'Number',
647                value   => sub { $self->imagelist->quality(@_) },
648            },
649            {
650                label     => gettext("Site image filter :"),
651                type      => 'Choice',
652                value   => sub { $self->imagelist->filter(@_) },
653                choice    => [ qw/Point Box Triangle Hermite Hanning Hamming Blackman Gaussian Quadratic Cubic Catrom Mitchell Lanczos Bessel Sinc/ ],
654            },
655            {
656                label     => gettext("Site image blur :"),
657                type      => 'Number',
658                value   => sub { $self->imagelist->blur(@_) },
659            },
660            {
661                label     => gettext("Site image interlace :"),
662                type      => 'Choice',
663                value   => sub { $self->imagelist->interlace(@_) },
664                choice    => [ qw/None Line Plane Partition JPEG GIF PNG/ ],
665            },
666        ]   
667    );
668
669    $self->thumbnail_settings(
670        [
671            {
672                label     => gettext("Site thumbnail size :"),
673                type      => 'Number',
674                value   => sub { $self->imagelist->thumb_size(@_) },
675            },
676            {
677                label     => gettext("Site thumbnail jpeg quality :"),
678                type      => 'Number',
679                value   => sub { $self->imagelist->th_quality(@_) },
680            },
681            {
682                label     => gettext("Photo selection thumbnail size :"),
683                type      => 'Number',
684                value   => sub { $self->imagelist->wx_thumb_size(@_) },
685            },
686            {
687                label     => gettext("Photo selection thumbnail jpeg quality :"),
688                type      => 'Number',
689                value   => sub { $self->imagelist->wx_quality(@_) },
690            },
691        ]   
692    );
693   
694    $self->preview_settings(
695        [
696            {
697                label     => gettext("Use exif preview when available :"),
698                type      => 'Bool',
699                value   => sub { $self->imagelist->use_exif_preview(@_) },
700            },
701            {
702                label     => gettext("Custom preview ratio :"),
703                type      => 'Number',
704                value   => sub { $self->imagelist->preview_ratio(@_) },
705            },
706        ]   
707    );
708
709    $self->advanced_settings(
710        [
711            {
712                label     => gettext("Transfert chunk size :"),
713                type      => 'Number',
714                value   => sub { wxTheApp->chunk_size(@_) },
715            },
716        ]   
717    );
718
719    $self->image_tags(
720        sub { $self->imagelist->current_image->site_tags(@_) }
721    );
722
723    $self->piwigo_tags(
724        wxTheApp->pwg->tags||[]
725    ); 
726}
727
728sub _refreshFrame {
729    my ( $self ) = @_;
730   
731    $self->_set_setting_properties;
732    $self->_refresh_settings_panels_properties;
733    map {
734        $_->Refresh;   
735    }
736    (
737        $self->image_prop_piwigo,
738        $self->image_prop_exif,
739        $self->image_prop_tags,
740        $self->general_settings_panel,
741        $self->resized_settings_panel,
742        $self->thumbnail_settings_panel,
743        $self->preview_settings_panel,
744        $self->advanced_settings_panel,
745    );
746   
747    $self->manager->Update;
748}
749
750
751sub _destroy_settings_panels {
752    my ( $self ) = @_;
753
754
755
756    map {
757        $self->manager->DetachPane(
758            $_
759        );
760        $_->Show(0);
761        $_->Destroy;
762    }(
763        $self->notebook_global_settings,
764        $self->notebook_image_properties,
765    );
766}
767
768#
769sub _initFrame {
770    my ( $self ) = @_;
771   
772 
773    $self->init_panels;
774
775    $self->init_aui;
776    $self->init_dnd_targets;
777
778    if( $self->imagelist->wx_thumb_imglist->GetImageCount){
779        printf("%s images\n", $self->imagelist->wx_thumb_imglist->GetImageCount); 
780        $self->ShowImageViewer;
781       
782        $self->imageviewer->Refresh(
783            $self->imagelist->wx_thumb_imglist
784        );
785       
786    }
787
788}
789
790sub _refresh_settings_panels_properties {
791    my ( $self ) = @_; 
792
793    $self->image_prop_piwigo->properties(
794        $self->piwigo_properties
795    );
796   
797    $self->image_prop_exif->properties(
798        $self->exif_properties
799    );
800
801
802    $self->general_settings_panel->properties(
803        $self->general_settings
804    );   
805
806    $self->resized_settings_panel->properties(
807        $self->resized_settings
808    );   
809
810    $self->thumbnail_settings_panel->properties(
811        $self->thumbnail_settings,
812    );   
813
814    $self->preview_settings_panel->properties(
815        $self->preview_settings,
816    );   
817
818    $self->advanced_settings_panel->properties(
819        $self->advanced_settings,
820    );   
821
822       
823}
824
825sub _init_settings_panels {
826    my ( $self ) = @_; 
827
828    $self->image_prop_piwigo(
829        Uploader::GUI::wxPropertyGridPanel->new( 
830            { 
831                parentwnd       => $self,
832                properties      => $self->piwigo_properties,
833                frame_callbacks => [ 
834                                          sub {
835                                              $self->imageviewer->Refresh();
836                                          },
837                                   ],
838            }
839        )
840    );
841
842    $self->image_prop_exif(
843        Uploader::GUI::wxPropertyGridPanel->new( 
844            { 
845                parentwnd       => $self,
846                frame_callbacks => [],
847                properties      => $self->exif_properties,
848            }
849        )
850    );
851
852
853    $self->general_settings_panel(
854        Uploader::GUI::wxPropertyGridPanel->new( 
855            { 
856                parentwnd       => $self,
857                properties      => $self->general_settings,
858                frame_callbacks => [], 
859            }
860        )
861    );   
862
863    $self->resized_settings_panel(
864        Uploader::GUI::wxPropertyGridPanel->new( 
865            { 
866                parentwnd       => $self,
867                properties      => $self->resized_settings,
868                frame_callbacks => [],
869
870            }
871        )   
872    );   
873
874    $self->thumbnail_settings_panel(
875        Uploader::GUI::wxPropertyGridPanel->new( 
876            { 
877                parentwnd       => $self,
878                properties      => $self->thumbnail_settings,
879                frame_callbacks => [],
880
881            }
882        )   
883    );   
884    $self->preview_settings_panel(
885        Uploader::GUI::wxPropertyGridPanel->new( 
886            { 
887                parentwnd       => $self,
888                properties      => $self->preview_settings,
889                frame_callbacks => [],
890
891            }
892        )   
893    );   
894
895    $self->advanced_settings_panel(
896        Uploader::GUI::wxPropertyGridPanel->new( 
897            { 
898                parentwnd       => $self,
899                properties      => $self->advanced_settings,
900                frame_callbacks => [],
901
902            }
903        )   
904    );   
905
906    $self->image_prop_tags(
907        Uploader::GUI::wxChoiceGridPanel->new( 
908            { 
909                parentwnd    => $self,
910                choices      => $self->piwigo_tags,
911                selection    => $self->image_tags, 
912            }
913        )   
914    );   
915
916   
917    $self->general_settings_panel->Show(0);
918
919    $self->image_preview(
920        Wx::HtmlWindow->new(
921            $self,
922            -1,
923            [-1,-1],
924            [-1,-1],
925        )
926    );
927
928
929    $self->image_prop_piwigo->Show(0);
930   
931    $self->image_prop_exif->Show(0);
932       
933}
934
935sub init_panels {
936    my ( $self ) = @_; 
937
938    my $file = sprintf(
939        "../locale/%s/gs.html",
940        wxTheApp->locale->GetCanonicalName
941    );
942
943    $self->htmlhome(
944        Uploader::GUI::wxHtmlWindow->new(
945            $self, -1, [-1, -1], [450, 450]
946        )
947    );
948   
949    $self->htmlhome->LoadPage($file) if -e $file ;
950   
951    $self->htmlhome->InitHrefCallbacks(
952        {
953            new_album => sub {$self->OnAddCategories(@_) },
954            add_photos => sub { $self->OnAddImages(@_) },
955            upload_photos => sub { $self->ProcessImageSelection(@_)},   
956        }
957    );
958   
959    $self->imageviewer(
960        Uploader::GUI::wxImageListCtrl->new( 
961            { 
962                parentwnd => $self,
963                imagelist => $self->imagelist,
964            }
965        )
966    );
967   
968    $self->_init_settings_panels;       
969}
970
971sub init_dnd_targets {
972    my ( $self ) = @_; 
973
974    $self->imageviewer->SetDropTarget( 
975        DNDImageListDropTarget->new(
976            $self->imageviewer
977        ) 
978    );
979
980    $self->tree->SetDropTarget( 
981        DNDCategoryTreeDropTarget->new(
982            $self->tree
983        )
984    );
985       
986}
987
988sub init_aui {
989    my ( $self ) = @_;
990
991    my $url = wxTheApp->site_url;
992   
993    $url = gettext("empty - work Offline") if wxTheApp->use_offline;
994
995    $self->manager->AddPane
996      ( $self->create_notebook_imagelist, Wx::AuiPaneInfo->new->Name( "ImageViewer" )
997        ->CenterPane->Resizable->CloseButton(0) );
998
999    $self->manager->AddPane( 
1000        $self->create_tree, 
1001        Wx::AuiPaneInfo->new->Name( "categories" )
1002        ->Right->Position( 0 )->Resizable->CloseButton(0), 
1003    );
1004
1005
1006
1007    $self->_init_aui_settings_panels;
1008
1009    $self->toolbar(
1010        $self->create_toolbar
1011    );
1012
1013    $self->manager->AddPane
1014      ( $self->toolbar, Wx::AuiPaneInfo->new->Name( "tb1" )
1015        ->ToolbarPane->Top->Row( 1 )->LeftDockable( 0 )->RightDockable( 0 ) ) if defined $self->toolbar;
1016
1017    $self->SetSize( 
1018            $self->frameLayout->{pX}, 
1019            $self->frameLayout->{pY}, 
1020            $self->frameLayout->{W}, 
1021            $self->frameLayout->{H}, 
1022    );
1023
1024
1025    if($self->perspective){
1026        $self->manager->LoadPerspective($self->perspective);
1027    }
1028    else {
1029        $self->manager->GetPane("categories")->MinSize(300,100);
1030
1031        $self->manager->GetPane("tb1")->Caption( gettext("Tools") );
1032        $self->manager->GetPane("image_preview")->Caption(gettext("Preview"))->Show(0);
1033        $self->manager->GetPane("getting_started")->Caption(gettext("Getting started"))->Float->Show(1);
1034        $self->manager->GetPane("photo_properties")->Caption(gettext("Photo properties"))->Float->Show(0);
1035        $self->manager->GetPane("global_settings")->Caption(gettext("Global settings"))->Float->Show(0);
1036    }
1037
1038    $self->manager->GetPane("categories")->Caption(
1039          sprintf("%s - %s", sprintf("Piwigo %s", wxTheApp->branding->{categories}), $url )
1040    );
1041   
1042    $self->manager->Update;
1043
1044}
1045
1046
1047sub _init_aui_settings_panels {
1048    my ( $self ) = @_; 
1049
1050    $self->manager->AddPane
1051      ( $self->image_preview, Wx::AuiPaneInfo->new->Name( "image_preview" )
1052        ->Floatable(1)->Resizable->CloseButton(1));
1053
1054    $self->manager->AddPane
1055      ( $self->htmlhome, Wx::AuiPaneInfo->new->Name( "getting_started" )
1056       ->Floatable(1)->Resizable->CloseButton(1) );
1057
1058    $self->manager->AddPane
1059      ( $self->create_notebook_image_properties, Wx::AuiPaneInfo->new->Name( "photo_properties" )
1060        ->Floatable(1)->Resizable->CloseButton(1) );
1061
1062    $self->manager->AddPane
1063      ( $self->create_notebook_global_settings, Wx::AuiPaneInfo->new->Name( "global_settings" )
1064        ->Floatable(1)->Resizable->CloseButton(1) );
1065
1066}
1067
1068sub OnPhotoProperties {
1069    my ( $self ) = @_;
1070
1071    $self->manager->GetPane("photo_properties")->Show(1);
1072    $self->manager->Update();   
1073       
1074}
1075
1076sub OnPreview {
1077    my ( $self ) = @_;
1078
1079    $self->manager->GetPane("image_preview")->Float->Show(1);
1080    $self->manager->Update();   
1081       
1082}
1083
1084sub OnGettingStarted {
1085    my ( $self ) = @_;
1086
1087    $self->toolbar->EnableTool(100, 0 );
1088    $self->manager->GetPane("getting_started")->Float->Show(1);
1089    $self->manager->Update();   
1090       
1091}
1092
1093sub OnGlobalSettings {
1094    my ( $self ) = @_;
1095
1096    $self->toolbar->EnableTool(104, 0 );
1097    $self->manager->GetPane("global_settings")->Float->Show(1);
1098    $self->manager->Update();   
1099}
1100
1101sub OnChooseLanguage {
1102    my ( $self ) = @_; 
1103
1104  my $languages = [
1105             ['Dutch', wxLANGUAGE_DUTCH, ],   
1106             ['English', wxLANGUAGE_ENGLISH, ],   
1107             ['French', wxLANGUAGE_FRENCH, ],   
1108             ['German', wxLANGUAGE_GERMAN, ],   
1109             ['Italian', wxLANGUAGE_ITALIAN, ],   
1110             ['Polish', wxLANGUAGE_POLISH, ],   
1111             ['Portuguese', wxLANGUAGE_PORTUGUESE, ],   
1112             ['Russian', wxLANGUAGE_RUSSIAN, ],   
1113             ['Spanish', wxLANGUAGE_SPANISH, ],   
1114  ];
1115
1116  my $dialog = new Wx::SingleChoiceDialog
1117    ( undef, gettext( "Choose a language" ), gettext( "Choose a language" ),
1118      [ map { Wx::GetTranslation( ${$_}[0] ) } @$languages ] );
1119
1120  if( $dialog->ShowModal() == wxID_OK ) {
1121    wxTheApp->current_language(
1122        $languages->[$dialog->GetSelection][1]
1123    );
1124    wxTheApp->init_locale();
1125    $self->_refreshFrame;
1126  }
1127
1128  $dialog->Destroy;
1129
1130}
1131
1132sub OnDefaultPhotoNameChanged {
1133    my ( $self ) = @_;
1134   
1135    Wx::LogMessage("New default_photo_name %s", $self->imagelist->default_photo_name); 
1136}
1137
1138
1139sub create_notebook_imagelist {
1140    my( $self ) = @_;
1141    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [300, 450],
1142                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);
1143
1144        my $imglistpage = [
1145            [
1146                $self->imageviewer, 
1147                gettext("Photo selection"),
1148                '../res/images.png', 
1149                wxBITMAP_TYPE_PNG,
1150            ],
1151        ];
1152
1153    $self->notebook($book);
1154    $self->_populate_notebook($self->notebook, $imglistpage, 0);
1155    return $book;
1156}
1157
1158sub create_notebook_image_properties {
1159    my( $self ) = @_;
1160    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [450, 450],
1161                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);
1162    my $pages = [   
1163        [
1164            $self->image_prop_piwigo, 
1165            "Piwigo",
1166        ],
1167        [
1168            $self->image_prop_tags, 
1169            "Tags",
1170        ],
1171        [
1172            $self->image_prop_exif, 
1173            "Exif",
1174        ],
1175    ];
1176   
1177    $self->_populate_notebook( $book, $pages );
1178
1179    $self->notebook_image_properties($book);
1180
1181    return $book;
1182}
1183
1184sub create_notebook_global_settings {
1185    my( $self ) = @_;
1186    my $book = Wx::AuiNotebook->new( $self, -1, [-1, -1], [450, 450],
1187                                     wxBORDER_NONE|wxAUI_NB_TAB_MOVE|wxAUI_NB_TAB_SPLIT);
1188    my $pages = [   
1189        [
1190            $self->general_settings_panel, 
1191            gettext("General"),
1192        ],
1193        [
1194            $self->resized_settings_panel, 
1195            gettext("Resized"),
1196        ],
1197        [
1198            $self->thumbnail_settings_panel, 
1199            gettext("Thumbnail"),
1200        ],
1201        [
1202            $self->preview_settings_panel, 
1203            gettext("Preview"),
1204        ],
1205        [
1206            $self->advanced_settings_panel, 
1207            gettext("Advanced"),
1208        ],
1209    ];
1210   
1211    $self->_populate_notebook( $book, $pages );
1212
1213    $self->notebook_global_settings($book);
1214
1215    return $book;
1216}
1217
1218
1219
1220
1221sub create_tree {
1222    my ( $self ) = @_;
1223
1224    my $images = [
1225        map {
1226            Wx::Bitmap->new( $_, wxBITMAP_TYPE_PNG )
1227               
1228        }
1229        (
1230          '../res/tree_pwg.png',
1231          '../res/tree_folder.png',
1232        )   
1233    ];
1234
1235    $self->treeimglist( Wx::ImageList->new( 16, 16, 1 ) );
1236    map {
1237        $self->treeimglist->Add($_);
1238    }
1239    @$images;
1240
1241   
1242    $self->tree( 
1243        Wx::TreeCtrl->new( 
1244           $self, 
1245           -1, 
1246           wxDefaultPosition, 
1247           wxDefaultSize, 
1248           wxBORDER_NONE|
1249           wxCLIP_CHILDREN|
1250           wxTR_HAS_BUTTONS|
1251           wxTR_EDIT_LABELS
1252        ) 
1253    );
1254
1255    $self->tree->SetImageList( $self->treeimglist );
1256    $self->populate_tree_categories if !wxTheApp->use_offline;
1257    $self->tree ;
1258}
1259
1260
1261sub populate_tree_categories {
1262    my ( $self ) = @_;
1263
1264    $self->populate_tree(
1265        $self->tree,
1266        wxTheApp->pwg->categories,
1267    ) if defined wxTheApp->pwg ;
1268   
1269    #$self->tree->ExpandAll;
1270
1271}
1272
1273
1274# returns a valid itemData
1275sub itemData { Wx::TreeItemData->new( $_[0] ) }
1276
1277sub populate_tree {
1278    my ( $self, $tree, $tree_items ) = @_;
1279    my $root = shift @{$tree_items};
1280
1281    $self->tree_root(
1282        $tree->AddRoot( 
1283            $root->[0], 
1284            $root->[3], 
1285            $root->[4], 
1286            itemData( $root->[2] ) 
1287        )
1288    );
1289
1290  $self->populate_tree_helper( $tree, $self->tree_root, $tree_items );
1291 
1292  $tree->SelectItem( $self->tree_root );
1293  $tree->Expand( $self->tree_root );
1294}
1295
1296sub populate_tree_helper {
1297  my ( $self, $tree, $parent_id, $tree_items ) = @_;
1298
1299  my $id;
1300
1301  map {
1302      my $name = $_->[0];
1303      eval {
1304        $name = is_utf8($name) ?  decode('UTF-8', $name) : $name;
1305      };
1306      if($@){
1307          $name = $_->[0];
1308      }
1309
1310      $id = $tree->AppendItem( 
1311                                   $parent_id, 
1312                                   $name,
1313                                   defined($_->[3]) ? $_->[3] : 0, 
1314                                   defined($_->[4]) ? $_->[4] : 0, 
1315                                   itemData( $_->[2]) 
1316                              );
1317      $self->tree_item_default($id) if ! defined $self->tree_item_default;
1318      # current item has children
1319      if( ref( $_->[1] ) eq 'ARRAY' ) {
1320          $self->populate_tree_helper( $tree, $id, $_->[1] );
1321      } 
1322  }
1323  @{$tree_items};
1324
1325}
1326
1327
1328
1329
1330sub _populate_notebook {
1331    my ( $self, $book, $pages, $position ) = @_;       
1332
1333    my $i = 0;
1334    map {
1335        my $icon = Wx::Icon->new();
1336        eval { $icon->LoadFile($_->[2], $_->[3]) ; }
1337            if defined $_->[2];
1338        my $nb_icon = Wx::Bitmap->new( $icon );
1339        defined $position ?
1340            $book->InsertPage($position, $_->[0],
1341                    $_->[1], 1, $nb_icon )
1342                          :
1343            $book->AddPage($_->[0],
1344                    $_->[1], 0, $nb_icon );
1345
1346        $i++;
1347    } @$pages;
1348
1349}
1350
1351
1352sub _initMenus {
1353    my ( $self ) = @_ ;
1354
1355    $self->_tree_mnu;
1356    $self->_imageviewer_mnu;   
1357}
1358
1359
1360sub _tree_mnu {
1361    my ( $self ) = @_; 
1362
1363    my $ctx_mnu = Wx::Menu->new;
1364   
1365    map {
1366        $ctx_mnu->Append(
1367            @$_[0..2], wxITEM_NORMAL
1368        )->SetBitmap(Wx::Bitmap->new($_->[3],wxBITMAP_TYPE_PNG));
1369    }
1370    (
1371        # workaround : first item does not show bitmap
1372        [
1373            0, 
1374            "",
1375            "",
1376            '../res/mnu_folder_new.png',
1377        ],
1378        [
1379            1+$ID_TREE_CTX_MENU, 
1380            wxTheApp->branding->{'Add new category'},
1381            sprintf(
1382                "%s %s %s %s", 
1383                gettext("Add a new"), 
1384                wxTheApp->branding->{category},
1385                gettext("to the currently selected"),
1386                wxTheApp->branding->{category},
1387            ),
1388            '../res/mnu_folder_new.png',
1389        ],
1390        [
1391            2+$ID_TREE_CTX_MENU, 
1392            gettext("Refresh"),
1393            sprintf(
1394                "Refresh %s list.",
1395                wxTheApp->branding->{category},
1396            ),
1397            '../res/mnu_refresh.png',
1398        ],
1399        [
1400            3+$ID_TREE_CTX_MENU, 
1401            gettext("Expand all"),
1402            sprintf(
1403                "Expand %s list.",
1404                wxTheApp->branding->{category},
1405            ),
1406            '../res/mnu_expandall.png',
1407        ],
1408        [
1409            4+$ID_TREE_CTX_MENU, 
1410            gettext("Collapse all"),
1411            sprintf(
1412                "Collapse %s list.",
1413                wxTheApp->branding->{category},
1414            ),
1415            '../res/mnu_collapseall.png',
1416        ],
1417    );
1418
1419    $ctx_mnu->Delete(0);
1420    $self->tree_mnu(
1421         $ctx_mnu
1422    ); 
1423}       
1424
1425sub _imageviewer_mnu {
1426    my ( $self ) = @_; 
1427
1428    my $ctx_mnu = Wx::Menu->new;
1429   
1430    map {
1431        $ctx_mnu->Append(
1432            @$_[0..2]
1433        )->SetBitmap(Wx::Bitmap->new($_->[3],wxBITMAP_TYPE_PNG));
1434    }
1435    (
1436        # workaround : first item does not show bitmap
1437        [
1438            0, 
1439            "",
1440            "",
1441            '../res/mnu_properties.png',
1442        ],
1443        [
1444            1+$ID_IMAGEVIEWER_CTX_MENU, 
1445            gettext("Properties"),
1446            gettext("Modify photo properties"),
1447            '../res/mnu_properties.png',
1448        ],
1449        [
1450            2+$ID_IMAGEVIEWER_CTX_MENU, 
1451            gettext("Preview"),
1452            gettext("Display photo preview"),
1453            '../res/mnu_preview.png',
1454        ],
1455    );
1456       
1457    $ctx_mnu->Delete(0);
1458    $self->imageviewer_mnu(
1459         $ctx_mnu
1460    ); 
1461}
1462
1463sub _initEventHandlers {
1464    my ( $self ) = @_ ;
1465       
1466    Wx::Event::EVT_MENU( $self, 100, \&OnGettingStarted );
1467    Wx::Event::EVT_MENU( $self, 101, \&OnAddImages );
1468    Wx::Event::EVT_MENU( $self, 102, \&OnRemoveImages );
1469    Wx::Event::EVT_MENU( $self, 103, \&OnUploadImages );
1470    Wx::Event::EVT_MENU( $self, 104, \&OnGlobalSettings );
1471    Wx::Event::EVT_MENU( $self, 105, \&OnChooseLanguage );
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    $self->image_preview->SetPage(
1548        "<html></html>"
1549    ) if !$self->imageviewer->GetItemCount;
1550
1551}
1552
1553sub SetNewFiles {
1554    my ( $self, $file_paths ) = @_;
1555
1556    $self->ShowImageViewer();
1557    $self->progressdlg( 
1558        Uploader::GUI::wxImageProcessingProgressDlg->new(
1559            { 
1560                title => gettext("Image processing progress information"),
1561                bt_label => gettext("Cancel image processing"), 
1562             }
1563        )       
1564    );
1565    $self->progressdlg->Show(1);
1566    Wx::Yield();
1567   
1568    my $files = [
1569        map {
1570            encode('iso-8859-1', $_)
1571        }@$file_paths   
1572    ];
1573
1574    @$files = sort @$files;   
1575
1576    $self->imagelist->SetNewFiles(
1577        $files
1578    );
1579
1580   
1581}
1582
1583sub OnTreeSelChanged {
1584    my( $self, $event ) = @_;
1585 
1586    my @items = $self->tree->GetSelections;
1587
1588    $self->imagelist->categories(
1589        [
1590            map {
1591                my $category = $self->tree->GetPlData( $_ );
1592                $category->{id} if $category != -1;
1593            }
1594            @items
1595        ]
1596    );
1597}
1598
1599sub OnTreeItemRightClick {
1600    my( $self, $event ) = @_;
1601
1602
1603    $self->PopupMenu($self->tree_mnu, wxDefaultPosition);
1604       
1605}
1606
1607sub OnTreeEndLabelEdit {
1608    my( $self, $event ) = @_;
1609
1610
1611    my $category = $self->tree->GetPlData($event->GetItem);
1612    my $category_id;
1613   
1614    $category_id = $category->{id} if 'HASH' eq ref($category) ;
1615    my $comment;
1616    my ( $success, $status_msg, $content ) = $self->pwg->SetInfoCategories( $event->GetLabel, $comment, $category_id);
1617
1618    my $ok = 1;
1619   
1620    if(!$success){
1621        $ok = 0;
1622    }
1623
1624    if('fail' eq $content->{stat}){
1625        $ok = 0;
1626    }
1627
1628    # method call failed
1629    if(!$ok){
1630        $event->Veto;
1631        Wx::MessageBox( 
1632            sprintf(
1633                "%s %s", 
1634                gettext("Update failed : "),
1635                $status_msg
1636            ),
1637            gettext("Piwigo update error"),
1638            wxOK | wxICON_EXCLAMATION, 
1639        );
1640        Wx::LogMessage("%s\n\n%s", Dumper($content), gettext("This function is not available. A Piwigo upgrade may resolve this issue."));
1641    }
1642}
1643
1644sub OnImageViewerItemRightClick {
1645    my( $self, $event ) = @_;
1646
1647   
1648    $self->PopupMenu($self->imageviewer_mnu, wxDefaultPosition);
1649       
1650       
1651}
1652
1653sub OnExpandCategories {
1654    my ( $self, $event ) = @_;
1655
1656    my $parent_item = $self->tree->GetSelection;
1657    $self->tree->ExpandAllChildren($parent_item);
1658    $self->tree->EnsureVisible($parent_item);
1659}
1660
1661sub OnCollapseCategories {
1662    my ( $self, $event ) = @_;
1663
1664    my $parent_item = $self->tree->GetSelection;
1665    $self->tree->CollapseAllChildren($parent_item);
1666    $self->tree->Expand($parent_item) if -1 == $self->tree->GetPlData($parent_item);
1667}
1668
1669sub OnAddCategories {
1670    my ( $self, $event ) = @_;
1671
1672    my $parent_item = $self->tree->GetSelection;
1673
1674    my $category = $self->tree->GetPlData($parent_item);
1675    my $category_id;
1676   
1677    $category_id = $category->{id} if 'HASH' eq ref($category) ;
1678
1679    my $dialog = Wx::TextEntryDialog->new( 
1680        $self, 
1681        wxTheApp->branding->{'Category name'}, 
1682        wxTheApp->branding->{'Add new category'},
1683        wxTheApp->branding->{'New category'}, 
1684    );
1685
1686    if( $dialog->ShowModal != wxID_CANCEL ) {
1687        my $name = $dialog->GetValue;
1688        my ( $success, $status_msg, $content ) = $self->pwg->AddCategories( $name, $category_id);
1689
1690        if($success){
1691            $self->_append_category($parent_item, $name, $content->{result}{id});
1692        }
1693    }
1694    $dialog->Destroy;
1695}
1696
1697sub OnRefreshCategories {
1698    my ( $self, $event ) = @_;
1699
1700    $self->_refresh_all_categories_helper;
1701}
1702
1703
1704sub _refresh_all_categories_helper {
1705    my ( $self ) = @_; 
1706
1707    my $busycursor = Wx::BusyCursor->new();
1708    $self->tree->CollapseAll;
1709    $self->tree->DeleteAllItems;
1710    $self->imagelist->categories([]);
1711    $self->pwg->RefreshCategories();
1712    $self->populate_tree_categories;
1713}
1714
1715sub _append_category {
1716    my ( $self, $parent_id, $name, $id ) = @_;
1717
1718    $self->tree->SelectItem(
1719        $self->tree->AppendItem(
1720            $parent_id, 
1721            $name, 
1722            1, 
1723            -1, 
1724            Wx::TreeItemData->new( { id => $id } )
1725        )
1726    );
1727}
1728
1729sub OnImageViewerEndLabelEdit {
1730    my( $self, $event ) = @_;
1731 
1732    my $image = $self->imagelist->GetImage($event->GetIndex);
1733    $image->site_name(
1734        $event->GetLabel
1735    );
1736       
1737    $self->image_prop_piwigo->Refresh;
1738}
1739
1740sub OnImageViewerItemActivated {
1741    my( $self, $event ) = @_;
1742   
1743    $self->current_imageviewer_index(
1744        $event->GetIndex
1745    );
1746
1747    $self->OnPhotoProperties;
1748}
1749
1750
1751sub OnImageViewerItemSelected {
1752    my( $self, $event ) = @_;
1753 
1754    my $indx = $event->GetIndex;
1755
1756    $self->_on_imageviewer_item_selected($indx);
1757
1758    $event->Skip;
1759}
1760
1761sub _on_imageviewer_item_selected {
1762    my ( $self, $index ) = @_; 
1763
1764    $self->current_imageviewer_index($index);
1765    $self->imagelist->SetCurrentImage($index);
1766   
1767    $self->imagelist->image_selection(
1768        $self->imageviewer->GetSelectedItems
1769    );
1770
1771    $self->_image_preview_refresh if @{$self->imagelist->image_selection} < 2;
1772   
1773    $self->manager->Update;
1774   
1775    $self->image_prop_piwigo->Refresh;
1776    $self->image_prop_exif->Refresh;
1777    $self->image_prop_tags->Refresh;
1778
1779}
1780
1781sub _image_preview_refresh {
1782    my ( $self ) = @_; 
1783
1784
1785    my $html_src = sprintf("
1786      <html>
1787         <body>
1788             <img src=\"%s\"/>
1789         </body>
1790      </html>
1791      ",
1792      $self->imagelist->current_image->preview_file, 
1793    );
1794       
1795    $self->image_preview->SetPage(
1796        $html_src
1797    );
1798
1799    my $bmp = Wx::Bitmap->new( 
1800            $self->imagelist->current_image->preview_file, 
1801            $self->GetWxBitmapType($self->imagelist->type), 
1802        );
1803
1804    my $size = [40+$bmp->GetWidth, 60+$bmp->GetHeight];
1805
1806    $self->manager->GetPane("image_preview")->FloatingSize($size);
1807   
1808}
1809
1810sub OnImageViewerKeyDown {
1811    my( $self, $event ) = @_;
1812
1813    if(WXK_DELETE == $event->GetKeyCode){
1814        $self->OnRemoveImages();
1815       
1816        my $index = $self->current_imageviewer_index < $self->imageviewer->GetItemCount ?
1817            $self->current_imageviewer_index : $self->imageviewer->GetItemCount -1 ;
1818        $self->imageviewer->SelectItem(
1819            $index
1820        );
1821    }   
1822
1823}
1824
1825sub OnUploadImages {
1826    my( $self, $event ) = @_;
1827
1828    eval {
1829        $self->ProcessImageSelection();   
1830    };
1831}
1832
1833# remove image from imagelist when uploaded
1834sub UploadImagesViewerRefresh {
1835    my ( $self ) = @_; 
1836
1837    $self->imageviewer->Refresh;
1838    Wx::Yield();
1839}
1840
1841sub UploadProgressMessageRefresh {
1842    my ( $self, $msg ) = @_;   
1843
1844    $self->upload_progressdlg->processing(
1845        $msg   
1846    ); 
1847
1848    Wx::Yield();
1849}
1850
1851sub UploadProgressThumbnailRefresh {
1852    my ( $self ) = @_; 
1853
1854    my $imagelist = $self->imagelist ;
1855
1856 
1857    $self->upload_progressdlg->image->SetBitmap(wxNullBitmap);
1858    $self->upload_progressdlg->image->SetBitmap(
1859        Wx::Bitmap->new( 
1860            $self->imagelist->current_image->wx_thumb_file, 
1861            $self->GetWxBitmapType($self->imagelist->type), 
1862        )
1863    );
1864
1865    Wx::Yield();
1866}
1867
1868sub UploadProgressBarRefresh {
1869    my ( $self, $ratio ) = @_; 
1870
1871    $ratio = $self->imagelist->count > 1 ? 1 : $ratio; 
1872    eval {
1873        $self->upload_progressdlg->progress(
1874            $ratio*$self->imagelist->count * ( 100/scalar @{$self->imagelist->image_selection} )
1875        );
1876        $self->upload_progressdlg->LogProgress();
1877    };
1878    croak gettext("Upload cancelled") if $@;
1879
1880    Wx::Yield();
1881}
1882
1883sub SetNewFilesDisplayEndInfo {
1884    my ( $self, $msg ) = @_;   
1885       
1886    $self->progressdlg->DisplayEndInfo($msg);
1887}
1888
1889sub UploadDisplayEndInfo {
1890    my ( $self, $msg ) = @_;   
1891   
1892    my $imagelist = $self->imagelist ;
1893   
1894    $self->upload_progressdlg->DisplayEndInfo($msg);
1895}
1896
1897sub ShowImageViewer {
1898    my ( $self ) = @_; 
1899
1900    if(!$self->imageviewer->IsShown){
1901        $self->imageviewer->Show(1);
1902    }
1903}
1904
1905
1906sub ActivateImageViewer {
1907    my ( $self ) = @_; 
1908       
1909}
1910
1911
1912sub SetNewFilesViewerRefresh {
1913
1914    my ( $self ) = @_; 
1915
1916    my $wximagelist = $self->imagelist->wx_thumb_imglist;
1917
1918    my $indx = $wximagelist->Add(
1919        Wx::Bitmap->new( 
1920            $self->imagelist->current_image->wx_thumb_file, 
1921            $self->GetWxBitmapType($self->imagelist->type), 
1922        )
1923    ) if defined $self->imagelist->current_image->wx_thumb_file;
1924    print $self->imagelist->current_image->wx_thumb_file, " added with index ", $indx, "\n";   
1925    $self->imageviewer->Refresh(
1926        $wximagelist
1927    );
1928
1929    Wx::Yield();
1930}
1931
1932
1933
1934# prepare and upload image_selection
1935sub ProcessImageSelection {
1936    my ( $self ) = @_;
1937
1938    return if !scalar @{$self->imagelist->sums};
1939
1940    if( scalar @{$self->imagelist->categories} ){
1941        # all selected is implicit
1942        if(!scalar @{$self->imageviewer->GetSelectedItems}){
1943       
1944            $self->imagelist->image_selection(
1945                $self->imageviewer->GetAllItems
1946            );
1947        }
1948       
1949        return if( !defined $self->imagelist->image_selection );
1950        return if( !scalar @{$self->imagelist->image_selection} );
1951       
1952        $self->upload_progressdlg(
1953            Uploader::GUI::wxImageProcessingProgressDlg->new(
1954                { 
1955                    title    => gettext("Image upload progress information"),
1956                    bt_label => gettext("Cancel upload"), 
1957                 }
1958            )       
1959        );
1960        # modeless dialog
1961        $self->upload_progressdlg->Show(1);
1962        Wx::Yield();
1963        eval {
1964            $self->imagelist->UploadSelection;
1965        };
1966        if($@){
1967            Wx::MessageBox( 
1968                sprintf(
1969                    gettext("Upload cancelled"),
1970                ),
1971                gettext("Piwigo upload information"),
1972                wxOK | wxICON_INFORMATION, 
1973            );
1974        }
1975    }
1976    else {
1977        Wx::MessageBox( 
1978            sprintf(
1979                "%s %s", 
1980                gettext("Please select a valid target"),
1981                wxTheApp->branding->{category}
1982            ),
1983            gettext("Piwigo upload error"),
1984            wxOK | wxICON_EXCLAMATION, 
1985        );
1986    }
1987}
1988
1989
1990sub SetNewFilesProgress {
1991    my ( $self ) = @_;
1992
1993    my $imagelist = $self->imagelist;
1994
1995    $self->progressdlg->processing(
1996        sprintf(
1997            $imagelist->progress_msg, 
1998            $imagelist->current_image->file,
1999        )
2000    );
2001
2002    eval {
2003        $self->progressdlg->image->SetSize([ $imagelist->wx_thumb_size, $imagelist->wx_thumb_size]);
2004        $self->progressdlg->image->SetBitmap(wxNullBitmap);
2005        $self->progressdlg->image->SetBitmap(
2006            Wx::Bitmap->new( 
2007                $imagelist->current_image->wx_thumb_file,
2008                $self->GetWxBitmapType( $imagelist->type )
2009            )
2010        );
2011        $self->progressdlg->progress(
2012            $imagelist->count * ( 100/scalar @{$imagelist->new_files} )
2013        );
2014        $self->progressdlg->LogProgress();
2015    };
2016    Wx::Yield();
2017}
2018
2019sub OnClose {
2020  my $self = shift;
2021
2022
2023    # Restaure previous log wnd
2024    Wx::Log::SetActiveTarget( $self->oldlogwnd );
2025
2026    # allways store
2027 
2028    wxTheApp->StoreConnectionProperties;
2029   
2030    $self->imagelist->Store;
2031    wxTheApp->login_dlg->Destroy;       
2032
2033    wxTheApp->perspective(
2034        $self->manager->SavePerspective
2035    );
2036   
2037    wxTheApp->imageviewerIndex(
2038        $self->current_imageviewer_index
2039    );
2040   
2041    my $frameLayout = {};
2042   
2043    ( $frameLayout->{pX}, $frameLayout->{pY}, $frameLayout->{W}, $frameLayout->{H} ) = ( $self->GetPositionXY, $self->GetSizeWH ) ; 
2044   
2045    wxTheApp->frameLayout(
2046        $frameLayout
2047    );
2048
2049    wxTheApp->StoreLayoutProperties;
2050
2051    $self->Destroy;
2052}
2053
2054
2055sub create_toolbar {
2056    my( $self ) = @_;
2057
2058    my $tb = Wx::ToolBar->new( $self, -1, wxDefaultPosition, wxDefaultSize, wxTB_FLAT );
2059    $tb->SetToolBitmapSize( wxSIZE( 32, 32 ) );
2060    map {
2061        my $icon1 = Wx::Icon->new();
2062        eval {
2063            $icon1->LoadFile($_->[2], $_->[3]);
2064        };
2065        my $tb_icon1 = Wx::Bitmap->new( $icon1 );
2066
2067        my $icon2 = Wx::Icon->new();
2068        eval {
2069            $icon2->LoadFile($_->[5], $_->[3]);
2070        };
2071        my $tb_icon2 = Wx::Bitmap->new( $icon2 );
2072
2073
2074        $tb->AddTool( $_->[0], $_->[1], $tb_icon1, $tb_icon2, wxITEM_NORMAL, $_->[1] );
2075        $tb->EnableTool( $_->[0], $_->[4]);
2076    }
2077    (
2078        [
2079            100, 
2080            gettext("Getting started"), 
2081            '../res/tb_getting_started.png', 
2082            wxBITMAP_TYPE_PNG, 
2083            1, 
2084            '../res/tb_getting_started.png', 
2085            gettext("Display getting started panel")
2086        ],
2087        [
2088            101, 
2089            gettext("Add photo to selection"), 
2090            '../res/tb_add.png', 
2091            wxBITMAP_TYPE_PNG, 
2092            1, 
2093            '../res/tb_add.png', 
2094            gettext("Add photo to selection for resizing and uploading")
2095        ],
2096        [
2097            102, 
2098            gettext("Remove photo from selection"), 
2099            '../res/tb_remove.png', 
2100            wxBITMAP_TYPE_PNG, 
2101            1, 
2102            '../res/tb_remove.png',
2103            gettext("Remove photo from selection. Files are not deleted ")
2104        ],
2105        [
2106            103, 
2107            gettext("Upload to Piwigo"), 
2108            '../res/tb_upload.png', 
2109            wxBITMAP_TYPE_PNG, 
2110            wxTheApp->use_offline ? 0 : 1, 
2111            '../res/tb_upload.png',
2112            gettext("Upload photos to Piwigo.")
2113        ],
2114        [
2115            104, 
2116            gettext("Global settings"), 
2117            '../res/tb_settings.png', 
2118            wxBITMAP_TYPE_PNG, 
2119            0, 
2120            '../res/tb_settings.png',
2121            gettext("Change global settings.")
2122        ],
2123        [
2124            105, 
2125            gettext("Language choice"), 
2126            '../res/tb_i18n.png', 
2127            wxBITMAP_TYPE_PNG, 
2128            1, 
2129            '../res/tb_i18n.png',
2130            gettext("Language choice")
2131        ],
2132   
2133    );
2134
2135    if($@){
2136        undef $tb;
2137    }
2138    else{
2139        $tb->Realize;
2140    }
2141
2142    return $tb;
2143}
2144
2145
2146sub _create_textctrl {
2147    my( $self, $parent, $text, $size ) = @_;
2148
2149    return Wx::TextCtrl->new( $parent, -1, $text, [0, 0], $size,
2150                              wxNO_BORDER | wxTE_MULTILINE | wxTE_READONLY  );
2151}
2152
2153sub create_textctrl {
2154    my( $self, $text, $size ) = @_;
2155
2156    return $self->_create_textctrl( $self, $text, $size );
2157}
2158
2159sub DESTROY {
2160    my( $self ) = @_;
2161
2162    $self->manager->UnInit;
2163}
2164
2165
2166
21671;
2168
2169
2170
2171
2172
2173package DNDImageListDropTarget;
2174use Wx qw/wxTheApp/;
2175use base qw(Wx::FileDropTarget Class::Accessor::Fast);
2176
2177__PACKAGE__->mk_accessors( 
2178    qw/
2179          imageviewer
2180      /
2181);
2182
2183sub new {
2184  my $class = shift;
2185  my $imageviewer = shift;
2186  my $self = $class->SUPER::new( @_ );
2187
2188  $self->imageviewer($imageviewer);
2189
2190  return $self;
2191}
2192
2193sub OnDropFiles {
2194  my( $self, $x, $y, $files ) = @_;
2195
2196  wxTheApp->frame->SetNewFiles($files) ;
2197}
2198
2199
2200
2201
22021;
2203
2204
2205package DNDCategoryTreeDropTarget;
2206
2207use base qw(Wx::TextDropTarget Class::Accessor::Fast);
2208use Data::Dumper;
2209use Wx qw/
2210              wxDragNone
2211              wxDragCopy
2212              wxDragMove
2213         /;
2214
2215__PACKAGE__->mk_accessors( 
2216    qw/
2217          tree
2218          frame
2219      /
2220);
2221
2222sub new {
2223  my ( $class, $tree ) = @_;
2224  my $self = $class->SUPER::new();
2225
2226  $self->tree($tree);
2227  $self->frame($tree->GetParent);
2228  return $self;
2229}
2230
2231
2232
2233sub OnDropText {
2234  my( $self, $x, $y, $textdata ) = @_;
2235
2236  # must be $VAR1 because $textdata is the result of Data::Dumper
2237  my $VAR1;
2238  eval $textdata;
2239  eval {
2240      if(scalar @$VAR1){
2241           my @items;
2242           if(scalar @items < 2) {
2243               my ($dropItem, $flag) = $self->tree->HitTest([$x, $y]);
2244                push @items, $dropItem;
2245           }
2246           else {
2247                @items = $self->tree->GetSelections;
2248           }
2249           
2250           # remove root item which is not a valid category
2251           @items = grep { $self->tree->GetPlData( $_ ) != -1 } @items;
2252           
2253           $self->frame->imagelist->categories(
2254               [
2255                   map {
2256                       $self->tree->GetPlData( $_ )->{id};
2257                   }
2258                   @items
2259               ]
2260           );
2261           
2262           $self->frame->imagelist->image_selection($VAR1);
2263           $self->frame->ProcessImageSelection ;
2264      } 
2265  };
2266}
2267
22681;
Note: See TracBrowser for help on using the repository browser.