line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Tk::VisualBrowser;
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
$VERSION = "0.14";
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# TODO Font, anchor für Label per option
|
6
|
|
|
|
|
|
|
#
|
7
|
2
|
|
|
2
|
|
49747
|
use Carp;
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
162
|
|
8
|
2
|
|
|
2
|
|
10
|
use File::Basename;
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
178
|
|
9
|
2
|
|
|
2
|
|
806
|
use Tk;
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
use Tk::Event;
|
11
|
|
|
|
|
|
|
use Tk::Balloon;
|
12
|
|
|
|
|
|
|
#use Tk::ErrorDialog;
|
13
|
|
|
|
|
|
|
use Tk::XPMs qw(:arrows);
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
require Tk::Frame;
|
16
|
|
|
|
|
|
|
use base qw(Tk::Frame);
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
use strict;
|
19
|
|
|
|
|
|
|
use constant NORMAL => 0;
|
20
|
|
|
|
|
|
|
use constant MOVE => 1;
|
21
|
|
|
|
|
|
|
my $state = NORMAL;
|
22
|
|
|
|
|
|
|
my $save_cursor;
|
23
|
|
|
|
|
|
|
my $cursor;
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $do_scroll = 1;
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# PDO {{{
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 NAME
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Tk::VisualBrowser - Visual Browser for image directories
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
use Tk;
|
37
|
|
|
|
|
|
|
use Tk::VisualBrowser;
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
my $top = MainWindow->new();
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my $vsb = $top->VisualBrowser;
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my @PICTURES = qw( f1.jpg f2.jpg f3.gif);
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
$vsb->configure(
|
46
|
|
|
|
|
|
|
-rows => 5, -cols => 6,
|
47
|
|
|
|
|
|
|
-pictures => \@PICTURES,
|
48
|
|
|
|
|
|
|
-thumbnail => \&thumbnail_handler,
|
49
|
|
|
|
|
|
|
-special_color => \&special_color_handler,
|
50
|
|
|
|
|
|
|
-b1_handler => \&my_b1_handler,
|
51
|
|
|
|
|
|
|
-b2_handler => \&my_b2_handler,
|
52
|
|
|
|
|
|
|
-b3_handler => \&my_b3_handler,
|
53
|
|
|
|
|
|
|
-double_b1_handler => \&my_bdouble_1_handler,
|
54
|
|
|
|
|
|
|
-double_b2_handler => \&my_bdouble_2_handler,
|
55
|
|
|
|
|
|
|
-double_b3_handler => \&my_bdouble_3_handler,
|
56
|
|
|
|
|
|
|
);
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
$vsb->scroll(0); # scroll to first picture
|
59
|
|
|
|
|
|
|
# this will implicitely load the pictures
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
C is a megawidget which displays a matrix of
|
65
|
|
|
|
|
|
|
(C<-rows>) x (C<-cols>) Labels with thumbnail images. It can be used,
|
66
|
|
|
|
|
|
|
for example, to create a visual directory browser for image directories
|
67
|
|
|
|
|
|
|
or an interactive program for sorting images (dia-sorter.pl).
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
The application program must provide a reference to a list of image
|
70
|
|
|
|
|
|
|
filenames and a handler which returns the filename of a corresponding
|
71
|
|
|
|
|
|
|
thumbnail GIF image for a given image filename.
|
72
|
|
|
|
|
|
|
C displays the thumbnail pictures and provides some
|
73
|
|
|
|
|
|
|
navigation buttons for scrolling linewise or pagewise through the list.
|
74
|
|
|
|
|
|
|
A scrollbar is also attached to the widget.
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
It is possible to select thumbnails with the left moust button or to
|
77
|
|
|
|
|
|
|
select ranges of thumbnails with shift-click (as you would select files in
|
78
|
|
|
|
|
|
|
normal file browser). Ctrl-click allows adding or removing single thumbnails
|
79
|
|
|
|
|
|
|
from a selection.
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
The selected thumbnails may be moved around with the left mouse button.
|
82
|
|
|
|
|
|
|
The cursor image changes and all thumbnails which are currently under the
|
83
|
|
|
|
|
|
|
mouse will be highlighted while moving around. Releasing the mouse button
|
84
|
|
|
|
|
|
|
inserts the selected thumbnails before the current position.
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
When moving around, an automatic scroll up or down is triggered when the
|
87
|
|
|
|
|
|
|
mouse comes close to the upper or lower margin of the C.
|
88
|
|
|
|
|
|
|
But only one linewise scroll is triggered at a time (in order to avoid the
|
89
|
|
|
|
|
|
|
scrollbar from running away). Try going back and forth with the mouse
|
90
|
|
|
|
|
|
|
to trigger further scrolls as needed.
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head1 CONFIGURATION
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
There are the following possibilities for configuring the C:
|
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=head2 Rows and Columns
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Use C<-rows> and C<-cols> to specify the number of rows and columns
|
99
|
|
|
|
|
|
|
of the C
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
$vsb->configure(-rows => 4, -cols => 8);
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
NOTE: C<-cols> and/or C<-rows> B be configured in order to
|
104
|
|
|
|
|
|
|
get the C up and running: Only when configuring
|
105
|
|
|
|
|
|
|
columns or rows the C will be (re-)built.
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=head2 List of Images
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
The list of images to be displayed is passed as a reference via
|
110
|
|
|
|
|
|
|
the C<-pictures> option:
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
$vsb->configure(-pictures => \@PICTURES);
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
The C needs GIF images for each image filename in the list.
|
115
|
|
|
|
|
|
|
To this end a handler is specified which returns the name of the
|
116
|
|
|
|
|
|
|
corresponding GIF image when fed with an image filename:
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
$vsb->configure(-thumbnail => \&thumbnail_handler);
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub thumbnail_handler {
|
121
|
|
|
|
|
|
|
my ($image_filename) = @_;
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# for example: (assuming that the thumbnails are
|
124
|
|
|
|
|
|
|
# in the same directory but with .gif extension):
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
$image_filename =~ s/\.jpg/.gif/i;
|
127
|
|
|
|
|
|
|
return $image_filename;
|
128
|
|
|
|
|
|
|
}
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
It could also be arranged that the thumbnail_handler creates the GIF
|
131
|
|
|
|
|
|
|
images when they do not yet exist. So the viewing of an image directory
|
132
|
|
|
|
|
|
|
would automatically create the thumbnails (with Image::Magick, for example).
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
NOTE: The names in the @PICTURES array need not be valid filenames,
|
135
|
|
|
|
|
|
|
although they normally are. The names of the GIF files
|
136
|
|
|
|
|
|
|
provided by the thumbnail_handler must be valid filenames,
|
137
|
|
|
|
|
|
|
either relative to the current working directory or absolute
|
138
|
|
|
|
|
|
|
pathnames.
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=head2 Handlers for Mouse Button Events
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
The application can specify its own handlers for mousebutton events, e. g.:
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
$vsb->configure(-doubel_b1_handler => \&my_double_1);
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub my_double_1 {
|
147
|
|
|
|
|
|
|
my ($image_filename) = @_;
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# display $image_filename in a Toplevel Window:
|
150
|
|
|
|
|
|
|
require Tk::JPEG;
|
151
|
|
|
|
|
|
|
my $show = $top->Toplevel();
|
152
|
|
|
|
|
|
|
my $image = $top->Photo('-format' => "jpeg",
|
153
|
|
|
|
|
|
|
-file => $image_filename);
|
154
|
|
|
|
|
|
|
$show->Label(-image => $image)->pack;
|
155
|
|
|
|
|
|
|
}
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=head2 Colors
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
The following table shows the possible color options:
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
-highlight => "#rrggbb" color for moving around
|
162
|
|
|
|
|
|
|
-active_color => "#rrggbb" color for selected thumbs
|
163
|
|
|
|
|
|
|
-bg_color1 => "#rrggbb" background color for plane
|
164
|
|
|
|
|
|
|
-bg_color => "#rrggbb" background color for thumbs
|
165
|
|
|
|
|
|
|
-cursor_bg => "#rrggbb" background color for cursor
|
166
|
|
|
|
|
|
|
-cursor_fg => "#rrggbb" foreground color for cursor
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
When you have selected some thumbnails, they are colored with the
|
169
|
|
|
|
|
|
|
C<-active_color> option. Moving them around will highlight the
|
170
|
|
|
|
|
|
|
thumbnail under the cursor with C<-highlight> color to indicate the
|
171
|
|
|
|
|
|
|
current insert position.
|
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
NOTE: Color options must be specified at the very beginning, when the
|
174
|
|
|
|
|
|
|
C is instantiated. Later reconfigurations may have no effect.
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
It is possible to provide a handler which makes sure that certain images
|
177
|
|
|
|
|
|
|
get a different background color (for example to indicate that these
|
178
|
|
|
|
|
|
|
images have been changed recently):
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
$vsb->configure(-special_color => \&my_color_hdlr);
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub my_color_hdlr {
|
183
|
|
|
|
|
|
|
my ($image_filename) = @_;
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# decide if $image_filname needs to be displayed with a different
|
186
|
|
|
|
|
|
|
# background color:
|
187
|
|
|
|
|
|
|
if ( -M $image_filename < 7 ) {
|
188
|
|
|
|
|
|
|
return "#cc2222"; # use special bg color
|
189
|
|
|
|
|
|
|
}
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
return 0; # no special color
|
192
|
|
|
|
|
|
|
}
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=head2 Labels and Balloons
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
It is possible to use Labels for each image and to have balloon messages on each image (i. e.
|
197
|
|
|
|
|
|
|
a small window with text pops up when the cursor hovers over an image). In order to activate this
|
198
|
|
|
|
|
|
|
features use the following options:
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
-use_labels => 1
|
201
|
|
|
|
|
|
|
-use_balloons => 1
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
The default text for labels and balloons are the basenames of the image filenames. You can, however,
|
204
|
|
|
|
|
|
|
set the labels and balloon texts indiviually by passing references to corresponding arrays the the
|
205
|
|
|
|
|
|
|
VisualBrowser:
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
-balloon_texts => \@Array_with_balloon_texts
|
208
|
|
|
|
|
|
|
-label_texts => \@Array_with_label_texts
|
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
This may be used, for example, to prepare an array with text for each image which contains the filename
|
211
|
|
|
|
|
|
|
and EXIF information for the image.
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head1 METHODS
|
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
The following methods are available:
|
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=cut
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# }}}
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Construct Tk::Widget 'VisualBrowser';
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# Public Methods
|
224
|
|
|
|
|
|
|
# ==============
|
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub get_selected { # {{{
|
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
=head2 my @SELECTED = $vsb->get_selected;
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
Returns the list of currently selected images. The list contains the
|
231
|
|
|
|
|
|
|
filenames of the selected pictures. This might be useful for the
|
232
|
|
|
|
|
|
|
creation of a slideshow control file with the names of the selected
|
233
|
|
|
|
|
|
|
images.
|
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=cut
|
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
my ($w) = @_;
|
238
|
|
|
|
|
|
|
my @LIST = ();
|
239
|
|
|
|
|
|
|
for (my $i=0; $i < @{$w->{SEL}}; $i++){
|
240
|
|
|
|
|
|
|
push @LIST, $w->{pictures}[$i] if $w->{SEL}[$i];
|
241
|
|
|
|
|
|
|
} # for $i
|
242
|
|
|
|
|
|
|
return @LIST;
|
243
|
|
|
|
|
|
|
} # get_selected }}}
|
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
sub get_selected_idx{ # {{{
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=head2 my @SELECTED = $vsb->get_selected_idx;
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
Returns the list of currently selected images. The list contains the index numbers,
|
250
|
|
|
|
|
|
|
not the filenames.
|
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=cut
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
my ($w) = @_;
|
255
|
|
|
|
|
|
|
my @LIST = ();
|
256
|
|
|
|
|
|
|
for (my $i=0; $i < @{$w->{SEL}}; $i++){
|
257
|
|
|
|
|
|
|
push @LIST, $i if $w->{SEL}[$i];
|
258
|
|
|
|
|
|
|
} # for $i
|
259
|
|
|
|
|
|
|
return @LIST;
|
260
|
|
|
|
|
|
|
} # get_selected_idx }}}
|
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub select { # {{{
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=head2 $vsb->select($idx);
|
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
Select specified picture with index $idx. Note that other pictures are not
|
267
|
|
|
|
|
|
|
deselected automatically.
|
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=cut
|
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
my ($w, $z) = @_;
|
272
|
|
|
|
|
|
|
$w->{SEL}[$z] = 1;
|
273
|
|
|
|
|
|
|
_select_pic($w, $z, 1);
|
274
|
|
|
|
|
|
|
} # select }}}
|
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub select_all { # {{{
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=head2 $vsb->select_all;
|
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
Selectes all pictures together.
|
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
=cut
|
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
my ($w) = @_;
|
285
|
|
|
|
|
|
|
for ( my $z = 0; $z <= $#{$w->{pictures}}; $z++ ){
|
286
|
|
|
|
|
|
|
$w->{SEL}[$z] = 1;
|
287
|
|
|
|
|
|
|
_select_pic($w, $z, 1);
|
288
|
|
|
|
|
|
|
}
|
289
|
|
|
|
|
|
|
} # select_all }}}
|
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
sub deselect_all { # {{{
|
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head2 $vsb->deselect_all;
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Deselectes all pictures.
|
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=cut
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
my ($w) = @_;
|
300
|
|
|
|
|
|
|
for ( my $z = 0; $z <= $#{$w->{pictures}}; $z++ ){
|
301
|
|
|
|
|
|
|
$w->{SEL}[$z] = 0;
|
302
|
|
|
|
|
|
|
_select_pic($w, $z, 0);
|
303
|
|
|
|
|
|
|
}
|
304
|
|
|
|
|
|
|
} # deselect_all }}}
|
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
sub remove_selected { # {{{
|
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head2 $vsb->remove_selected;
|
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
This command removes the selected images from the list of pictures.
|
311
|
|
|
|
|
|
|
Note that the original list is changed because you passed a reference to
|
312
|
|
|
|
|
|
|
this list via C<-pictures>.
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=cut
|
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
my ($w) = @_;
|
317
|
|
|
|
|
|
|
# delete all selected pictures from list
|
318
|
|
|
|
|
|
|
# when there are labels and/or balloons: delete from theses lists also
|
319
|
|
|
|
|
|
|
for (my $i = @{$w->{SEL}} -1; $i>=0; $i--){
|
320
|
|
|
|
|
|
|
if ($w->{SEL}[$i]) {
|
321
|
|
|
|
|
|
|
splice( @{ $w->cget('-pictures') }, $i, 1) ;
|
322
|
|
|
|
|
|
|
my $lref = $w->cget('-label_texts');
|
323
|
|
|
|
|
|
|
if ($lref and ref($lref) eq 'ARRAY' and @$lref) {
|
324
|
|
|
|
|
|
|
splice( @{ $w->cget('-label_texts') }, $i, 1) ;
|
325
|
|
|
|
|
|
|
}
|
326
|
|
|
|
|
|
|
my $bref = $w->cget('-balloon_texts');
|
327
|
|
|
|
|
|
|
if ($bref and ref($bref) eq 'ARRAY' and @$bref and $bref != $lref) {
|
328
|
|
|
|
|
|
|
splice( @{ $w->cget('-balloon_texts') }, $i, 1) ;
|
329
|
|
|
|
|
|
|
}
|
330
|
|
|
|
|
|
|
}
|
331
|
|
|
|
|
|
|
}
|
332
|
|
|
|
|
|
|
@{$w->{SEL}} = map {0} @{$w->cget('-pictures')};
|
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
scroll($w, $w->{posi});
|
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
}# remove_selected }}}
|
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
sub swap_selected { # {{{
|
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=head2 $vsb->swap_selected;
|
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
Swaps two selected pictures. Returns 1 in case of success and 0 otherwise.
|
343
|
|
|
|
|
|
|
NOTE: The user must have selected exactly two pictures.
|
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=cut
|
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
my ($w) = @_;
|
348
|
|
|
|
|
|
|
my @SL; # indices of selected pics
|
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
# Ermitteln, welche beiden Bilder selektiert sind.
|
351
|
|
|
|
|
|
|
for (my $i=0; $i < @{$w->{SEL}}; $i++){
|
352
|
|
|
|
|
|
|
push @SL, $i if $w->{SEL}[$i];
|
353
|
|
|
|
|
|
|
} # for $i
|
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
if (scalar(@SL) != 2){
|
356
|
|
|
|
|
|
|
return 0; # not ok, need exactly two selected images
|
357
|
|
|
|
|
|
|
}
|
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# ok: swap pics and display again
|
360
|
|
|
|
|
|
|
my $pref = $w->cget('-pictures');
|
361
|
|
|
|
|
|
|
($$pref[ $SL[0] ], $$pref[ $SL[1] ]) =
|
362
|
|
|
|
|
|
|
($$pref[ $SL[1] ], $$pref[ $SL[0] ]);
|
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# if we have labels and/or ballons: swap also:
|
365
|
|
|
|
|
|
|
my $lref = $w->cget('-label_texts');
|
366
|
|
|
|
|
|
|
if ($lref and ref($lref) eq 'ARRAY' and @$lref) {
|
367
|
|
|
|
|
|
|
($$lref[ $SL[0] ], $$lref[ $SL[1] ]) =
|
368
|
|
|
|
|
|
|
($$lref[ $SL[1] ], $$lref[ $SL[0] ]);
|
369
|
|
|
|
|
|
|
}
|
370
|
|
|
|
|
|
|
my $bref = $w->cget('-balloon_texts');
|
371
|
|
|
|
|
|
|
if ($bref and ref($bref) eq 'ARRAY' and @$bref and $bref != $lref) {
|
372
|
|
|
|
|
|
|
($$bref[ $SL[0] ], $$bref[ $SL[1] ]) =
|
373
|
|
|
|
|
|
|
($$bref[ $SL[1] ], $$bref[ $SL[0] ]);
|
374
|
|
|
|
|
|
|
}
|
375
|
|
|
|
|
|
|
$w->{SEL}[ $SL[0] ] = 0; # deselect ...
|
376
|
|
|
|
|
|
|
$w->{SEL}[ $SL[1] ] = 0; # deselect ...
|
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
scroll($w, $w->{posi});
|
379
|
|
|
|
|
|
|
return 1; # ok
|
380
|
|
|
|
|
|
|
} # swap_selected }}}
|
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
sub scroll { # {{{
|
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=head2 $vsb->scroll();
|
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
Scrolls the C to the specified position.
|
387
|
|
|
|
|
|
|
may have the following values:
|
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
adjust the view so that the image with index
|
390
|
|
|
|
|
|
|
appears in the upper left corner.
|
391
|
|
|
|
|
|
|
"p" go back one line (previous line)
|
392
|
|
|
|
|
|
|
"pp" go back one page (previous page)
|
393
|
|
|
|
|
|
|
"n" scroll forward one line (next line)
|
394
|
|
|
|
|
|
|
"nn" scroll forward one page (next page)
|
395
|
|
|
|
|
|
|
"l" scroll to last image
|
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
In order to go to the first image, you should use the numeric value 0.
|
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=cut
|
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
# Scroll to absolute position or scroll page wise or line wise.
|
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
405
|
|
|
|
|
|
|
return unless $do_scroll;
|
406
|
|
|
|
|
|
|
my $thmb;
|
407
|
|
|
|
|
|
|
my $k = 0;
|
408
|
|
|
|
|
|
|
my ($r,$c) = ($w->cget('-rows'), $w->cget('-cols'));
|
409
|
|
|
|
|
|
|
return unless defined $w->{Photo}[0][0];
|
410
|
|
|
|
|
|
|
return unless defined $c;
|
411
|
|
|
|
|
|
|
return unless defined $r;
|
412
|
|
|
|
|
|
|
return unless defined $w->cget("-pictures");
|
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
# print " scroll: pos: $pos\n";
|
415
|
|
|
|
|
|
|
my $ps = $w->{posi};
|
416
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
417
|
|
|
|
|
|
|
my $max = $#{$picref};
|
418
|
|
|
|
|
|
|
my $blnref = $w->cget('-balloon_texts');
|
419
|
|
|
|
|
|
|
my $lblref = $w->cget('-label_texts');
|
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
my $anz = $r * $c;
|
422
|
|
|
|
|
|
|
if ($pos =~ /^\d+$/){ # absolute
|
423
|
|
|
|
|
|
|
$k = trim_pos($w, $pos);
|
424
|
|
|
|
|
|
|
} elsif ( $pos eq "p") { # prev line
|
425
|
|
|
|
|
|
|
$k = trim_pos($w, $ps -$c);
|
426
|
|
|
|
|
|
|
} elsif ( $pos eq "pp") { # prev page
|
427
|
|
|
|
|
|
|
$k = trim_pos($w, $ps-$anz);
|
428
|
|
|
|
|
|
|
} elsif ( $pos eq "n") { # next line
|
429
|
|
|
|
|
|
|
$k = trim_pos($w, $ps +$c);
|
430
|
|
|
|
|
|
|
} elsif ( $pos eq "nn") { # next page
|
431
|
|
|
|
|
|
|
$k = trim_pos($w, $ps+$anz);
|
432
|
|
|
|
|
|
|
} elsif ( $pos eq "l") { # last page
|
433
|
|
|
|
|
|
|
$k = trim_pos($w, $max+1-$anz);
|
434
|
|
|
|
|
|
|
} else {
|
435
|
|
|
|
|
|
|
}
|
436
|
|
|
|
|
|
|
$w ->{posi} = $k;
|
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
# Picture with index $k is placed in upper left corner
|
439
|
|
|
|
|
|
|
my ($color, $relief) = ("#CCCCCC", "flat");
|
440
|
|
|
|
|
|
|
$do_scroll = 0;
|
441
|
|
|
|
|
|
|
my $use_balloon = $w->cget('-use_balloons');
|
442
|
|
|
|
|
|
|
my $use_labels = $w->cget('-use_labels');
|
443
|
|
|
|
|
|
|
for (my $i = 0; $i < $r; $i++){
|
444
|
|
|
|
|
|
|
for (my $j = 0; $j < $c; $j++){
|
445
|
|
|
|
|
|
|
if ( $k <= $max and $k >= 0 ){
|
446
|
|
|
|
|
|
|
my $special_color = $w->Callback(-special_color => $$picref[$k]) || $w->cget("-bg_color");;
|
447
|
|
|
|
|
|
|
$relief = $w->{SEL}[$k] ? "groove" : "flat";
|
448
|
|
|
|
|
|
|
$color = $w->{SEL}[$k] ? $w->cget("-active_color") : $special_color;
|
449
|
|
|
|
|
|
|
$thmb = $w->Callback( -thumbnail => $$picref[$k]);
|
450
|
|
|
|
|
|
|
if (! -e $thmb){
|
451
|
|
|
|
|
|
|
$thmb = $w->{pic_path}."/vis-dummy.gif";
|
452
|
|
|
|
|
|
|
}
|
453
|
|
|
|
|
|
|
my $name = basename($$picref[$k]);
|
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
$w->{Photo}[$i][$j] -> configure( -file => $thmb );
|
456
|
|
|
|
|
|
|
if ($use_labels) {
|
457
|
|
|
|
|
|
|
if ( @{ $w->cget('-label_texts')} ) {
|
458
|
|
|
|
|
|
|
$name = $$lblref[$k];
|
459
|
|
|
|
|
|
|
}
|
460
|
|
|
|
|
|
|
$w->{Label}[$i][$j] = $name;
|
461
|
|
|
|
|
|
|
}
|
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
if ($use_balloon) {
|
464
|
|
|
|
|
|
|
if ( @{ $w->cget('-balloon_texts')} ) {
|
465
|
|
|
|
|
|
|
$name = $$blnref[$k];
|
466
|
|
|
|
|
|
|
}
|
467
|
|
|
|
|
|
|
$w->{bln}->detach( $w->{Thmb}[$i][$j]);
|
468
|
|
|
|
|
|
|
$w->{bln}->attach( $w->{Thmb}[$i][$j], -balloonmsg => "$name");
|
469
|
|
|
|
|
|
|
}
|
470
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] -> configure(
|
471
|
|
|
|
|
|
|
-width => 80,
|
472
|
|
|
|
|
|
|
-height => 80,
|
473
|
|
|
|
|
|
|
-background =>$color,
|
474
|
|
|
|
|
|
|
-relief => $relief,
|
475
|
|
|
|
|
|
|
-image => $w->{Photo}[$i][$j]
|
476
|
|
|
|
|
|
|
);
|
477
|
|
|
|
|
|
|
} else { # empty pictures after the end of our list
|
478
|
|
|
|
|
|
|
$thmb = $w->{pic_path}."/vis-empty.gif";
|
479
|
|
|
|
|
|
|
if ($use_labels) {
|
480
|
|
|
|
|
|
|
$w->{Label}[$i][$j] = "";
|
481
|
|
|
|
|
|
|
}
|
482
|
|
|
|
|
|
|
if ($use_balloon) {
|
483
|
|
|
|
|
|
|
$w->{bln}->detach( $w->{Thmb}[$i][$j]);
|
484
|
|
|
|
|
|
|
}
|
485
|
|
|
|
|
|
|
$w->{Photo}[$i][$j] -> configure( -file => $thmb );
|
486
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] -> configure(
|
487
|
|
|
|
|
|
|
-width => 80,
|
488
|
|
|
|
|
|
|
-height => 80,
|
489
|
|
|
|
|
|
|
-background => $w->cget("-bg_color"),
|
490
|
|
|
|
|
|
|
-relief => "flat",
|
491
|
|
|
|
|
|
|
-image => $w->{Photo}[$i][$j]
|
492
|
|
|
|
|
|
|
);
|
493
|
|
|
|
|
|
|
}
|
494
|
|
|
|
|
|
|
$k++; # next picture
|
495
|
|
|
|
|
|
|
#$w->MainWindow->update;
|
496
|
|
|
|
|
|
|
#$w->{Thmb}[$i][$j]->update; # same effect
|
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
# ACHTUNG: Unter Windows:
|
499
|
|
|
|
|
|
|
# wenn update Aktiv ist, tritt derselbe Effekt auf, wie unter Linux ....
|
500
|
|
|
|
|
|
|
# Beim Klick auf Scrollbar-Pfeil läuft der Rollbalken weg (Dauerscroll ...)
|
501
|
|
|
|
|
|
|
} # $i
|
502
|
|
|
|
|
|
|
} # $j
|
503
|
|
|
|
|
|
|
# print " end\n";
|
504
|
|
|
|
|
|
|
$do_scroll = 1;
|
505
|
|
|
|
|
|
|
} # scroll }}}
|
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
# Private Methods
|
508
|
|
|
|
|
|
|
# ===============
|
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
sub Populate { # {{{
|
511
|
|
|
|
|
|
|
my ($w, $args) = @_;
|
512
|
|
|
|
|
|
|
$w->SUPER::Populate($args);
|
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
$w->{posi} = 0;
|
515
|
|
|
|
|
|
|
$w->{state} = NORMAL;
|
516
|
|
|
|
|
|
|
$w->{pic_path} = $INC{"Tk/VisualBrowser.pm"};
|
517
|
|
|
|
|
|
|
$w->{pic_path} =~ s/VisualBrowser.pm//;
|
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
$w->ConfigSpecs(
|
520
|
|
|
|
|
|
|
-cols => [METHOD => undef, undef, 5],
|
521
|
|
|
|
|
|
|
-rows => [METHOD => undef, undef, 4],
|
522
|
|
|
|
|
|
|
-b1_handler => [CALLBACK => undef, undef, undef],
|
523
|
|
|
|
|
|
|
-b2_handler => [CALLBACK => undef, undef, undef],
|
524
|
|
|
|
|
|
|
-b3_handler => [CALLBACK => undef, undef, undef],
|
525
|
|
|
|
|
|
|
-double_b1_handler => [CALLBACK => undef, undef, undef],
|
526
|
|
|
|
|
|
|
-double_b2_handler => [CALLBACK => undef, undef, undef],
|
527
|
|
|
|
|
|
|
-double_b3_handler => [CALLBACK => undef, undef, undef],
|
528
|
|
|
|
|
|
|
-pictures => [METHOD => undef, undef, []],
|
529
|
|
|
|
|
|
|
-thumbnail => [CALLBACK => undef, undef, sub{ return "nix is" }],
|
530
|
|
|
|
|
|
|
-special_color => [CALLBACK => undef, undef, sub{ return 0 }],
|
531
|
|
|
|
|
|
|
-highlight => [PASSIVE => undef, undef, "#3F8856"],
|
532
|
|
|
|
|
|
|
-active_color => [PASSIVE => undef, undef, "#2222CC"],
|
533
|
|
|
|
|
|
|
-bg_color => [PASSIVE => undef, undef, "#CCCCCC"],
|
534
|
|
|
|
|
|
|
-bg_color1 => [PASSIVE => undef, undef, "#BBBBBB"],
|
535
|
|
|
|
|
|
|
-cursor_fg => [PASSIVE => undef, undef, "white"],
|
536
|
|
|
|
|
|
|
-cursor_bg => [PASSIVE => undef, undef, "brown"],
|
537
|
|
|
|
|
|
|
-use_labels => [PASSIVE => undef, undef, 0],
|
538
|
|
|
|
|
|
|
-use_balloons => [PASSIVE => undef, undef, 0],
|
539
|
|
|
|
|
|
|
-balloon_texts => [METHOD => undef, undef, []],
|
540
|
|
|
|
|
|
|
-label_texts => [METHOD => undef, undef, []],
|
541
|
|
|
|
|
|
|
);
|
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
} # Populate }}}
|
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
sub rebuild { # {{{
|
546
|
|
|
|
|
|
|
my ($w, $rows_old, $cols_old) = @_;
|
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
my $cols = $w->cget("-cols");
|
549
|
|
|
|
|
|
|
my $rows = $w->cget("-rows");
|
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
# print "---- rebuild $rows, $cols\n";
|
552
|
|
|
|
|
|
|
return unless defined $rows_old;
|
553
|
|
|
|
|
|
|
return unless defined $cols_old;
|
554
|
|
|
|
|
|
|
return unless defined $rows;
|
555
|
|
|
|
|
|
|
return unless defined $cols;
|
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
# is it really necessary?
|
559
|
|
|
|
|
|
|
if ($cols_old == $cols and $rows_old == $rows) {
|
560
|
|
|
|
|
|
|
return ;
|
561
|
|
|
|
|
|
|
}
|
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
# remove all buttons and labels
|
564
|
|
|
|
|
|
|
$w->{ysb}->destroy if defined $w->{ysb};
|
565
|
|
|
|
|
|
|
# scrollbar must be destroyed before all other objects
|
566
|
|
|
|
|
|
|
# because its enclosing frame $frm_pan is handled in the following list
|
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
foreach my $obj ( @{ $w->{OBJECTS} } ){
|
569
|
|
|
|
|
|
|
$obj->destroy;
|
570
|
|
|
|
|
|
|
}
|
571
|
|
|
|
|
|
|
undef $w->{OBJECTS};
|
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
# free Photo Objects
|
574
|
|
|
|
|
|
|
for (my $i = 0; $i < $rows_old; $i++){
|
575
|
|
|
|
|
|
|
for (my $j = 0; $j < $cols_old; $j++){
|
576
|
|
|
|
|
|
|
undef $w->{Photo}[$i][$j];
|
577
|
|
|
|
|
|
|
}
|
578
|
|
|
|
|
|
|
}
|
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
# rebuild all:
|
581
|
|
|
|
|
|
|
my $pfeil_first = $w->Pixmap(-data => arrow_first_xpm);
|
582
|
|
|
|
|
|
|
my $pfeil_last = $w->Pixmap(-data => arrow_last_xpm);
|
583
|
|
|
|
|
|
|
my $pfeil_ll = $w->Pixmap(-data => arrow_ppage_xpm);
|
584
|
|
|
|
|
|
|
my $pfeil_nn = $w->Pixmap(-data => arrow_npage_xpm);
|
585
|
|
|
|
|
|
|
my $pfeil_l = $w->Pixmap(-data => arrow_prev_xpm);
|
586
|
|
|
|
|
|
|
my $pfeil_n = $w->Pixmap(-data => arrow_next_xpm);
|
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
my $frm_but = $w->Frame()->pack;
|
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
if ($w->cget('-use_balloons')) {
|
591
|
|
|
|
|
|
|
$w->{bln} = $w->Balloon;
|
592
|
|
|
|
|
|
|
}
|
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
my $mm = $rows * $cols;
|
595
|
|
|
|
|
|
|
my $b_fst = $frm_but->Button(#-text => "|<",
|
596
|
|
|
|
|
|
|
-image => $pfeil_first,
|
597
|
|
|
|
|
|
|
-command => sub { scroll($w, 0);
|
598
|
|
|
|
|
|
|
set_sb($w, 0, $mm);
|
599
|
|
|
|
|
|
|
}
|
600
|
|
|
|
|
|
|
)->pack(-side => "left");
|
601
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $b_fst;
|
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
my $b_pp = $frm_but->Button(#-text => "<<",
|
604
|
|
|
|
|
|
|
-image => $pfeil_ll,
|
605
|
|
|
|
|
|
|
-command => sub { scroll($w, "pp");
|
606
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
607
|
|
|
|
|
|
|
}
|
608
|
|
|
|
|
|
|
)->pack(-side => "left");
|
609
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $b_pp;
|
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
my $b_p = $frm_but->Button(#-text => "<",
|
612
|
|
|
|
|
|
|
-image => $pfeil_l,
|
613
|
|
|
|
|
|
|
-command => sub { scroll($w, "p");
|
614
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
615
|
|
|
|
|
|
|
}
|
616
|
|
|
|
|
|
|
)->pack(-side => "left");
|
617
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $b_p;
|
618
|
|
|
|
|
|
|
my $b_n = $frm_but->Button(#-text => ">",
|
619
|
|
|
|
|
|
|
-image => $pfeil_n,
|
620
|
|
|
|
|
|
|
-command => sub { scroll($w, "n");
|
621
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
622
|
|
|
|
|
|
|
}
|
623
|
|
|
|
|
|
|
)->pack(-side => "left");
|
624
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $b_n;
|
625
|
|
|
|
|
|
|
my $b_nn = $frm_but->Button(#-text => ">>",
|
626
|
|
|
|
|
|
|
-image => $pfeil_nn,
|
627
|
|
|
|
|
|
|
-command => sub { scroll($w, "nn");
|
628
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
629
|
|
|
|
|
|
|
}
|
630
|
|
|
|
|
|
|
)->pack(-side => "left");
|
631
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $b_nn;
|
632
|
|
|
|
|
|
|
my $b_lst = $frm_but->Button(#-text => ">|",
|
633
|
|
|
|
|
|
|
-image => $pfeil_last,
|
634
|
|
|
|
|
|
|
-command => sub { scroll($w, "l");
|
635
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
636
|
|
|
|
|
|
|
my $max = $#{$picref};
|
637
|
|
|
|
|
|
|
set_sb($w, $max-$mm, $mm);
|
638
|
|
|
|
|
|
|
}
|
639
|
|
|
|
|
|
|
)->pack(-side => "left");
|
640
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $b_lst;
|
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $frm_but;
|
643
|
|
|
|
|
|
|
# push frames after their widgets so that destroy is applied
|
644
|
|
|
|
|
|
|
# in reverse order ...
|
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
my $frm_pan = $w->Frame()->pack;
|
647
|
|
|
|
|
|
|
my $frm_pic = $frm_pan->Frame(-bg => $w->cget(-bg_color1) )->pack(-side => "left");
|
648
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
$w->{ysb} = $frm_pan->Scrollbar( -command => [yview=>$w], );
|
650
|
|
|
|
|
|
|
$w->{ysb} -> pack(-side => 'left', -fill => 'y');
|
651
|
|
|
|
|
|
|
my $use_labels = $w->cget('-use_labels');
|
652
|
|
|
|
|
|
|
my $row_fakt = $use_labels ? 2 : 1;
|
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
# print " === rows: $rows, cols: $cols\n";
|
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
for (my $i = 0; $i < $rows; $i++){
|
657
|
|
|
|
|
|
|
for (my $j = 0; $j < $cols; $j++){
|
658
|
|
|
|
|
|
|
# push @{ $w->{OBJECTS} },
|
659
|
|
|
|
|
|
|
$w->{Photo}->[$i][$j] = $w->Photo(-file => $w->{pic_path}."/vis-empty.gif");
|
660
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} },
|
661
|
|
|
|
|
|
|
$w->{Thmb} ->[$i][$j] = $frm_pic->Label(
|
662
|
|
|
|
|
|
|
-width => 80,
|
663
|
|
|
|
|
|
|
-height => 80,
|
664
|
|
|
|
|
|
|
-background => $w->cget("-bg_color"),
|
665
|
|
|
|
|
|
|
-image => $w->{Photo}[$i][$j],
|
666
|
|
|
|
|
|
|
) -> grid( -column => $j, -row => $i*$row_fakt,
|
667
|
|
|
|
|
|
|
-sticky => "w", -padx => 3, -pady => 3);
|
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
if ($use_labels ) {
|
670
|
|
|
|
|
|
|
$w->{Label}->[$i][$j] = "$i $j";
|
671
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} },
|
672
|
|
|
|
|
|
|
$w->{Lbl} ->[$i][$j] = $frm_pic->Label(
|
673
|
|
|
|
|
|
|
-width => 12,
|
674
|
|
|
|
|
|
|
-anchor => "center",
|
675
|
|
|
|
|
|
|
-background => $w->cget("-bg_color"),
|
676
|
|
|
|
|
|
|
-textvariable => \$w->{Label}[$i][$j],
|
677
|
|
|
|
|
|
|
) -> grid( -column => $j, -row => $i*2 + 1,
|
678
|
|
|
|
|
|
|
-sticky => "w", -padx => 3, -pady => 3);
|
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
}
|
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
my $kx = $i*($cols) + $j;
|
684
|
|
|
|
|
|
|
my ($ii, $jj) = ($i, $j);
|
685
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", sub{b1($w, $kx, 1)});
|
686
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", sub{b1($w, $kx, 2)});
|
687
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", sub{dbl_b1($w, $kx)});
|
688
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", sub{dbl_b2($w, $kx)});
|
689
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", sub{dbl_b3($w, $kx)});
|
690
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", sub{b1($w, $kx)});
|
691
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", sub{b2($w, $kx)});
|
692
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", sub{b3($w, $kx)});
|
693
|
|
|
|
|
|
|
|
694
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", [\&b1_release, $w, $ii, $jj]);
|
695
|
|
|
|
|
|
|
# first parameter for b1_release is the widget handle of the thumbnail:
|
696
|
|
|
|
|
|
|
# $w->{Thmb}[$i][$j]
|
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] ->bind("", [\&b1_motion, $w, $ii, $jj]);
|
699
|
|
|
|
|
|
|
}
|
700
|
|
|
|
|
|
|
}
|
701
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $frm_pic;
|
702
|
|
|
|
|
|
|
push @{ $w->{OBJECTS} }, $frm_pan;
|
703
|
|
|
|
|
|
|
scroll($w, 0); # loads the pictures
|
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
} # rebuild }}}
|
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
sub _move_selected { # {{{
|
708
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
709
|
|
|
|
|
|
|
# print "move to pos $pos ...\n";
|
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
# first of all: remove selected pics from array and save to a new array
|
712
|
|
|
|
|
|
|
# calculate the insert position during this action.
|
713
|
|
|
|
|
|
|
# Then insert new list at insert position.
|
714
|
|
|
|
|
|
|
#
|
715
|
|
|
|
|
|
|
my @MOVE_PICS;
|
716
|
|
|
|
|
|
|
my $pos_back = $pos;
|
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
# handle label texts {{{
|
719
|
|
|
|
|
|
|
@MOVE_PICS = ();
|
720
|
|
|
|
|
|
|
$pos = $pos_back;
|
721
|
|
|
|
|
|
|
my $lref = $w->cget('-label_texts');
|
722
|
|
|
|
|
|
|
if ($lref and ref($lref) eq 'ARRAY' and @$lref) {
|
723
|
|
|
|
|
|
|
for (my $i = @{$w->{SEL}} -1; $i>=0; $i--){
|
724
|
|
|
|
|
|
|
if ($w->{SEL}[$i]) {
|
725
|
|
|
|
|
|
|
push @MOVE_PICS, splice( @{ $w->cget('-label_texts') }, $i, 1) ;
|
726
|
|
|
|
|
|
|
$pos -- if $pos ne "end" and $pos > $i;
|
727
|
|
|
|
|
|
|
}
|
728
|
|
|
|
|
|
|
}
|
729
|
|
|
|
|
|
|
if ($pos eq "end"){
|
730
|
|
|
|
|
|
|
push @{ $w->cget('-label_texts') }, reverse @MOVE_PICS;
|
731
|
|
|
|
|
|
|
} else {
|
732
|
|
|
|
|
|
|
splice @{ $w->cget('-label_texts') }, $pos, 0, reverse @MOVE_PICS;
|
733
|
|
|
|
|
|
|
}
|
734
|
|
|
|
|
|
|
} # }}}
|
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
# handle balloon texts {{{
|
737
|
|
|
|
|
|
|
@MOVE_PICS = ();
|
738
|
|
|
|
|
|
|
$pos = $pos_back;
|
739
|
|
|
|
|
|
|
my $bref = $w->cget('-balloon_texts');
|
740
|
|
|
|
|
|
|
if ($bref and ref($bref) eq 'ARRAY' and @$bref and $bref != $lref) {
|
741
|
|
|
|
|
|
|
for (my $i = @{$w->{SEL}} -1; $i>=0; $i--){
|
742
|
|
|
|
|
|
|
if ($w->{SEL}[$i]) {
|
743
|
|
|
|
|
|
|
push @MOVE_PICS, splice( @{ $w->cget('-balloon_texts') }, $i, 1) ;
|
744
|
|
|
|
|
|
|
$pos -- if $pos ne "end" and $pos > $i;
|
745
|
|
|
|
|
|
|
}
|
746
|
|
|
|
|
|
|
}
|
747
|
|
|
|
|
|
|
if ($pos eq "end"){
|
748
|
|
|
|
|
|
|
push @{ $w->cget('-balloon_texts') }, reverse @MOVE_PICS;
|
749
|
|
|
|
|
|
|
} else {
|
750
|
|
|
|
|
|
|
splice @{ $w->cget('-balloon_texts') }, $pos, 0, reverse @MOVE_PICS;
|
751
|
|
|
|
|
|
|
}
|
752
|
|
|
|
|
|
|
} # }}}
|
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
# the same procedure has to be done for the pictures
|
755
|
|
|
|
|
|
|
@MOVE_PICS = ();
|
756
|
|
|
|
|
|
|
$pos = $pos_back;
|
757
|
|
|
|
|
|
|
for (my $i = @{$w->{SEL}} -1; $i>=0; $i--){
|
758
|
|
|
|
|
|
|
if ($w->{SEL}[$i]) {
|
759
|
|
|
|
|
|
|
push @MOVE_PICS, splice( @{ $w->cget('-pictures') }, $i, 1) ;
|
760
|
|
|
|
|
|
|
$pos -- if $pos ne "end" and $pos > $i;
|
761
|
|
|
|
|
|
|
}
|
762
|
|
|
|
|
|
|
}
|
763
|
|
|
|
|
|
|
if ($pos eq "end"){
|
764
|
|
|
|
|
|
|
push @{ $w->cget('-pictures') }, reverse @MOVE_PICS;
|
765
|
|
|
|
|
|
|
scroll($w, $w->{posi});
|
766
|
|
|
|
|
|
|
} else {
|
767
|
|
|
|
|
|
|
splice @{ $w->cget('-pictures') }, $pos, 0, reverse @MOVE_PICS;
|
768
|
|
|
|
|
|
|
scroll($w, $w->{posi});
|
769
|
|
|
|
|
|
|
}
|
770
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
deselect_all($w);
|
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
}# _move_selected }}}
|
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
# scrollbar handling
|
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
sub yview { # {{{
|
778
|
|
|
|
|
|
|
# print "yview call: @_\n";
|
779
|
|
|
|
|
|
|
my $w = shift;
|
780
|
|
|
|
|
|
|
my $dir = shift;
|
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
my ($r,$c) = ($w->cget('-rows'), $w->cget('-cols'));
|
784
|
|
|
|
|
|
|
my $mm = $r * $c;
|
785
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
786
|
|
|
|
|
|
|
my $mmax = scalar(@{$picref});
|
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
my $n;
|
789
|
|
|
|
|
|
|
my $unit;
|
790
|
|
|
|
|
|
|
if ($dir eq "moveto") {
|
791
|
|
|
|
|
|
|
$n = shift;
|
792
|
|
|
|
|
|
|
# print " moveto --> $n\n";
|
793
|
|
|
|
|
|
|
my $pos = int($n*$mmax);
|
794
|
|
|
|
|
|
|
$pos = 0 if $pos < 0;
|
795
|
|
|
|
|
|
|
$pos = $mmax if $pos > $mmax;
|
796
|
|
|
|
|
|
|
scroll($w, $pos);
|
797
|
|
|
|
|
|
|
set_sb($w, $pos, $mm);
|
798
|
|
|
|
|
|
|
} elsif ($dir eq "scroll") {
|
799
|
|
|
|
|
|
|
$n = shift;
|
800
|
|
|
|
|
|
|
$unit = shift;
|
801
|
|
|
|
|
|
|
# print " scroll --> $n $unit\n";
|
802
|
|
|
|
|
|
|
if ($n == 1){
|
803
|
|
|
|
|
|
|
if ($unit eq "pages"){
|
804
|
|
|
|
|
|
|
scroll($w, "nn");
|
805
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
806
|
|
|
|
|
|
|
} else {
|
807
|
|
|
|
|
|
|
scroll($w, "n");
|
808
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
809
|
|
|
|
|
|
|
}
|
810
|
|
|
|
|
|
|
} else {
|
811
|
|
|
|
|
|
|
if ($unit eq "pages"){
|
812
|
|
|
|
|
|
|
scroll($w, "pp");
|
813
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
814
|
|
|
|
|
|
|
} else {
|
815
|
|
|
|
|
|
|
scroll($w, "p");
|
816
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
817
|
|
|
|
|
|
|
}
|
818
|
|
|
|
|
|
|
}
|
819
|
|
|
|
|
|
|
}
|
820
|
|
|
|
|
|
|
} # yview }}}
|
821
|
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
sub set_sb { # {{{
|
823
|
|
|
|
|
|
|
my $w = shift;
|
824
|
|
|
|
|
|
|
return unless defined $w->{ysb};
|
825
|
|
|
|
|
|
|
my $val = shift;
|
826
|
|
|
|
|
|
|
my $mm = shift;
|
827
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
828
|
|
|
|
|
|
|
my $mmax = scalar(@{$picref}) || 1;
|
829
|
|
|
|
|
|
|
$w->{ysb}->set( $val/$mmax, ($val + $mm)/$mmax);
|
830
|
|
|
|
|
|
|
} # set_sb }}}
|
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
# option handlers
|
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
sub pictures { # {{{
|
835
|
|
|
|
|
|
|
my ($w, $ref) = @_;
|
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
if ($#_ > 0){ # configure
|
838
|
|
|
|
|
|
|
@{$w->{SEL}} = map {0} @$ref;
|
839
|
|
|
|
|
|
|
$w->{pictures} = $ref;
|
840
|
|
|
|
|
|
|
set_sb($w, 0, $w->cget("-cols") * $w->cget("-rows"));
|
841
|
|
|
|
|
|
|
scroll($w, 0);
|
842
|
|
|
|
|
|
|
} else { # cget request
|
843
|
|
|
|
|
|
|
$w->{pictures}
|
844
|
|
|
|
|
|
|
}
|
845
|
|
|
|
|
|
|
} # pictures }}}
|
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
sub balloon_texts { # {{{
|
848
|
|
|
|
|
|
|
my ($w, $ref) = @_;
|
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
if ($#_ > 0){ # configure
|
851
|
|
|
|
|
|
|
$w->{balloon_texts} = $ref;
|
852
|
|
|
|
|
|
|
} else { # cget request
|
853
|
|
|
|
|
|
|
$w->{balloon_texts}
|
854
|
|
|
|
|
|
|
}
|
855
|
|
|
|
|
|
|
} # balloon_texts }}}
|
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
sub label_texts { # {{{
|
858
|
|
|
|
|
|
|
my ($w, $ref) = @_;
|
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
if ($#_ > 0){ # configure
|
861
|
|
|
|
|
|
|
$w->{label_texts} = $ref;
|
862
|
|
|
|
|
|
|
} else { # cget request
|
863
|
|
|
|
|
|
|
$w->{label_texts}
|
864
|
|
|
|
|
|
|
}
|
865
|
|
|
|
|
|
|
} # label_texts }}}
|
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
sub rows { # {{{
|
868
|
|
|
|
|
|
|
my ($w, $r) = @_;
|
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
if ($#_ > 0){ # configure
|
871
|
|
|
|
|
|
|
croak "number of rows must be greater 0\n" unless $r > 0;
|
872
|
|
|
|
|
|
|
my $c_old = $w->{cols};
|
873
|
|
|
|
|
|
|
my $r_old = $w->{rows};
|
874
|
|
|
|
|
|
|
$w->{rows} = $r;
|
875
|
|
|
|
|
|
|
rebuild($w, $r_old, $c_old);
|
876
|
|
|
|
|
|
|
set_sb($w, 0, $w->cget("-cols") * $w->cget("-rows")) if defined $w->{pictures};
|
877
|
|
|
|
|
|
|
} else { # cget request
|
878
|
|
|
|
|
|
|
$w->{rows}
|
879
|
|
|
|
|
|
|
}
|
880
|
|
|
|
|
|
|
} # rows }}}
|
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
sub cols { # {{{
|
883
|
|
|
|
|
|
|
my ($w, $c) = @_;
|
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
if ($#_ > 0){ # configure
|
886
|
|
|
|
|
|
|
croak "number of columns must be greater 0\n" unless $c > 0;
|
887
|
|
|
|
|
|
|
my $c_old = $w->{cols};
|
888
|
|
|
|
|
|
|
my $r_old = $w->{rows};
|
889
|
|
|
|
|
|
|
$w->{cols} = $c;
|
890
|
|
|
|
|
|
|
rebuild($w, $r_old, $c_old);
|
891
|
|
|
|
|
|
|
set_sb($w, 0, $w->cget("-cols") * $w->cget("-rows")) if defined $w->{pictures};
|
892
|
|
|
|
|
|
|
} else { # cget request
|
893
|
|
|
|
|
|
|
$w->{cols}
|
894
|
|
|
|
|
|
|
}
|
895
|
|
|
|
|
|
|
} # cols }}}
|
896
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
# mouse button handlers
|
898
|
|
|
|
|
|
|
|
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
# Button Events:
|
901
|
|
|
|
|
|
|
sub b1 { # {{{
|
902
|
|
|
|
|
|
|
my ($w, $pos, $sh) = @_;
|
903
|
|
|
|
|
|
|
# $w Object Handle
|
904
|
|
|
|
|
|
|
# $pos Position in Thumbs-Matrix: 0, 1, ..., cols*rows-1
|
905
|
|
|
|
|
|
|
# $sh Shift-Button pressed
|
906
|
|
|
|
|
|
|
#
|
907
|
|
|
|
|
|
|
# select/deselect current picture
|
908
|
|
|
|
|
|
|
my ($c, $r);
|
909
|
|
|
|
|
|
|
$r = int($pos/$w->cget("-cols")); # current row
|
910
|
|
|
|
|
|
|
$c = $pos%$w->cget("-cols"); # current column
|
911
|
|
|
|
|
|
|
# print " ---- b1: \n";
|
912
|
|
|
|
|
|
|
|
913
|
|
|
|
|
|
|
# print "shift-" if defined $sh;
|
914
|
|
|
|
|
|
|
# print "b1 pos: $pos $c, $r\n";
|
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
my $idx = list_index($w, $pos); # click position in PICS array
|
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
my $sel = 0;
|
919
|
|
|
|
|
|
|
# Shift-Klick
|
920
|
|
|
|
|
|
|
# ===========
|
921
|
|
|
|
|
|
|
if (defined $sh and $sh == 1){ # select area
|
922
|
|
|
|
|
|
|
# ersten und letzten selection index ermitteln:
|
923
|
|
|
|
|
|
|
$w->{SEL}[$idx] = 1;
|
924
|
|
|
|
|
|
|
my ($i1, $i2) = (9999999, -1);
|
925
|
|
|
|
|
|
|
for ( my $z = 0; $z <= $#{$w->{pictures}}; $z++ ){
|
926
|
|
|
|
|
|
|
if ( $w->{SEL}[$z]){
|
927
|
|
|
|
|
|
|
$i1 = $z; last;
|
928
|
|
|
|
|
|
|
}
|
929
|
|
|
|
|
|
|
}
|
930
|
|
|
|
|
|
|
for ( my $z = $#{$w->{pictures}}; $z >=0; $z-- ){
|
931
|
|
|
|
|
|
|
if ( $w->{SEL}[$z]){
|
932
|
|
|
|
|
|
|
$i2 = $z; last;
|
933
|
|
|
|
|
|
|
}
|
934
|
|
|
|
|
|
|
}
|
935
|
|
|
|
|
|
|
# print "**1 $i1 bis $i2\n";
|
936
|
|
|
|
|
|
|
if ($idx < $i1) {
|
937
|
|
|
|
|
|
|
$i1 = $idx;
|
938
|
|
|
|
|
|
|
}
|
939
|
|
|
|
|
|
|
if ($idx > $i1) {
|
940
|
|
|
|
|
|
|
$i2 = $idx;
|
941
|
|
|
|
|
|
|
}
|
942
|
|
|
|
|
|
|
# print "**2 $i1 bis $i2\n";
|
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
# erst mal alle deselektieren
|
945
|
|
|
|
|
|
|
for ( my $z = 0; $z <= $#{$w->{pictures}}; $z++ ){
|
946
|
|
|
|
|
|
|
$w->{SEL}[$z] = 0;
|
947
|
|
|
|
|
|
|
_select_pic($w, $z, 0);
|
948
|
|
|
|
|
|
|
}
|
949
|
|
|
|
|
|
|
# dann den Bereich selektieren
|
950
|
|
|
|
|
|
|
for ( my $z = $i1; $z <= $i2; $z++ ){
|
951
|
|
|
|
|
|
|
$w->{SEL}[$z] = 1;
|
952
|
|
|
|
|
|
|
_select_pic($w, $z, 1);
|
953
|
|
|
|
|
|
|
}
|
954
|
|
|
|
|
|
|
|
955
|
|
|
|
|
|
|
# Ctrl-Klick
|
956
|
|
|
|
|
|
|
# ==========
|
957
|
|
|
|
|
|
|
} elsif (defined $sh and $sh == 2){ # ctrl B1, add/remove
|
958
|
|
|
|
|
|
|
# print "##### ctrl \n";
|
959
|
|
|
|
|
|
|
$w->{SEL}[$idx] = 1 - $w->{SEL}[$idx] if $idx > -1;
|
960
|
|
|
|
|
|
|
my $relief = _is_selected($w, $pos) ? "groove" : "flat";
|
961
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
962
|
|
|
|
|
|
|
my $special_color = $w->Callback(-special_color => $$picref[$idx]) || $w->cget("-bg_color");;
|
963
|
|
|
|
|
|
|
my $color = _is_selected($w, $pos) ? $w->cget("-active_color") : $special_color;
|
964
|
|
|
|
|
|
|
$w->{Thmb}[$r][$c] ->configure(
|
965
|
|
|
|
|
|
|
-relief =>$relief,
|
966
|
|
|
|
|
|
|
-background => $color,
|
967
|
|
|
|
|
|
|
);
|
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
# Button-1
|
970
|
|
|
|
|
|
|
# ========
|
971
|
|
|
|
|
|
|
} else { # single select
|
972
|
|
|
|
|
|
|
# wenn man in ein nicht selektierte Bils kilckt:
|
973
|
|
|
|
|
|
|
# neues Bild wird als einziges selektiert
|
974
|
|
|
|
|
|
|
if (! $w->{SEL}[$idx]) {
|
975
|
|
|
|
|
|
|
for ( my $z = 0; $z <= $#{$w->{pictures}}; $z++ ){
|
976
|
|
|
|
|
|
|
$w->{SEL}[$z] = 0;
|
977
|
|
|
|
|
|
|
_select_pic($w, $z, 0);
|
978
|
|
|
|
|
|
|
}
|
979
|
|
|
|
|
|
|
_select_pic($w, $idx, 1);
|
980
|
|
|
|
|
|
|
$w->{SEL}[$idx] = 1;
|
981
|
|
|
|
|
|
|
} else {
|
982
|
|
|
|
|
|
|
# andernfalls: klick auf selektiertes Bild:
|
983
|
|
|
|
|
|
|
# gehe in den MOVE-Zustand: Aktuelle Auswahl wird via
|
984
|
|
|
|
|
|
|
# B1-Motion bewegt:
|
985
|
|
|
|
|
|
|
$state = MOVE;
|
986
|
|
|
|
|
|
|
# Cursor ändern:
|
987
|
|
|
|
|
|
|
$save_cursor = $w->MainWindow->cget('-cursor');
|
988
|
|
|
|
|
|
|
$cursor = 'mouse';
|
989
|
|
|
|
|
|
|
if ($^O !~ /Win/i){
|
990
|
|
|
|
|
|
|
if (scalar get_selected($w) == 1){
|
991
|
|
|
|
|
|
|
$cursor = ['@'. $w->{pic_path} ."/move1.xbm" ,
|
992
|
|
|
|
|
|
|
$w->{pic_path} ."move1_mask.xbm", $w->cget(-cursor_bg), $w->cget(-cursor_fg)];
|
993
|
|
|
|
|
|
|
} else {
|
994
|
|
|
|
|
|
|
$cursor = ['@'. $w->{pic_path} ."/move.xbm" ,
|
995
|
|
|
|
|
|
|
$w->{pic_path} ."move_mask.xbm", $w->cget(-cursor_bg), $w->cget(-cursor_fg)];
|
996
|
|
|
|
|
|
|
}
|
997
|
|
|
|
|
|
|
}
|
998
|
|
|
|
|
|
|
$w->MainWindow->configure(-cursor => $cursor);
|
999
|
|
|
|
|
|
|
}
|
1000
|
|
|
|
|
|
|
}
|
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
# Call user's b1 handler if applicable:
|
1003
|
|
|
|
|
|
|
my $jpg = ${$w->{pictures}}[$idx];
|
1004
|
|
|
|
|
|
|
$w->Callback( -b1_handler => $jpg);
|
1005
|
|
|
|
|
|
|
} # b1 }}}
|
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
sub b1_motion { # {{{
|
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
my ($thb, $w, $ii, $jj) = @_;
|
1010
|
|
|
|
|
|
|
return unless $state == MOVE; # only then ...
|
1011
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
my $rows = $w->cget('-rows');
|
1013
|
|
|
|
|
|
|
my $cols = $w->cget('-cols');
|
1014
|
|
|
|
|
|
|
my $e = $thb->XEvent; # coordinates relativ to Thmb Label !!
|
1015
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
|
1017
|
|
|
|
|
|
|
THMB:
|
1018
|
|
|
|
|
|
|
for (my $i = 0; $i < $rows; $i++){
|
1019
|
|
|
|
|
|
|
for (my $j = 0; $j < $cols; $j++){
|
1020
|
|
|
|
|
|
|
my $idx = $w->{posi} + $i * $cols + $j;
|
1021
|
|
|
|
|
|
|
my $upper_left_x = $w->{Thmb}[$i][$j]->x;
|
1022
|
|
|
|
|
|
|
my $upper_left_y = $w->{Thmb}[$i][$j]->y;
|
1023
|
|
|
|
|
|
|
my $width = $w->{Thmb}[$i][$j]->width;
|
1024
|
|
|
|
|
|
|
my $height = $w->{Thmb}[$i][$j]->height;
|
1025
|
|
|
|
|
|
|
if (_enclosed($upper_left_x, $upper_left_y,
|
1026
|
|
|
|
|
|
|
$width, $height,
|
1027
|
|
|
|
|
|
|
$e->x + $jj * $width, # auf linkes oberes Label beziehen ...
|
1028
|
|
|
|
|
|
|
$e->y + $ii * $height)) # daher Korrektursummanden ...
|
1029
|
|
|
|
|
|
|
{
|
1030
|
|
|
|
|
|
|
# highlight background
|
1031
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] -> configure(
|
1032
|
|
|
|
|
|
|
-background =>$w->cget("-highlight"),
|
1033
|
|
|
|
|
|
|
-relief => "sunken",
|
1034
|
|
|
|
|
|
|
);
|
1035
|
|
|
|
|
|
|
} elsif ($w->{SEL}[$idx] ) {
|
1036
|
|
|
|
|
|
|
# selection background for thumbs which are selected
|
1037
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] -> configure(
|
1038
|
|
|
|
|
|
|
-background => $w->cget("-active_color"),
|
1039
|
|
|
|
|
|
|
-relief => "groove",
|
1040
|
|
|
|
|
|
|
);
|
1041
|
|
|
|
|
|
|
} else {
|
1042
|
|
|
|
|
|
|
# normal background for thumbs which are not selected
|
1043
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
1044
|
|
|
|
|
|
|
my $special_color = $w->Callback(-special_color => $$picref[$idx]) || $w->cget("-bg_color");;
|
1045
|
|
|
|
|
|
|
$w->{Thmb}[$i][$j] -> configure(
|
1046
|
|
|
|
|
|
|
-background => $special_color,
|
1047
|
|
|
|
|
|
|
-relief => "flat",
|
1048
|
|
|
|
|
|
|
);
|
1049
|
|
|
|
|
|
|
}
|
1050
|
|
|
|
|
|
|
}
|
1051
|
|
|
|
|
|
|
}
|
1052
|
|
|
|
|
|
|
|
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
# scroll when we approche the lower margin
|
1055
|
|
|
|
|
|
|
#
|
1056
|
|
|
|
|
|
|
my $mm = $rows * $cols;
|
1057
|
|
|
|
|
|
|
my $height =$thb->height;
|
1058
|
|
|
|
|
|
|
my $y_pos = $e->y + $ii*$height;
|
1059
|
|
|
|
|
|
|
if ( $y_pos < $height/2 ){
|
1060
|
|
|
|
|
|
|
# print " <<<<<<\n";
|
1061
|
|
|
|
|
|
|
if ($w->{up}) {
|
1062
|
|
|
|
|
|
|
$w->scroll("p");
|
1063
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
1064
|
|
|
|
|
|
|
$w->{up} = 0;
|
1065
|
|
|
|
|
|
|
}
|
1066
|
|
|
|
|
|
|
} elsif ($y_pos > $height*0.55) { # Hysterese
|
1067
|
|
|
|
|
|
|
$w->{up} = 1;
|
1068
|
|
|
|
|
|
|
}
|
1069
|
|
|
|
|
|
|
if ( $y_pos > $rows * $height - $height/2 ){
|
1070
|
|
|
|
|
|
|
# print " >>>>>>\n";
|
1071
|
|
|
|
|
|
|
if ($w->{down}) {
|
1072
|
|
|
|
|
|
|
$w->scroll("n");
|
1073
|
|
|
|
|
|
|
set_sb($w, $w->{posi}, $mm);
|
1074
|
|
|
|
|
|
|
$w->{down} = 0;
|
1075
|
|
|
|
|
|
|
}
|
1076
|
|
|
|
|
|
|
} elsif ( $y_pos < $rows*$height - 0.55*$height) { # Hysterese
|
1077
|
|
|
|
|
|
|
$w->{down} = 1;
|
1078
|
|
|
|
|
|
|
}
|
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
# update cursor image
|
1081
|
|
|
|
|
|
|
$w->MainWindow->configure(-cursor => $cursor);
|
1082
|
|
|
|
|
|
|
} # b1_motion }}}
|
1083
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
sub b1_release { # {{{
|
1085
|
|
|
|
|
|
|
my ($thb, $w, $ii, $jj) = @_;
|
1086
|
|
|
|
|
|
|
if ($state == MOVE) {
|
1087
|
|
|
|
|
|
|
# Versuche herauszubekommen, über welchem Label sich der
|
1088
|
|
|
|
|
|
|
# Cursor gerade befindet:
|
1089
|
|
|
|
|
|
|
my $e = $thb->XEvent; # Koordinaten relativ zum Thumb Label !!
|
1090
|
|
|
|
|
|
|
# print "x: ", $e->x, " y: ", $e->y, "\n";
|
1091
|
|
|
|
|
|
|
# ok, soweit so gut. Jetzt muss man die Koordiaten mit den umfassenden
|
1092
|
|
|
|
|
|
|
# Rechtecken aller Thmb Labels vergleichen und daraus die Release-Position
|
1093
|
|
|
|
|
|
|
# eritteln:
|
1094
|
|
|
|
|
|
|
my $rows = $w->cget('-rows');
|
1095
|
|
|
|
|
|
|
my $cols = $w->cget('-cols');
|
1096
|
|
|
|
|
|
|
THMB:
|
1097
|
|
|
|
|
|
|
for (my $i = 0; $i < $rows; $i++){
|
1098
|
|
|
|
|
|
|
for (my $j = 0; $j < $cols; $j++){
|
1099
|
|
|
|
|
|
|
my $upper_left_x = $w->{Thmb}[$i][$j]->x;
|
1100
|
|
|
|
|
|
|
my $upper_left_y = $w->{Thmb}[$i][$j]->y;
|
1101
|
|
|
|
|
|
|
my $width = $w->{Thmb}[$i][$j]->width;
|
1102
|
|
|
|
|
|
|
my $height = $w->{Thmb}[$i][$j]->height;
|
1103
|
|
|
|
|
|
|
# print " ux $upper_left_x, uy $upper_left_y\n";
|
1104
|
|
|
|
|
|
|
my $kx = $cols * $i + $j;
|
1105
|
|
|
|
|
|
|
if (_enclosed($upper_left_x, $upper_left_y,
|
1106
|
|
|
|
|
|
|
$width, $height,
|
1107
|
|
|
|
|
|
|
$e->x + $jj * $width, # auf linkes oberes Label beziehen ...
|
1108
|
|
|
|
|
|
|
$e->y + $ii * $height)) # daher Korrektursummanden ...
|
1109
|
|
|
|
|
|
|
{
|
1110
|
|
|
|
|
|
|
# print " #### $kx\n" ;
|
1111
|
|
|
|
|
|
|
my $idx = list_index($w, $kx); # click position in PICS array
|
1112
|
|
|
|
|
|
|
_move_selected($w, $idx);
|
1113
|
|
|
|
|
|
|
last THMB;
|
1114
|
|
|
|
|
|
|
}
|
1115
|
|
|
|
|
|
|
}
|
1116
|
|
|
|
|
|
|
}
|
1117
|
|
|
|
|
|
|
}
|
1118
|
|
|
|
|
|
|
$state = NORMAL;
|
1119
|
|
|
|
|
|
|
$w->MainWindow->configure(-cursor => $save_cursor);
|
1120
|
|
|
|
|
|
|
} # b1_release }}}
|
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
sub _enclosed { # {{{
|
1123
|
|
|
|
|
|
|
# check, if ($x, $y) is within the rectangle
|
1124
|
|
|
|
|
|
|
my ($ulx, $uly, $width, $height, $x, $y) = @_;
|
1125
|
|
|
|
|
|
|
return 1 if
|
1126
|
|
|
|
|
|
|
$ulx <= $x and $x <= $ulx + $width and
|
1127
|
|
|
|
|
|
|
$uly <= $y and $y <= $uly + $height;
|
1128
|
|
|
|
|
|
|
return 0;
|
1129
|
|
|
|
|
|
|
} # _enclosed }}}
|
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
sub b2 { # {{{
|
1132
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1133
|
|
|
|
|
|
|
my $idx = list_index($w, $pos); # click position in PICS array
|
1134
|
|
|
|
|
|
|
# Call user's b1 handler if applicable:
|
1135
|
|
|
|
|
|
|
my $jpg = ${$w->{pictures}}[$idx];
|
1136
|
|
|
|
|
|
|
# print " ---- b2: $jpg\n";
|
1137
|
|
|
|
|
|
|
$w->Callback( -b2_handler => $jpg);
|
1138
|
|
|
|
|
|
|
} # b2 }}}
|
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
sub b3 { # {{{
|
1141
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1142
|
|
|
|
|
|
|
my $idx = list_index($w, $pos); # click position in PICS array
|
1143
|
|
|
|
|
|
|
# Call user's b1 handler if applicable:
|
1144
|
|
|
|
|
|
|
my $jpg = ${$w->{pictures}}[$idx];
|
1145
|
|
|
|
|
|
|
# print " ---- b3: $jpg\n";
|
1146
|
|
|
|
|
|
|
$w->Callback( -b3_handler => $jpg);
|
1147
|
|
|
|
|
|
|
} # b3 }}}
|
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
sub dbl_b1 { # {{{
|
1150
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1151
|
|
|
|
|
|
|
my $idx = list_index($w, $pos); # click position in PICS array
|
1152
|
|
|
|
|
|
|
my $jpg = ${$w->cget("-pictures")}[$idx];
|
1153
|
|
|
|
|
|
|
# print " ---- dbl_b1: $jpg\n";
|
1154
|
|
|
|
|
|
|
|
1155
|
|
|
|
|
|
|
# select only current picture:
|
1156
|
|
|
|
|
|
|
_select_only($w, $pos);
|
1157
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
# Call user's double-b1 handler if applicable:
|
1159
|
|
|
|
|
|
|
# $jpg = ${$w->{pictures}}[$idx];
|
1160
|
|
|
|
|
|
|
$w->Callback( -double_b1_handler => $jpg);
|
1161
|
|
|
|
|
|
|
} # dbl_b1 }}}
|
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
sub dbl_b2 { # {{{
|
1164
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1165
|
|
|
|
|
|
|
my $idx = list_index($w, $pos); # click position in PICS array
|
1166
|
|
|
|
|
|
|
my $jpg = ${$w->{pictures}}[$idx];
|
1167
|
|
|
|
|
|
|
# print " ---- dbl_b2: $jpg\n";
|
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
# select only current picture:
|
1170
|
|
|
|
|
|
|
_select_only($w, $pos);
|
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
# Call user's double-b2 handler if applicable:
|
1173
|
|
|
|
|
|
|
$w->Callback( -double_b2_handler => $jpg);
|
1174
|
|
|
|
|
|
|
} # dbl_b2 }}}
|
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
sub dbl_b3 { # {{{
|
1177
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1178
|
|
|
|
|
|
|
my $idx = list_index($w, $pos); # click position in PICS array
|
1179
|
|
|
|
|
|
|
my $jpg = ${$w->{pictures}}[$idx];
|
1180
|
|
|
|
|
|
|
# print " ---- dbl_b3: $jpg\n";
|
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
# select only current picture:
|
1183
|
|
|
|
|
|
|
_select_only($w, $pos);
|
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
# Call user's double-b3 handler if applicable:
|
1186
|
|
|
|
|
|
|
$w->Callback( -double_b3_handler => $jpg);
|
1187
|
|
|
|
|
|
|
} # dbl_b3 }}}
|
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
# auxiliary functions
|
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
sub _is_selected { # {{{
|
1192
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1193
|
|
|
|
|
|
|
my $idx = list_index($w, $pos);
|
1194
|
|
|
|
|
|
|
return 0 if $idx < 0;
|
1195
|
|
|
|
|
|
|
return $w->{SEL}[$idx];
|
1196
|
|
|
|
|
|
|
} # _is_selected }}}
|
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
sub _select_pic { # {{{
|
1199
|
|
|
|
|
|
|
my ($w, $z, $sel) = @_;
|
1200
|
|
|
|
|
|
|
# $z position in PICs array
|
1201
|
|
|
|
|
|
|
# $sel select/deselect
|
1202
|
|
|
|
|
|
|
return if $z < $w->{posi}
|
1203
|
|
|
|
|
|
|
or $z > $w->{posi}+$w->cget("-rows")*$w->cget("-cols")-1;
|
1204
|
|
|
|
|
|
|
|
1205
|
|
|
|
|
|
|
my $pos = $z - $w->{posi}; # position in thumbs matrix
|
1206
|
|
|
|
|
|
|
my ($c, $r);
|
1207
|
|
|
|
|
|
|
$r = int($pos/$w->cget("-cols")); # current row
|
1208
|
|
|
|
|
|
|
$c = $pos%$w->cget("-cols"); # current column
|
1209
|
|
|
|
|
|
|
# print "_select_pic: $r, $c z: $z pos: $pos\n";
|
1210
|
|
|
|
|
|
|
my $relief = $sel ? "groove" : "flat";
|
1211
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
1212
|
|
|
|
|
|
|
my $special_color = $w->Callback(-special_color => $$picref[$z]) || $w->cget("-bg_color");;
|
1213
|
|
|
|
|
|
|
my $color = $sel ? $w->cget("-active_color") : $special_color;
|
1214
|
|
|
|
|
|
|
return unless defined $w->{Thmb}[$r][$c];
|
1215
|
|
|
|
|
|
|
$w->{Thmb}[$r][$c] ->configure(
|
1216
|
|
|
|
|
|
|
-relief => $relief,
|
1217
|
|
|
|
|
|
|
-background => $color,
|
1218
|
|
|
|
|
|
|
);
|
1219
|
|
|
|
|
|
|
} # _select_pic }}}
|
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
sub _select_only { # {{{
|
1222
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1223
|
|
|
|
|
|
|
# select only current picture:
|
1224
|
|
|
|
|
|
|
for ( my $z = 0; $z <= $#{$w->{pictures}}; $z++ ){
|
1225
|
|
|
|
|
|
|
$w->{SEL}[$z] = 0;
|
1226
|
|
|
|
|
|
|
_select_pic($w, $z, 0);
|
1227
|
|
|
|
|
|
|
}
|
1228
|
|
|
|
|
|
|
_select_pic($w, $pos, 1);
|
1229
|
|
|
|
|
|
|
$w->{SEL}[$pos] = 1;
|
1230
|
|
|
|
|
|
|
} # _select_only }}}
|
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
sub trim_pos{ # {{{
|
1233
|
|
|
|
|
|
|
# calculate position in PICS array, check boundaries
|
1234
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1235
|
|
|
|
|
|
|
return 0 if $pos < 0;
|
1236
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
1237
|
|
|
|
|
|
|
my $max = scalar(@{$picref});
|
1238
|
|
|
|
|
|
|
return $max if $pos > $max;
|
1239
|
|
|
|
|
|
|
return $pos;
|
1240
|
|
|
|
|
|
|
} # trim_pos }}}
|
1241
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
sub list_index { # {{{
|
1243
|
|
|
|
|
|
|
# Position of current pic in list PICS
|
1244
|
|
|
|
|
|
|
my ($w, $pos) = @_;
|
1245
|
|
|
|
|
|
|
my $idx = $w->{posi}+$pos;
|
1246
|
|
|
|
|
|
|
my $picref = $w->cget('-pictures');
|
1247
|
|
|
|
|
|
|
my $max = scalar(@{$picref});
|
1248
|
|
|
|
|
|
|
return -1 if $idx > $max;
|
1249
|
|
|
|
|
|
|
return $idx;
|
1250
|
|
|
|
|
|
|
} # list_index }}}
|
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
1;
|
1253
|
|
|
|
|
|
|
|
1254
|
|
|
|
|
|
|
__END__
|