Making menus can be an complex activity. For now, I made a simple statistics application, demonstrating only
the basic features of a menu. More complex menu examples will follow in later chapters.
Notice that this program has statistical functions
without using modules. Compare: 4. Practical example in Part 3
use Prima qw(Application Themes InputLine Buttons Label); use Prima::Menus; require "/home/reinier/mcMessage.pl"; # code 7. Messagewindow $mw = Prima::MainWindow-> create( text => "Menu example", size => [ 600, 200], icon => Prima::Icon-> load('icon.png'), backColor => 0x606060, skin => 'flat', menuItems => [ [ '~File' => [ [ '-', 'Preferences disabled', '', '', sub {} ],# disbabled by - prefix [], # divisor line [ 'Exit', 'Alt+X', '@X', sub { exit } ],# @X is equivalent to km::Alt | X ] ], [ '~Insert' => [ [ '2-6 integers', 'Ctrl+1', '^1', sub { insert_random(1) } ], # ^1 is short for km::Ctrl | ord('1') [ '7-11 integers', 'Ctrl+2', '^2', sub { insert_random(2) } ], ] ], [ '~Statistics' => [ [ 'Min', 'Alt+1', km::Alt | ord('1'), sub { min() } ], [ 'Max', 'Alt+2', km::Alt | ord('2'), sub { max() } ], [ 'Range', 'Alt+3', km::Alt | ord('3'), sub { range() } ], [ 'Sum', 'Alt+4', km::Alt | ord('4'), sub { sum() } ], [ 'Mean', 'Alt+5', km::Alt | ord('5'), sub { mean() } ], [ 'Median', 'Alt+6', km::Alt | ord('6'), sub { median() } ], [ 'Standard deviation', 'Alt+7', km::Alt | ord('7'), sub { standard_deviation() } ], ] ], [],# divisor in main menu: menuitem Help is now at the right [ '~Help' => [ [ 'Short cuts' => sub { mcMessage(300, 300, "Short cuts", "Insert integers\n2-6 integers: Ctrl+1\n7-11 integers: Ctrl+2\n\nStatistics\nMin: Alt+1\nMax: Alt+2\nRange: Alt+3\nSum: Alt+4\nAverage: Alt+5\nMedian: Alt+6\nStandard deviation: Alt+7"); } ], [],# divisor line [ 'About' => sub { mcMessage(300, 125, "About", "This is a demo application about menus\nin Prima - a perl graphic toolkit");}], ] ], ], ); $mw-> insert( "Label", pack => { pad => 20, fill => 'none' }, text => "Enter integers, separated by a space (or use Insert) and select your Statistics formula:", valignment => ta::Center, ); $in = $mw-> insert( "InputLine", pack => { pady => 20, padx => 20, fill => 'both'}, }, text => "", valignment => ta::Center, size => [500, 30], autoHeight => 1,# blink signals invalid input by setting background to red color; set for your own color the property backColor in blink, e.g. blink(backColor=>0xFF00FF) onChange => sub { $out-> set(text => ""); $in-> blink if($in-> text !~ (/^[0-9 ]+$/));} popupItems => [],# for now, we disable the right mouseclick ); $out = $mw-> insert( "Label", pack => { pad => 20, fill => 'none' }, text => "", font => { size => 14, }, valignment => ta::Center, ); sub insert_random { $category = shift; if ($category == 1) { $number_of_integers = 2 + int(rand((6 + 1) - 2));# 2-6 random numbers } else { $number_of_integers = 7 + int(rand((11 + 1) - 7));# 7-11 random numbers } $integer_string = ""; for ($i = 0; $i < $number_of_integers; $i++) { $integer_string = $integer_string . int(rand(100)) . " ";# integers between 0 - 100 (exclusive) } chop($integer_string); $in-> set(text => $integer_string); $in-> autoSelect(0); # no text is selected $in -> charOffset(length($integer_string));# cursor at the end } sub validate { $data = shift; $data =~ s/\h+/ /g; if($data =~ (/^[0-9 ]+$/) and (length($data) > 2) ) {# minimal two integers and a space, i.e. 1 2 return $data; } else { $in -> blink; return 0; } } sub min { if ($data = validate($in->text)) { @numbers = sort { $a <=> $b } split(" ", $data); $out-> set(text => "Lowest number: " . $numbers[0]); } } sub max { if ($data = validate($in->text)) { @numbers = sort { $a <=> $b } split(" ", $data); $out-> set(text => "Highest number: " . $numbers[$#numbers]); } } sub range { if ($data = validate($in->text)) { @numbers = sort { $a <=> $b } split(" ", $data); $out-> set(text => "Range: " . ($numbers[$#numbers] - $numbers[0])); } } sub sum { if ($data = validate($in->text)) { $sum = 0; @numbers = split(" ", $data); foreach (@numbers) { $sum = $sum + $_; } $out-> set(text => "Sum: " . $sum); } } sub mean { if ($data = validate($in->text)) { $sum = 0; @numbers = split(" ", $data); foreach (@numbers) { $sum = $sum + $_; } $mean = $sum/(scalar(@numbers)); $out-> set(text => "mean: " . $mean); } } sub median { if ($data = validate($in->text)) { @numbers = sort { $a <=> $b } split(" ", $data); $len_array = (scalar(@numbers)); if ($len_array % 2) { $median = $numbers[($len_array+1)/2 - 1]; } else { $median = ($numbers[($len_array)/2 - 1] + $numbers[($len_array)/2])/2; } $out-> set(text => "Median: " . $median); } } sub standard_deviation { if ($data = validate($in->text)) {# first: find mean $sum = 0; @numbers = split(" ", $data); foreach (@numbers) { $sum = $sum + $_; } $mean_1 = $sum/(scalar(@numbers));# second: find second mean (variance): sum of squared differences between each number and the first mean, divided by the number of integers $sum = 0; foreach (@numbers) { $sum = $sum + (($_ - $mean_1)**2); } $mean_2 = $sum/((scalar(@numbers)) - 1);# minus 1 -> formula for sample (not a population) # third: the standard deviation is the square root of the second mean $standard_dev = sprintf("%.2f", sqrt($mean_2));# format the resultto 2 decimal places $out-> set(text => "Standard deviation: " . $standard_dev); } } $in->focused(1);# cursor shown in inputline run Prima;