The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

#!/usr/local/bin/perl -w
#
# This script demonstrates the various widgets provided by Tk, along with many of the features of the Tk toolkit. This file
# only contains code to generate the main window for the application, which invokes individual demonstrations. The code for
# the actual demonstrations is contained in separate ".pl" files in the directory "widget_lib", which are auto-loaded by Perl
# when they are needed. To find the code for a particular demo, look below for the procedure that's invoked by its menu entry,
# then grep for the file that contains the procedure definition.
#
# Tcl/Tk -> Perl translation by Stephen O. Lidie. lusol@Lehigh.EDU 95/01/08
require 5.001;
use Tk;
use English;
$auto_path = "Tk/demos/widget_lib";
sub AUTOLOAD {
# This routine handles the loading of most menu button methods.
my($prefix, $method) = $AUTOLOAD =~ /(.*)::(.+)$/;
eval "require \"$auto_path/${method}.pl\"";
die $@ if $@;
goto &$AUTOLOAD;
} # end AUTOLOAD
sub dpos {
# Position a window at a reasonable place on the screen.
shift->geometry('+300+300');
} # end dpos
sub insert_with_tags {
# The procedure below inserts text into a given text widget and applies one or more tags to that text. The arguments are:
#
# w Window in which to insert
# text Text to insert (it's inserted at the "insert" mark)
# args One or more tags to apply to text. If this is empty then all tags are removed from the text.
my($w, $text, @args) = @_;
my($tag, $i, $start);
$start = $w->index('insert');
$w->insert('insert', $text);
foreach $tag ($w->tag('names', $start)) {
$w->tag('remove', $tag, $start, 'insert');
}
foreach $i (@args) {
$w->tag('add', $i, $start, 'insert');
}
} # end insert_with_tags
sub lsearch {
# Search the list using the supplied regular expression and return it's ordinal, or -1 if not found.
my($regexp, @list) = @_;
my($i);
for ($i=0; $i<=$#list; $i++) {
return $i if $list[$i] =~ /$regexp/;
}
return -1;
} # end lsearch
sub mkmb {
# Make a Menubutton widget; note that the menu is automatically created. We maintain a list of the Menubutton references
# since some callers need to refer to the Menubutton, as well as to suppress stray name warnings with Perl -w.
my($mb_label, $mb_label_underline, $mb_list_ref) = @_;
my $mb = $menu->Menubutton(-text => $mb_label, -underline => $mb_label_underline);
foreach $mb_list (@{$mb_list_ref}) {
$mb->command(-label => $mb_list->[0], -command => $mb_list->[1] , -underline => $mb_list->[2]);
}
$mb->pack(-side => 'left');
push @menu_button_list, $mb;
} # end mkmb
$top = MainWindow->new;
$top->title('Widget Demonstration');
# The code below creates the main window, consisting of a menu bar and a message explaining the basic operation of the program.
$menu = $top->Frame(-relief => 'raised', -borderwidth => 1);
$mess = $top->Message(-font => '-Adobe-times-medium-r-normal--*-180-*-*-*-*-*-*', -relief => 'raised', -width => 500,
-borderwidth => 1, -text => "This application demonstrates the widgets provided by the Tk toolkit. " .
"The menus above are organized by widget type: each menu contains one or more demonstrations of a " .
"particular type of widget. To invoke a demonstration, press mouse button 1 over one of the menu " .
"buttons above, drag the mouse to the desired entry in the menu, then release the mouse button.\n\nTo " .
"exit this demonstration, invoke the \"Quit\" entry in the \"Misc\" menu.");
$menu->pack(-side => 'top', -fill => 'x');
$mess->pack(-side, 'bottom', -expand => 'yes', -fill => 'both');
# The code below creates all the Dialog objects required by this widget demonstration program.
$DialogRef_bml = $top->Dialog(-title => 'Bitmap menu label');
$DialogRef_bml->Subwidget('message')->configure(-wraplength => '2.5i', -text => 'The menu entry you invoked displays a bitmap ' .
'rather than a text string. Other than this, it is just like any other menu entry.');
$DialogRef_lg = $top->Dialog(-title => 'Modal dialog (local grab)');
$DialogRef_lg->Subwidget('message')->configure(-wraplength => '4i', -justify => 'left', -text =>'This dialog box is a modal one. ' .
'It uses Tk\'s "grab" command to create a "local grab" on the dialog box. The grab ' .
'prevents any pointer-related events from getting to any other windows in the application. ' .
'If you press the "OK" button below (or hit the Return key) then the dialog box will go ' .
'away and things will return to normal.');
$DialogRef_gg = $top->Dialog(-title => 'Modal dialog (global grab)');
$DialogRef_gg->Subwidget('message')->configure(-wraplength => '4i', -text => 'This is another modal dialog box. However, in this ' .
'case a "global grab" is used, which locks up the display so you can\'t talk to any windows in ' .
'any applications anywhere, except for the dialog. If you press the "OK" button below (or hit ' .
'the Return key) then the dialog box will go away and things will return to normal.');
# The code below creates all the menus, which invoke procedures to create particular demonstrations of various widgets.
mkmb('Labels_Buttons', 7,
[
['Labels', \&mkLabel, 0],
['Buttons', \&mkButton, 0],
['Checkbuttons', \&mkCheck, 0],
['Radiobuttons', \&mkRadio, 0],
['15-puzzle', \&mkPuzzle, 0],
['Iconic buttons', \&mkIcon, 0],
]);
$menu_button_list[$#menu_button_list]->configure(-text => 'Labels/Buttons');
mkmb('Listboxes', 0,
[
['States', \&mkListbox, 0],
['Colors', \&mkListbox2, 0],
['Well-known sayings', \&mkListbox3, 0],
]);
mkmb('Entries', 0,
[
['Without scrollbars', \&mkEntry, 4],
['With scrollbars', \&mkEntry2, 0],
['Simple form', \&mkForm, 0],
]);
mkmb('Text', 0,
[
['Basic text', \&mkBasic, 0],
['Display styles', \&mkStyles, 0],
['Command bindings', \&mkTextBind, 0],
['Embedded windows', \&mkTextWind, 0],
['Search', \&mkTxtSearch, 0],
]);
mkmb('Scrollbars', 0,
[
['Vertical', \&mkListbox2, 0],
['Horizontal', \&mkEntry2, 0],
]);
mkmb('Scales', 2,
[
['Vertical', \&mkVScale, 0],
['Horizontal', \&mkHScale, 0],
]);
mkmb('Canvases', 0,
[
['Item types', \&mkItems, 0],
['2-D plot', \&mkPlot, 0],
['Text', \&mkCanvText, 0],
['Arrow shapes', \&mkArrow, 0],
['Ruler', \&mkRuler, 0],
['Scrollable canvas', \&mkScroll, 0],
['Floor plan', \&mkFloor, 0],
]);
$MENUS_HI = 'Print hello';
$MENUS_BY = 'Print goodbye';
$MENUS_CB = 'Check buttons';
$MENUS_RB = 'Radio buttons';
mkmb('Menus', 0,
[
[$MENUS_HI, sub {print STDOUT "Hello\n"}, 6],
[$MENUS_BY, sub {print STDOUT "Goodbye\n"}, 6],
['Light blue background', sub {$mess->configure(-background => 'LightBlue1')}, 0],
]);
$mess->bind('<Any-Enter>' => sub {shift->focus});
$mess->bind('<Control-a>' => sub {print STDOUT "Hello\n"});
$mess->bind('<Control-b>' => sub {print STDOUT "Goodbye\n"});
my $menus = $menu_button_list[$#menu_button_list]->cget('-menu'); # get Menubutton "Menus" auto-created menu
$menus->entryconfigure($MENUS_HI, -accelerator => 'Control+a');
$menus->entryconfigure($MENUS_BY, -accelerator => 'Control+b');
$menus->cascade(-label => $MENUS_CB, -underline => 0);
$menus->cascade(-label => $MENUS_RB, -underline => 0);
$menus->command(-bitmap => '@'.Tk->findINC('demos/images/pattern'), -command => sub {$DialogRef_bml->Show});
my $menus_check = $menus->Menu();
$menus->entryconfigure($MENUS_CB, -menu => $menus_check);
$oil = 0;
$trans = 0;
$brakes = 0;
$lights = 0;
$menus_check->checkbutton(-label => 'Oil checked', -variable => \$oil);
$menus_check->checkbutton(-label => 'Transmission checked', -variable => \$trans);
$menus_check->checkbutton(-label => 'Brakes checked', -variable => \$brakes);
$menus_check->checkbutton(-label => 'Lights checked', -variable => \$lights);
$menus_check->separator;
$menus_check->command(-label => 'Show current values', -command => [\&showVars, $top, qw(oil trans brakes lights)]);
$menus_check->invoke(1);
$menus_check->invoke(3);
my $menus_radio = $menus->Menu();
$menus->entryconfigure($MENUS_RB, -menu => $menus_radio);
$pointSize = 0;
$style = 'roman';
$menus_radio->radiobutton(-label => '10 point', -variable => \$pointSize, -value => 10);
$menus_radio->radiobutton(-label => '14 point', -variable => \$pointSize, -value => 14);
$menus_radio->radiobutton(-label => '18 point', -variable => \$pointSize, -value => 18);
$menus_radio->radiobutton(-label => '24 point', -variable => \$pointSize, -value => 24);
$menus_radio->radiobutton(-label => '32 point', -variable => \$pointSize, -value => 32);
$menus_radio->separator;
$menus_radio->radiobutton(-label => 'Roman', -variable => \$style, -value => 'roman');
$menus_radio->radiobutton(-label => 'Bold', -variable => \$style, -value => 'bold');
$menus_radio->radiobutton(-label => 'Italic', -variable => \$style, -value => 'italic');
$menus_radio->separator;
$menus_radio->command(-label => 'Show current values', -command => [\&showVars, $top, 'pointSize', 'style']);
$menus_radio->invoke(1);
$menus_radio->invoke(7);
mkmb('Misc', 1,
[
['Modal dialog (local grab)', sub {$DialogRef_lg->Show}, 14],
['Modal dialog (global grab)', sub {$DialogRef_gg->Show('-global')}, 14],
['Built-in bitmaps', \&mkBitmaps, 0],
['Quit', \&exit, 0],
]);
MainLoop;