package Tk::ColorEntry; use strict; use warnings; use vars qw($VERSION); $VERSION = '0.11'; use Tk; use base qw(Tk::Derived Tk::Frame); Construct Tk::Widget 'ColorEntry'; require Tk::PopColor; =head1 NAME Tk::ColorEntry - Entry widget with a color selection facilities. =head1 SYNOPSIS use Tk::ColorEntry; my $entry = $window->ColorEntry->pack; =head1 DESCRIPTION Megawidget, inherits L Tk::ColorEntry is an entry widget with a label packed to it's right. The background color of the label is used as indicator for the current color. Clicking the entry widget pops a L widget. Pressing escape causes the ColorPop to widthdraw. If a pick operation is active cancels the pick operation instead. =head1 OPTIONS You can use many options of L. =over 4 =item Switch: B<-command> Callback to be executed when a color is selected. The color is given as parameter. =item Switch: B<-entryerrorcolor> Default value '#FF0000' (red). Foreground color of the entry when it's content is not a valid color. =item Switch: B<-indborderwidth> Default value 2. Borderwidth of the indicator label. =item Switch: B<-indicatorwidth> Default value 4. Width of the indicator label. =item Switch: B<-indrelief> Default value 'sunken'. Relief of the indicator label. =item Switch: B<-popcolor> Sets and returns the reference to the PopColor widget to be used. =item Switch: B<-variable> Reference to the variable where the current value is held. =back =head1 METHODS You can use many methods of L. =over 4 =cut sub Populate { my ($self,$args) = @_; my $pop = delete $args->{'-popcolor'}; $self->SUPER::Populate($args); my $entry = $self->Entry( )->pack( -side => 'left', -expand => 1, -fill => 'x', # -pady => 2, ); my $indicator = $self->Label->pack( -side => 'left', -fill => 'y', -padx => 2, # -pady => 2, ); $self->Advertise('Display', $indicator); $self->Advertise('Entry', $entry); $pop = $self->PopColor( -updatecall => sub { $self->put(shift); }, -widget => $self, ) unless defined $pop; $self->Advertise('Pop', $pop); $entry->bind('', [$self, 'popBlock']); $entry->bind('', [$self, 'popFlip']); $entry->bind('', [$self, 'popFlip']); # $entry->bind('', [$self, 'popDown']); $entry->bind('', [$self, 'OnKey']); $entry->bind('', [$self, 'OnEscape']); $self->{POPBLOCK} = 0; my $var = ''; $self->ConfigSpecs( -background => ['SELF', 'DESCENDANTS'], -command => ['CALLBACK', undef, undef, sub {}], -entryerrorcolor => ['PASSIVE', undef, undef, '#FF0000'], -entryforeground => ['PASSIVE', undef, undef, $self->Subwidget('Entry')->cget('-foreground')], -font => [$entry], -foreground => [$entry], -historyfile => [$pop->Subwidget('Picker')], -indborderwidth => [{-borderwidth => $indicator}, undef, undef, 2], -indicatorwidth => [{-width => $indicator}, undef, undef, 4], -indrelief => [{-relief => $indicator}, undef, undef, 'sunken'], -justify => [$entry], -popborderwidth => [{-borderwidth => $pop}, undef, undef, 1], -popcolor => ['PASSIVE', undef, undef, $pop], -poprelief => [{-relief => $pop}, undef, undef, 'raised'], -state => [$entry], -variable => [{-textvariable => $entry}, undef, undef, \$var], -width => [$entry], DEFAULT => [ $pop ], ); $self->Delegates( DEFAULT => $pop, ); } sub EntryUpdate { my $self = shift; my $entry = $self->Subwidget('Entry'); my $display = $self->Subwidget('Display'); my $val = $entry->get; if ($self->validate($val)) { my $pop = $self->Subwidget('Pop'); my $current = $pop->getHEX; $display->configure(-background => $current) if $self->validate($current); $entry->configure(-foreground => $self->cget('-entryforeground')); } else { $display->configure(-background => $self->cget('-background')); $entry->configure(-foreground => $self->cget('-entryerrorcolor')); } } =item B Returns the contents of the entry widget if it is a valid color. =cut sub get { my $self = shift; my $color = $self->Subwidget('Entry')->get; return $color if $self->validate($color); } sub OnEscape { my $self = shift; if ($self->pickInProgress) { $self->pickCancel } else { my $save = delete $self->{'e_save'}; $self->put($save) if defined $save; $self->popCancel; } } sub OnKey { my $self = shift; my $color = $self->Subwidget('Entry')->get; $self->put($color) if $self->validate($color); $self->EntryUpdate; } sub popCancel { my $self = shift; delete $self->{'e_save'}; $self->cget('-popcolor')->popCancel; } sub popBlock { my $self = shift; if ($self->cget('-popcolor')->ismapped) { my $color = $self->Subwidget('Entry')->get; $self->Callback('-command', $color) if $self->validate($color); $self->{POPBLOCK} = 1; $self->after(400, sub { $self->{POPBLOCK} = 0}); } } sub popDown { my $self = shift; delete $self->{'e_save'}; my $color = $self->Subwidget('Entry')->get; $self->Callback('-command', $color) if $self->validate($color); $self->cget('-popcolor')->popDown; } sub popFlip { my $self = shift; if ($self->cget('-popcolor')->ismapped) { $self->popDown } else { $self->popUp unless $self->{POPBLOCK} } } sub popUp { my $self = shift; my $save = $self->Subwidget('Entry')->get; $self->{'e_save'} = $save; my $pop = $self->cget('-popcolor'); $pop->configure(-widget => $self->Subwidget('Entry')); $pop->configure(-updatecall => ['put', $self]); $pop->put($save); $pop->popUp; } =item B(I<$color>) $color becomes the content of the entry widget. Adjusts the sliders if $color is a valid color. =cut; sub put { my ($self, $color) = @_; unless (defined($color)) { warn "color is not defined"; return } my $var = $self->Subwidget('Entry')->cget('-textvariable'); $$var = $color; my $pop = $self->Subwidget('Pop'); $pop->put($color); $self->EntryUpdate; } =back =head1 LICENSE Same as Perl. =head1 AUTHOR Hans Jeuken (hanje at cpan dot org) =cut =head1 BUGS Unknown. If you find any, please contact the author. =head1 SEE ALSO =over 4 =item L =item L =item L =back =cut 1; __END__