To give you another example, the following simple Perl/Tk program demonstrates a ROText widget containing information about 20 famous companies (name, address and homepage), with column headings which can be clicked on to sort by the data in that column.
I'm working on a project of my own, which will ultimately have a very similar forward-sort/reverse-sort capability:
#!/usr/bin/perl -w
# Strict
use strict;
use warnings;
# Libraries
use Tk;
use Tk::ROText;
# User-defined
my $linux_browser = 'firefox';
my $win32_browser = 'C:\\PROGRA~1\\MOZILL~1\\FIREFOX.EXE';
my $headerfont = "Courier 10 bold";
my $textfont = "Courier 10";
my $urlfont = "Courier 10 italic";
my @colors = qw( peachpuff lightyellow );
my @columns = qw( Company Address Homepage );
my $p_col_widths = { 'Company' => 20, 'Address' => 20, 'Homepage' =>
+ 28 };
my $pdata = [
['General Electric', 'Fairfield, CT', 'www.ge.com'
+ ],
['FedEx', 'Memphis, TN', 'www.fedex.com'
+ ],
['Southwest Airlines', 'Dallas, TX', 'www.southwest.com'
+ ],
['Procter & Gamble', 'Cincinnati, OH', 'www.pg.com'
+ ],
['Starbucks', 'Seattle, WA', 'www.starbucks.com'
+ ],
['Johnson & Johnson', 'New Brunswick, NJ', 'www.jnj.com'
+ ],
['Berkshire Hathaway', 'Omaha, NE', 'www.berkshirehathaway
+.com'],
['Dell', 'Round Rock, TX', 'www.dell.com'
+ ],
['Toyota', 'Toyota, Japan', 'www.toyota.co.jp'
+ ],
['Microsoft', 'Redmond, WA', 'www.microsoft.com'
+ ],
['Apple Computer', 'Cupertino, CA', 'www.apple.com'
+ ],
['Wal-Mart', 'Bentonville, AR', 'www.walmartstores.com
+' ],
['UPS', 'Atlanta, GA', 'www.ups.com'
+ ],
['Home Depot', 'Atlanta, GA', 'www.homedepot.com'
+ ],
['PepsiCo', 'Purchase, NY', 'www.pepsico.com'
+ ],
['Costco', 'Issaquah, WA', 'www.costco.com'
+ ],
['American Express', 'New York, NY', 'www.americanexpress.c
+om' ],
['Goldman Sachs', 'New York, NY', 'www.gs.com'
+ ],
['IBM', 'Armonk, NY', 'www.ibm.com'
+ ],
['3M', 'St. Paul, MN', 'www.3m.com'
+ ],
];
# Main program
# Create the GUI
my $mw = new MainWindow;
my $f1 = $mw->Frame()->pack(-expand => 0, -fill => 'x');
my $f2 = $mw->Frame()->pack(-expand => 1, -fill => 'both');
button($f1, 'Exit', 'right', sub { $mw->destroy() }, "Escape");
my $txt = $f2->Scrolled('ROText', -scrollbars => 'osoe');
$txt->configure(-width => 90, -height => 32, -selectforeground => 'bla
+ck');
$txt->pack(-expand => 1, -fill => 'both');
sort_by_column(1, 0);
MainLoop;
# Subroutines
sub button {
my ($w, $text, $side, $psub, $bind) = @_;
($bind || 0) and $text .= " ($bind)";
my $btn = $w->Button(-bg => 'skyblue', -text => $text);
if ($psub || 0) {
$btn->configure(-command => $psub);
($bind || 0) and $mw->bind("<$bind>" => sub { $btn->invoke() }
+);
}
$btn->pack(-side => $side);
return $btn;
}
sub sort_by_column {
my ($idx, $order) = @_;
# Delete all items in the Text widget
$txt->delete("1.0", "end");
my $item_count = 0;
# Display each column of the header
for (my $i = 1; $i <= @columns; $i++) {
my $text = my $column = $columns[$i - 1];
my $b_this_col = ($idx == $i)? 1: 0;
$b_this_col and $text .= (0 == $order)? " (+)": " (-)";
my $width = $p_col_widths->{$column};
my $line = sprintf "| %-${width}.${width}s", $text;
my $tag = "column_$column";
($i == @columns) and $line .= "\n";
my $new_idx = $i;
my $psub = sub {
my $new_order = $b_this_col? 1 - $order: 0;
sort_by_column($new_idx, $new_order);
};
insert_item($line, '#ff7fef', $tag, $headerfont, $psub);
}
# Sort all data by the given field index
my @sorted = $order? sort { $b->[$idx-1] cmp $a->[$idx-1] } @$pdat
+a:
sort { $a->[$idx-1] cmp $b->[$idx-1] } @$pdat
+a;
# Display each line of the data
for (my $i = 0; $i < @sorted; $i++) {
my $pcompany = $sorted[$i];
++$item_count;
my $color = $colors[$item_count % @colors];
for (my $j = 1; $j <= @columns; $j++) {
my $column = $columns[$j-1];
my $data = $pcompany->[$j-1];
my $width = $p_col_widths->{$column};
my $line = sprintf "| %-${width}.${width}s", $data;
($j == @columns) and $line .= "\n";
my $tag = "item_${item_count}_$j";
if ($column eq 'Homepage') {
my $psub = sub { launch_url($data) };
insert_item($line, $color, $tag, $urlfont, $psub);
} else {
insert_item($line, $color, $tag, $textfont);
}
}
}
}
sub insert_item {
my ($text, $bg, $tag, $font, $psub) = @_;
$txt->tagConfigure($tag, -font => $font, -background => $bg);
($psub || 0) and make_text_hot($tag, $psub);
$txt->insert("end", $text, $tag);
}
sub make_text_hot {
my ($tag, $psub) = @_;
my $p_enter_sub = sub { $txt->configure(-cursor => 'hand2') };
my $p_leave_sub = sub { $txt->configure(-cursor => 'xterm') };
$txt->tagBind($tag, "<Button-1>", $psub);
$txt->tagBind($tag, "<Any-Enter>", $p_enter_sub);
$txt->tagBind($tag, "<Any-Leave>", $p_leave_sub);
}
sub launch_url {
my ($url) = @_;
if ($^O =~ /win32/i) {
# Startup the preferred Windows browser
system("start $win32_browser \"$url\"");
} else {
# Child process runs the preferred Linux browser, parent retur
+ns
fork or exec "$linux_browser '$url'";
}
}
The column which is sorted by changes its text to include either "(+)" for a forward sort, or "(-)" for a reverse sort. Furthermore, any URL in the homepage address column can be clicked on to bring that page up in a browser (the browsers are set according to the variables $linux_browser and $win32_browser).
s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
|