Viewing file: periodic.pl (15.46 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
=pod
=head1 NAME
examples/periodic.pl - A periodic table of elements
=head1 FEATURES
Demonstrates usage of grid widget
=cut
use strict; use warnings; use Prima qw(Application Grids);
my $scaling = $::application->uiScaling;
my $w = Prima::MainWindow-> create( text => "Periodic table of elements", size => [ map { $scaling * $_ } 45 * 14 + 5, 45 * 14 + 5], );
my @layers = ( 2, 8, 8, 10, 9, 10, 9, 10, 9, 10, 10, 0, 14, 14); my %colors = ( 2 => { 0 => cl::Blue, 10 => cl::Red, }, 8 => { 0 => cl::Blue, 1 => cl::Blue, 10 => cl::Red, default => 0x804000 }, 9 => { 0 => cl::Black, 1 => cl::Black, 10 => cl::Red, default => 0x804000 }, 10 => { 0 => cl::Blue, 1 => cl::Blue, default => cl::Black, }, 14 => { default => cl::Green, } ); my %sides = ( '9:0' => 4, '9:1' => 4, '9:2' => 4, '7:4' => 8, '8:4' => 8, '9:4' => 12, '7:6' => 8, '8:6' => 8, '9:6' => 12, '7:8' => 8, '8:8' => 8, '9:8' => 12, '7:10' => 8, '8:10' => 8, '9:10' => 12, '10:3' => 8, '10:5' => 8, '10:7' => 8, '10:9' => 8, '10:11' => 8, '0:11' => 8, '1:11' => 8, '2:11' => 8, '3:11' => 8, '4:11' => 8, '5:11' => 8, '6:11' => 8, # '11:4' => 8, '12:4' => 8, '13:4' => 12, # '10:5' => 12, '13:5' => 4, '13:6' => 4, # '11:7' => 8, '12:7' => 8, '13:7' => 8, );
package Periodic; use vars qw(@ISA); @ISA = qw(Prima::GridViewer);
my %elem_info = ( H => { atomic_number => 1, name => "Hydrogen", weight => "1.00794(7)", }, He => { atomic_number => 2, name => "Helium", weight => "4.002602(2)", },
Li => { atomic_number => 3, name => "Lithium", weight => "6.941(2)", }, Be => { atomic_number => 4, name => "Beryllium", weight => "9.012182(3)", }, B => { atomic_number => 5, name => "Boron", weight => "10.881(7)", }, C => { atomic_number => 6, name => "Carbon", weight => "12.0107(8)", }, N => { atomic_number => 7, name => "Nitrogen", weight => "14.00674(7)", }, O => { atomic_number => 8, name => "Oxygen", weight => "15.9994(3)", }, F => { atomic_number => 9, name => "Fluorine", weight => "18.9984032(5)", }, Ne => { atomic_number => 10, name => "Neon", weight => "20.1797(6)", },
Na => { atomic_number => 11, name => "Sodium", weight => "22.989770(2)", }, Mg => { atomic_number => 12, name => "Magnesium", weight => "24.3050(6)", }, Al => { atomic_number => 13, name => "Aluminium", weight => "26.981538(2)", }, Si => { atomic_number => 14, name => "Silicon", weight => "28.0855(3)", }, P => { atomic_number => 15, name => "Phosphorus", weight => "30.973761(2)", }, S => { atomic_number => 16, name => "Sulfur", weight => "32.066(6)", }, Cl => { atomic_number => 17, name => "Chlorine", weight => "35.4527(9)", }, Ar => { atomic_number => 18, name => "Argon", weight => "39.948(1)", }, K => { atomic_number => 19, name => "Potassium", weight => "39.0983(1)", }, Ca => { atomic_number => 20, name => "Calcium", weight => "40.078(4)", }, Sc => { atomic_number => 21, name => "Scandium", weight => "44.955910(8)", }, Ti => { atomic_number => 22, name => "Titanium", weight => "47.867(1)", }, V => { atomic_number => 23, name => "Vanadium", weight => "50.9415(1)", }, Cr => { atomic_number => 24, name => "Chromium", weight => "51.9961(6)", }, Mn => { atomic_number => 25, name => "Manganese", weight => "54.938049(9)", }, Fe => { atomic_number => 26, name => "Iron", weight => "55.845(2)", }, Co => { atomic_number => 27, name => "Cobalt", weight => "58.933200(9)", }, Ni => { atomic_number => 28, name => "Nickel", weight => "58.6934(2)", }, Cu => { atomic_number => 29, name => "Copper", weight => "63.546(3)", }, Zn => { atomic_number => 30, name => "Zinc", weight => "65.39(2)", }, Ga => { atomic_number => 31, name => "Gallium", weight => "69.723(1)", }, Ge => { atomic_number => 32, name => "Germanium", weight => "72.61(2)", }, As => { atomic_number => 33, name => "Arsenic", weight => "74.92160(2)", }, Se => { atomic_number => 34, name => "Selenium", weight => "78.96(3)", }, Br => { atomic_number => 35, name => "Bromine", weight => "79.904(1)", }, Kr => { atomic_number => 36, name => "Krypton", weight => "83.80(1)", },
Rb => { atomic_number => 37, name => "Rubidium", weight => "85.4678(3)", }, Sr => { atomic_number => 38, name => "Strontium", weight => "87.62(1)", }, Y => { atomic_number => 39, name => "Yttrium", weight => "88.90585(2)", }, Zr => { atomic_number => 40, name => "Zirconium", weight => "91.224(2)", }, Nb => { atomic_number => 41, name => "Niobium", weight => "92.90638(2)", }, Mo => { atomic_number => 42, name => "Molybdenum", weight => "95.94(1)", }, Tc => { atomic_number => 43, name => "Technetium", weight => "[97.9072]", }, Ru => { atomic_number => 44, name => "Ruthenium", weight => "101.07(2)", }, Rh => { atomic_number => 45, name => "Rhodium", weight => "102.90550(2)", }, Pd => { atomic_number => 46, name => "Palladium", weight => "106.42(1)", }, Ag => { atomic_number => 47, name => "Silver", weight => "107.8682(2)", }, Cd => { atomic_number => 48, name => "Cadmium", weight => "112.411(8)", }, In => { atomic_number => 49, name => "Indium", weight => "114.818(3)", }, Sn => { atomic_number => 50, name => "Tin", weight => "118.710(7)", }, Sb => { atomic_number => 51, name => "Antimony", weight => "121.760(1)", }, Te => { atomic_number => 52, name => "Tellurium", weight => "127.60(3)", }, I => { atomic_number => 53, name => "Iodine", weight => "126.90447(3)", }, Xe => { atomic_number => 54, name => "Xenon", weight => "131.29(2)", },
Cs => { atomic_number => 55, name => "Caesium", weight => "132.90545(2)", }, Ba => { atomic_number => 56, name => "Barium", weight => "137.327(7)", }, La => { atomic_number => 57, name => "Lanthanum", weight => "138.9055(2)", },
Hf => { atomic_number => 72, name => "Hafnium", weight => "178.49(2)", }, Ta => { atomic_number => 73, name => "Tantalum", weight => "180.9479(1)", }, W => { atomic_number => 74, name => "Tungsten", weight => "183.84(1)", }, Re => { atomic_number => 75, name => "Rhenium", weight => "186.207(1)", }, Os => { atomic_number => 76, name => "Osmium", weight => "190.23(3)", }, Ir => { atomic_number => 77, name => "Iridium", weight => "192.217(3)", }, Pt => { atomic_number => 78, name => "Platinum", weight => "195.078(2)", }, Au => { atomic_number => 79, name => "Gold", weight => "196.96655(2)", }, Hg => { atomic_number => 80, name => "Mercury", weight => "200.59(2)", }, Tl => { atomic_number => 81, name => "Thallium", weight => "204.3383(2)", }, Pb => { atomic_number => 82, name => "Lead", weight => "207.2(1)", }, Bi => { atomic_number => 83, name => "Bismuth", weight => "208.98038(2)", }, Po => { atomic_number => 84, name => "Polonium", weight => "[208.9824]", }, At => { atomic_number => 85, name => "Astatine", weight => "[209.9871]", }, Rn => { atomic_number => 86, name => "Radon", weight => "[222.0176]", },
Fr => { atomic_number => 87, name => "Francium", weight => "[223.0197]", }, Ra => { atomic_number => 88, name => "Radium", weight => "[226.0254]", }, Ac => { atomic_number => 89, name => "Actinium", weight => "[227.0277]", },
Rf => { atomic_number => 104, name => "Rutherfordium", weight => "[263.1125]", }, Db => { atomic_number => 105, name => "Dubnium", weight => "[262.1144]", }, Sg => { atomic_number => 106, name => "Seaborgium", weight => "[266.1219]", }, Bh => { atomic_number => 107, name => "Bohrium", weight => "[264.1247]", }, Hs => { atomic_number => 108, name => "Hassium", weight => "[269.1341]", }, Mt => { atomic_number => 109, name => "Meitnerium", weight => "[268.1388]", }, Ds => { atomic_number => 110, name => "Darmstadtium", weight => "[272.1463]", }, Rg => { atomic_number => 111, name => "Roentgenium", weight => "[282]", }, Cn => { atomic_number => 112, name => "Copenicium", weight => "[285]", }, Nh => { atomic_number => 113, name => "Nihonium", weight => "[286]", }, Fl => { atomic_number => 114, name => "Flerovium", weight => "[289]", }, Mc => { atomic_number => 115, name => "Moscovium", weight => "[290]", }, Lv => { atomic_number => 116, name => "Livermorium", weight => "[293]", }, Ts => { atomic_number => 117, name => "Tennessine", weight => "[294]", }, Og => { atomic_number => 118, name => "Oganesson", weight => "[294]", },
Ce => { atomic_number => 58, name => "Cerium", weight => "140.116(1)", }, Pr => { atomic_number => 59, name => "Praseodymium", weight => "140.90765(2)", }, Nd => { atomic_number => 60, name => "Neodymium", weight => "144.24(3)", }, Pm => { atomic_number => 61, name => "Promethium", weight => "[144.9127]", }, Sm => { atomic_number => 62, name => "Samarium", weight => "150.36(3)", }, Eu => { atomic_number => 63, name => "Europium", weight => "151.964(1)", }, Gd => { atomic_number => 64, name => "Gadolinium", weight => "157.25(3)", }, Tb => { atomic_number => 65, name => "Terbium", weight => "158.92534(2)", }, Dy => { atomic_number => 66, name => "Dysprosium", weight => "162.50(3)", }, Ho => { atomic_number => 67, name => "Holmium", weight => "164.93032(2)", }, Er => { atomic_number => 68, name => "Erbium", weight => "167.26(3)", }, Tm => { atomic_number => 69, name => "Thulium", weight => "168.93421(2)", }, Yb => { atomic_number => 70, name => "Ytterbium", weight => "173.04(3)", }, Lu => { atomic_number => 71, name => "Lutetium", weight => "174.967(1)", },
Th => { atomic_number => 90, name => "Thorium", weight => "232.0381(1)", }, Pa => { atomic_number => 91, name => "Protactinium", weight => "231.03588(2)", }, U => { atomic_number => 92, name => "Uranium", weight => "238.0289(1)", }, Np => { atomic_number => 93, name => "Neptunium", weight => "[237.0482]", }, Pu => { atomic_number => 94, name => "Plutonium", weight => "[244.0642]", }, Am => { atomic_number => 95, name => "Americium", weight => "[243.0614]", }, Cm => { atomic_number => 96, name => "Curium", weight => "[247.0703]", }, Bk => { atomic_number => 97, name => "Berkelium", weight => "[247.0703]", }, Cf => { atomic_number => 98, name => "Californium", weight => "[251.0796]", }, Es => { atomic_number => 99, name => "Einsteinium", weight => "[252.0830]", }, Fm => { atomic_number => 100, name => "Fermium", weight => "[257.0951]", }, Md => { atomic_number => 101, name => "Mendelevium", weight => "[258.0984]", }, No => { atomic_number => 102, name => "Nobelium", weight => "[259.1011]", }, Lr => { atomic_number => 103, name => "Lawrencium", weight => "[262.110]", }, );
sub on_keydown { my $self = shift; local $self->{inside_keydown} = 1; $self->SUPER::on_keydown(@_); }
sub focusedCell { return $_[0]-> SUPER::focusedCell unless $#_; my ($self,$x,$y) = @_; ($x, $y) = @$x if !defined $y && ref($x) eq 'ARRAY';
my (@last, @dir); if ( $self-> {inside_keydown}) { @last = $self->SUPER::focusedCell; @dir = ($x - $last[0], $y - $last[1]); @dir = () unless (abs($dir[0]) == 1 && $dir[1] == 0) || (abs($dir[1]) == 1 && $dir[0] == 0); }
if ( @dir ) { my $text = $self-> {cells}-> [$last[1]]-> [$last[0]]; if ( $dir[0] == 1 ) { if ($text eq 'La' ) { ($x, $y) = (0, 12); } elsif ( $text eq 'Ac') { ($x, $y) = (0, 13); } elsif ( $text eq 'Lu') { ($x, $y) = (3, 7); } elsif ( $text eq 'Lr') { ($x, $y) = (3, 9); } } elsif ( $dir[0] == -1 ) { if ($text eq 'Hf' ) { ($x, $y) = (13, 12); } elsif ( $text eq 'Rf') { ($x, $y) = (13, 13); } elsif ( $text eq 'Ce') { ($x, $y) = (2, 7); } elsif ( $text eq 'Th') { ($x, $y) = (2, 9); } } }
unless ($y >= 0 && $x >= 0 && $self-> {cells}-> [$y] && $self-> {cells}-> [$y]-> [$x] && length $self-> {cells}-> [$y]-> [$x] ) { return unless @dir; my $n = 9; my @p = ($x, $y); my $c = $self->{cells}; while ($n-- > 0) { $p[$_] += $dir[$_] for 0,1; last if $p[0] < 0 || $p[1] < 0 || $p[1] >= @$c || $p[0] >= @{$c->[$p[1]]}; my $item = $c-> [$p[1]]-> [$p[0]]; next unless defined($item) and defined ($elem_info{$item}-> {name}); ($x,$y) = @p; goto SETFOC; }
if ( $dir[0] == 1 && $y < $#$c ) { my $item = $c-> [$y + 1]-> [0]; if ( defined($item) and defined ($elem_info{$item}-> {name})) { $x = 0; $y++; goto SETFOC; } } elsif ( $dir[0] == -1 && $y > 0 ) { my $n = 5; my $nx = @{$c->[$y - 1]} - 1; while ( $n-- > 0 ) { my $item = $c-> [$y - 1]-> [$nx]; if ( defined($item) and defined ($elem_info{$item}-> {name})) { $x = $nx; $y--; goto SETFOC; } $nx--; } }
return; } SETFOC: $self-> SUPER::focusedCell( $x, $y); }
my @small_font_metrics;
my $g = $w-> insert( Periodic => origin => [0,0], size => [$w-> size], growMode => gm::Client, cells => [ ['H', ('')x9, 'He', ('')x3], [qw(Li Be B C N O F), ('')x3,'Ne', ('')x3], [qw(Na Mg Al Si P S Cl), ('')x3,'Ar', ('')x3], [qw(K Ca Sc Ti V Cr Mn Fe Co Ni), ('')x4], [qw(Cu Zn Ga Ge As Se Br), ('')x3,'Kr', ('')x3], [qw(Rb Sr Y Zr Nb Mo Tc Ru Rh Pd), ('')x4], [qw(Ag Cd In Sn Sb Te I), ('')x3,'Xe', ('')x3], [qw(Cs Ba La Hf Ta W Re Os Ir Pt), ('')x4], [qw(Au Hg Tl Pb Bi Po At), ('')x3,'Rn', ('')x3], [qw(Fr Ra Ac Rf Db Sg Bh Hs Mt Ds), ('')x4], [qw(Rg Cn Nh Fl Mc Lv Ts), ('')x3,'Og', ('')x3], [('') x 14], [qw(Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu)], [qw(Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr)], ], drawHGrid => 0, drawVGrid => 0, constantCellWidth => int( 45 * $scaling + .5), constantCellHeight => int( 45 * $scaling + .5), multiSelect => 0, onDrawCell => sub { my ( $self, $canvas, $column, $row, $indent, $sx1, $sy1, $sx2, $sy2, $cx1, $cy1, $cx2, $cy2, $selected, $focused, $prelight) = @_; $canvas-> clear($sx1, $sy1, $sx2, $sy2); my $item = $self-> {cells}-> [$row]-> [$column]; my $color = $colors{$layers[$row]}; if ( length $item) { return unless $color; return unless defined ($color = ( exists $color-> {$column}) ? $color-> {$column} : $color-> {default}); $canvas-> color( cl::Black); $canvas-> rectangle( $cx1-1, $cy1-1, $cx2, $cy2); if ( $focused || $prelight ) { $self-> draw_item_background($canvas, $cx1, $cy1, $cx2-1, $cy2-1, $prelight, $focused ? $self-> hiliteBackColor : cl::Back); $canvas-> backColor( cl::Back ); $canvas-> color( $focused ? $self-> hiliteColor : cl::Fore); } else { $canvas-> color( $color); } $canvas-> text_out( $item, $cx1 + 10 * $scaling, $cy1 + 10 * $scaling); my $f = $canvas-> font; $canvas-> font( height => 12 * $scaling ); @small_font_metrics = ( $canvas-> get_text_width('3'), $f-> height) unless @small_font_metrics;
my $text = $elem_info{$item}-> {atomic_number}||""; $canvas-> text_out( $text, $cx2 - $small_font_metrics[0] * length($text) - 4, $cy2 - $small_font_metrics[1] - 4); $canvas-> font($f); $canvas-> rect_focus( $sx1, $sy1, $sx2-1, $sy2-1) if $focused; } elsif ( exists $sides{"$column:$row"}) { my $side = $sides{"$column:$row"}; $canvas-> color( cl::Black); $canvas-> line( $cx1-1,$cy1-1,$cx2,$cy1-1 ) if $side & 1; $canvas-> line( $cx1-1,$cy1-1,$cx1-1,$cy2 ) if $side & 2; $canvas-> line( $cx2,$cy1-1,$cx2,$cy2 ) if $side & 4; $canvas-> line( $cx1-1,$cy2,$cx2,$cy2 ) if $side & 8; } }, onClick => sub { my ($self) = @_; my @foc = $self-> focusedCell; my $text = $self-> {cells}-> [$foc[1]]-> [$foc[0]]; return unless $text; if ($text eq "La") { $self-> focusedCell(0, 11); } elsif ($text eq "Ac") { $self-> focusedCell(0, 12); } }, onSelectCell => sub { my ( $self, $col, $row) = @_; my $item = $self-> {cells}-> [$row]-> [$col]; return unless defined($item) and defined ($elem_info{$item}-> {name}); $w-> text("Periodic table of elements - $elem_info{$item}->{name} $elem_info{$item}->{atomic_number} $elem_info{$item}->{weight}"); }, );
run Prima;
|