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