1package Prima::Image::TransparencyControl;
2
3use strict;
4use warnings;
5use Prima;
6use Prima::ImageViewer;
7use Prima::Label;
8use Prima::Sliders;
9
10use vars qw(@ISA);
11@ISA = qw(Prima::Widget);
12
13sub profile_default
14{
15	my $def = $_[ 0]-> SUPER::profile_default;
16	my %prf = (
17		index  => 0,
18		image  => undef,
19		width  => 364,
20		height => 158,
21		designScale => [ 7, 16],
22	);
23	@$def{keys %prf} = values %prf;
24	return $def;
25}
26
27sub init
28{
29	my $self = shift;
30	$self-> {imageColors} = 0;
31	my %profile = $self-> SUPER::init(@_);
32
33	$self-> insert( qq(Prima::ImageViewer) =>
34		origin => [ 10, 40],
35		name => 'Panel',
36		size => [ 100, 100],
37		borderWidth => 1,
38		alignment =>  ta::Center,
39		valignment => ta::Center,
40		delegations => [ 'MouseDown'],
41	);
42	my $p = $self-> insert( qq(Prima::Widget) =>
43		origin => [ 120, 40],
44		name => 'Palette',
45		size => [ 235, 100],
46		delegations => [ 'Paint', 'MouseDown'],
47		buffered => 1,
48	);
49	my $se = $self-> insert( qq(Prima::SpinEdit) =>
50		origin => [ 120, 10],
51		name => 'Index',
52		size => [ 100, 20],
53		delegations => [ 'Change'],
54	);
55	$self-> insert( qq(Prima::Label) =>
56		origin => [ 10, 10],
57		size => [ 105, 19],
58		text => 'Color inde~x',
59		focusLink => $se,
60	);
61
62	my @sz = $p-> size;
63	my $sqd = 20;
64	$sz[$_] -= 5 for 0,1;
65	while ( $sqd-- > 1) {
66		my @d = map { int($sz[$_] / $sqd)} 0, 1;
67		last if $d[0] * $d[1] >= 256;
68	}
69	$p-> {sqd} = $sqd;
70	$p-> {columns} = int( $sz[0] / $sqd);
71	$p-> width( 4 + $p-> {columns} * $sqd);
72
73	$self-> image( $profile{image});
74	$self-> index( $profile{index});
75	return %profile;
76}
77
78sub image
79{
80	return $_[0]-> {image} unless $#_;
81	my ( $self, $i) = @_;
82	$self-> {image} = $i;
83	$self-> {imageColors} = scalar ( @{$self-> {image}-> palette}) / 3 if $i;
84	$self-> Index-> max( $self-> {imageColors} - 1);
85	return unless $self-> enabled;
86	$self-> Panel-> image( $self-> {image});
87	return unless $i;
88	my @szA = $i-> size;
89	my @szB = $self-> Panel->get_active_area(2);
90	my $xx = $szB[0]/$szA[0];
91	my $yy = $szB[1]/$szA[1];
92	$self-> Panel-> zoom( $xx < $yy ? $xx : $yy);
93}
94
95sub index
96{
97	return $_[0]-> Index-> value unless $#_;
98	my ( $self, $i) = @_;
99	my $v = $self-> Index-> value;
100	$i = 0 if $i < 0;
101	$i = $self-> {imageColors} - 1 if $i >= $self-> {imageColors};
102	return if $v == $i;
103	$self-> Index-> value( $_[1]);
104	$self-> Palette-> repaint;
105	$self-> notify(q(Change));
106}
107
108sub Index_Change
109{
110	$_[0]-> index( $_[1]-> value);
111	$_[0]-> Palette-> repaint;
112}
113
114sub on_enable
115{
116	my $self = $_[0];
117	$_-> enabled( 1) for $self-> widgets;
118	$self-> Panel-> image( $self-> {image});
119	return unless $self-> {image};
120	my @szA = $self-> {image}->size;
121	my @szB = $self-> Panel->get_active_area(2);
122	my $xx = $szB[0]/$szA[0];
123	my $yy = $szB[1]/$szA[1];
124	$self-> Panel-> zoom( $xx < $yy ? $xx : $yy);
125	$self-> Palette-> repaint;
126}
127
128sub on_disable
129{
130	my $self = $_[0];
131	$_-> enabled( 0) for $self-> widgets;
132	$self-> Panel-> image( undef);
133	$self-> Palette-> repaint;
134}
135
136sub Panel_MouseDown
137{
138	my ( $owner, $self, $btn, $mod, $x, $y) = @_;
139	return if $btn != mb::Left;
140	( $x, $y) = $self-> screen2point( $x, $y);
141	my @sz = $owner-> {image}-> size;
142	return if $x < 0 || $x >= $sz[0] || $y < 0 || $y >= $sz[1];
143	my $pix = $owner-> {image}-> pixel( $x, $y);
144	my $pal = $owner-> {image}-> palette;
145	my $i;
146	my $c = $owner-> {imageColors};
147	my ( $r, $g, $b) = cl::to_rgb($pix);
148	for ( $i = 0; $i < $c; $i++) {
149		last if $pal->[ $i * 3 + 0] == $b &&
150				$pal->[ $i * 3 + 1] == $g &&
151				$pal->[ $i * 3 + 2] == $r;
152	}
153	return if $i == $c;
154	$owner-> index( $i);
155}
156
157sub Palette_Paint
158{
159	my ( $owner, $self, $canvas) = @_;
160	my @sz = $self-> size;
161	my @c3d = ( $self-> light3DColor, $self-> dark3DColor);
162	$canvas-> rect3d( 0, 0, $sz[0]-1, $sz[1]-1, 1, reverse(@c3d), $self-> backColor);
163	return unless $owner-> {image};
164	my $c = $owner-> {imageColors};
165	my $p = $owner-> {image}-> palette;
166	my $x = 2;
167	my $s = $self-> {sqd};
168	my $y = $sz[1] - 2 - $s;
169	my $i;
170	my $e = $self-> enabled;
171	my $cl = $self-> {columns};
172	my $ci = 0;
173	my $se = $owner-> index;
174	$se = -1 unless $owner-> enabled;
175	my $bwo = ( $s > 7) ? 1 : 0;
176	for ( $i = 0; $i < $c; $i++) {
177		$canvas-> rect3d( $x, $y, $x + $s - 1, $y + $s - 1,
178		$bwo + (($se == $i) ? 1 : 0),
179			( $se == $i) ? reverse(@c3d) : @c3d,
180			$e ? ( $p->[$i*3] + $p-> [$i*3+1] * 256 + $p-> [$i*3+2] * 65536) : ()
181		);
182		$x += $s;
183		$x = 2, $y -= $s, $ci = 0 if ++$ci == $cl;
184	}
185}
186
187sub Palette_MouseDown
188{
189	my ( $owner, $self, $btn, $mod, $x, $y) = @_;
190	return if $btn != mb::Left;
191	my @sz = $self-> size;
192	my $c = $owner-> {imageColors};
193	$self-> clear_event;
194	$x = int(( $x - 2) / $self-> {sqd});
195	$y = int(( $sz[1] - $y - 3) / $self-> {sqd});
196	return if $x >= $self-> {columns};
197	return if $y * $self-> {columns} + $x >= $c;
198	$owner-> index( $y * $self-> {columns} + $x);
199}
200
201package Prima::Image::BasicTransparencyDialog;
202use vars qw(@ISA);
203@ISA = qw(Prima::Dialog);
204
205sub profile_default
206{
207	my $def = $_[ 0]-> SUPER::profile_default;
208	my %prf = (
209		width    => 480,
210		height   => 206,
211		centered => 1,
212		designScale => [ 7, 16],
213	);
214	@$def{keys %prf} = values %prf;
215	return $def;
216}
217
218sub init
219{
220	my $self = shift;
221	my %profile = $self-> SUPER::init(@_);
222	$self-> insert( qq(Prima::CheckBox) =>
223		origin => [ 3, 167],
224		name => 'Transparent',
225		size => [ 133, 36],
226		text => '~Transparent',
227		delegations => ['Check'],
228	);
229	$self-> insert( qq(Prima::Image::TransparencyControl) =>
230		origin => [ 3, 6],
231		size => [ 364, 158],
232		text => '',
233		name => 'TC',
234	);
235	$self-> insert( qq(Prima::Button) =>
236		origin => [ 379, 165],
237		name => 'OK',
238		size => [ 96, 36],
239		text => '~OK',
240		default => 1,
241		modalResult => mb::OK,
242		delegations => ['Click'],
243	);
244	$self-> insert( qq(Prima::Button) =>
245		origin => [ 379, 120],
246		size => [ 96, 36],
247		text => 'Cancel',
248		modalResult => mb::Cancel,
249	);
250	return %profile;
251}
252
253
254sub transparent
255{
256	my $self = $_[0];
257	$self-> Transparent-> checked( $_[1]);
258	$self-> TC-> enabled( $_[1]);
259}
260
261sub Transparent_Check
262{
263	my ( $self, $tr) = @_;
264	$self-> transparent( $tr-> checked);
265}
266
267sub on_change
268{
269	my ( $self, $codec, $image) = @_;
270	$self-> {image} = $image;
271	return unless $image;
272	$self-> transparent( $image-> {extras}-> {transparentColorIndex} ? 1 : 0);
273	$self-> TC-> image( $image);
274	$self-> TC-> index( exists( $image-> {extras}-> {transparentColorIndex}) ?
275		$image-> {extras}-> {transparentColorIndex} : 0);
276}
277
278sub OK_Click
279{
280	my $self = $_[0];
281	if ( $self-> Transparent-> checked) {
282		$self-> {image}-> {extras}-> {transparentColorIndex} = $self-> TC-> index;
283	} else {
284		delete $self-> {image}-> {extras}-> {transparentColorIndex};
285	}
286	delete $self-> {image};
287	$self-> TC-> image( undef);
288}
289
2901;
291
292=pod
293
294=head1 NAME
295
296Prima::Image::TransparencyControl - standard dialog
297for transparent color index selection.
298
299=head1 DESCRIPTION
300
301The module contains two classes - C<Prima::Image::BasicTransparencyDialog>
302and C<Prima::Image::TransparencyControl>. The former provides a dialog,
303used by image codec-specific save options dialogs to select a transparent
304color index when saving an image to a file. C<Prima::Image::TransparencyControl>
305is a widget class that displays the image palette and allow color rather than
306index selection.
307
308=head1 Prima::Image::TransparencyControl
309
310=head2 Properties
311
312=over
313
314=item index INTEGER
315
316Selects the palette index.
317
318=item image IMAGE
319
320Selects image which palette is displayed, and the color
321index can be selected from.
322
323=back
324
325=head2 Events
326
327=over
328
329=item Change
330
331Triggered when the user changes C<index> property.
332
333=back
334
335=head1 Prima::Image::BasicTransparencyDialog
336
337=head2 Methods
338
339=over
340
341=item transparent BOOLEAN
342
343If 1, the transparent selection widgets are enabled, and the
344user can select the palette index. If 0, the widgets are
345disabled; the image file is saved with no transparent color index.
346
347The property can be toggled interactively by a checkbox.
348
349=back
350
351=head1 AUTHOR
352
353Dmitry Karasik, E<lt>dmitry@karasik.eu.orgE<gt>.
354
355=head1 SEE ALSO
356
357L<Prima::Dialog::ImageDialog>.
358
359=cut
360