package Application::Option; use strict; use warnings; use Tk; use version; ... # firstly, create subroutines that do the right thing for various Tk versions # poulate Listboxes with modern Tk's sub renderListAutoPopulate { my (undef, $parentWidget, $listVariable) = @_; return $parentWidget->Listbox( -listvariable => $listVariable, # autopopulate from this list # other options as required )->pack( # pack options ); } # populate old Tk Listboxes sub renderListManualPopulate { my (undef, $parentWidget, $listVariable) = @_; my $thisListbox = $parentWidget->Listbox( # options as required )->pack( # pack options ); $thisListbox->insert('end', @$listVariable); return $thisListbox; } # present numeric options with modern Tk Spinbox sub renderNumericOptionAsSpinbox { my (undef, $parent, $value) = @_; $parent->Spinbox( # spinbox options as required )->pack( # pack options ); } # present numeric option as a Tk::Entry widget, for older Tk's sub renderNumericOptionAsEntry { my (undef, $parent, $value) = @_; $parent->Entry( # Entry options as required )->pack( # pack options ); } # secondly, populate typeglobs with the required function references # version.pm overloads relational and stringification operators conveniently INIT { if (qv(Tk->VERSION()) >= "804.027") { # modern Tk *numericWidget = \&renderNumericOptionAsSpinbox; *listboxWidget = \&renderListAutoPopulate; } else { # older-style Tk *numericWidget = \&renderNumericOptionAsEntry; *listboxWidget = \&renderListManualList; } } # thirdly, call the code slot in the typeglob as required in the application ... } elsif (numericOption($option)) { $self->numericWidget($parent, $option); } elsif (listboxOption($option)) { $self->listboxWidget($parent, $option); } elsif (# other option types ...