.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "pod::Prima::tutorial 3" .TH pod::Prima::tutorial 3 "2009-02-24" "perl v5.14.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Prima::tutorial \- introductory tutorial .SH "DESCRIPTION" .IX Header "DESCRIPTION" Programming graphic interfaces is often considered somewhat boring, and not without a cause. It is a small pride in knowing that your buttons and scrollbars work exactly as millions of others buttons and scrollbars do, so whichever \s-1GUI\s0 toolkit is chosen, it is usually regarded as a tool of small importance, and the less obtrusive, the better. Given that, and trying to live up to the famous Perl 'making easy things easy and hard things possible' mantra, this manual page is an introductory tutorial meant to show how to write easy things easy. The hard things are explained in the other Prima manual pages ( see Prima ). .ie n .SH "Introduction \- a ""Hello world"" program" .el .SH "Introduction \- a ``Hello world'' program" .IX Header "Introduction - a Hello world program" Prima is written and is expected to be used in some traditions of Perl coding, such as \s-1DWIM\s0 ( do what I mean ) or \s-1TMTOWTDI\s0 ( there are more than one way to do it). Perl itself is language (arguably) most effective in small programs, as the programmer doesn't need to include lines and lines of prerequisite code before even getting to the problem itself. Prima can't compete with that, but the introductory fee is low; a minimal working 'Hello world' can be written in three lines of code: .PP .Vb 3 \& use Prima qw(Application); \& Prima::MainWindow\-> new( text => \*(AqHello world!\*(Aq); \& run Prima; .Ve .PP Line 1 here is the invocation of modules \fIPrima\fR and \fIPrima::Application\fR. Sure, one can explicitly invoke both \f(CW\*(C`use Prima\*(C'\fR and \f(CW\*(C`use Prima::Application\*(C'\fR etc etc, but as module Prima doesn't export method names, the exemplified syntax is well-suited for such a compression. .PP Line 2 creates a window of \fIPrima::MainWindow\fR class, which is visualized as a screen window, titled as 'Hello world'. The class terminates the application when the window is closed; this is the only difference from 'Window' windows, that do nothing after their closing. From here, \f(CW\*(C`Prima::\*(C'\fR prefix in class names will be omitted, and will be used only when necessary, such as in code examples. .PP Line 3 enters the Prima event loop. The loop is terminated when the only instance of \fIApplication\fR class, created by \f(CW\*(C`use Prima::Application\*(C'\fR invocation and stored in \f(CW$::application\fR scalar, is destroyed. .PP Strictly speaking, a minimal 'hello world' program can be written even in two lines: .PP .Vb 2 \& use Prima; \& Prima::message(\*(AqHello world\*(Aq); .Ve .PP but it is not illustrative and not useful. \f(CW\*(C`Prima::message\*(C'\fR is rarely used, and is one of few methods contained in \f(CW\*(C`Prima::\*(C'\fR namespace. To display a message, the \fIMsgBox\fR module is often preferred, with its control over message buttons and pre-defined icons. With its use, the code above can be rewritten as .PP .Vb 2 \& use Prima qw(Application MsgBox); \& message(\*(AqHello world\*(Aq); .Ve .PP but where \f(CW\*(C`Prima::message\*(C'\fR accepts the only text scalar parameters, \f(CW\*(C`Prima::MsgBox::message\*(C'\fR can do lot more. For example .PP .Vb 2 \& use Prima qw(Application MsgBox); \& message(\*(AqHello world\*(Aq, mb::OkCancel|mb::Information); .Ve .PP displays two buttons and an icon. A small achievement, but the following is a bit more interesting: .PP .Vb 10 \& use Prima qw(Application MsgBox); \& message(\*(AqHello world\*(Aq, mb::OkCancel|mb::Information, \& buttons => { \& mb::Cancel => { \& # there are predefined color constants to use \& backColor => cl::LightGreen, \& # but RGB integers are also o.k. \& color => 0xFFFFFF, \& }, \& mb::Ok => { \& text => \*(AqIndeed\*(Aq, \& }, \& } \& ); .Ve .PP The definition of many object properties at once is a major feature of Prima, and is seen throughout the toolkit. Returning back to the very first example, we can demonstrate the manipulation of the window properties in the same fashion: .PP .Vb 7 \& use Prima qw(Application); \& my $window = Prima::MainWindow\-> new( \& text => \*(AqHello world!\*(Aq, \& backColor => cl::Yellow, \& size => [ 200, 200], \& ); \& run Prima; .Ve .PP Note that the \f(CW\*(C`size\*(C'\fR property is a two-integer array, and color constant is registered in \f(CW\*(C`cl::\*(C'\fR namespace. In Prima there is a number of such two\- and three-letter namespaces, containing usually integer constants for various purposes. The design reason for choosing such syntax over string constants ( as in Perl-Tk, such as \f(CW\*(C`color => \*(Aqyellow\*(Aq\*(C'\fR ) is that the syntax is checked on the compilation stage, thus narrowing the possibility of a bug. .PP There are over a hundred properties, such as color, text, or size, defined on descendants of \fIWidget\fR class. These can be set in \f(CW\*(C`new\*(C'\fR ( alias \f(CW\*(C`create\*(C'\fR ) call, or referred later, either individually .PP .Vb 1 \& $window\-> size( 300, 150); .Ve .PP or in a group .PP .Vb 4 \& $window\-> set( \& text => \*(AqHello again\*(Aq, \& color => cl::Black, \& ); .Ve .PP In addition to these, there are also more than 30 events, called whenever a certain action is performed; the events have syntax identical to the properties. Changing the code again, we can catch a mouse click on the window: .PP .Vb 10 \& use Prima qw(Application MsgBox); \& my $window = Prima::MainWindow\-> new( \& text => \*(AqHello world!\*(Aq, \& size => [ 200, 200], \& onMouseDown => sub { \& my ( $self, $button, $mod, $x, $y) = @_; \& message("Aww! You\*(Aqve clicked me right in $x:$y!"); \& }, \& ); \& run Prima; .Ve .PP While an interesting concept, it is not really practical if the only thing you want is to catch a click, and this is the part where a standard button is probably should be preferred: .PP .Vb 11 \& use Prima qw(Application Buttons MsgBox); \& my $window = Prima::MainWindow\-> new( \& text => \*(AqHello world!\*(Aq, \& size => [ 200, 200], \& ); \& $window\-> insert( Button => \& text => \*(AqClick me\*(Aq, \& growMode => gm::Center, \& onClick => sub { message("Hello!") } \& ); \& run Prima; .Ve .PP For those who know Perl-Tk and prefer its ways to position a widget, Prima provides \fIpack\fR and \fIplace\fR interfaces. Here one can replace the line .PP .Vb 1 \& growMode => gm::Center, .Ve .PP to .PP .Vb 1 \& pack => { expand => 1 }, .Ve .PP with exactly the same effect. .SH "Widgets overview" .IX Header "Widgets overview" Prima contains a set of standard ( in \s-1GUI\s0 terms ) widgets, such as buttons, input lines, list boxes, scroll bars, etc etc. These are diluted with the other more exotic widgets, such as \s-1POD\s0 viewer or docking windows. Technically, these are collected in \f(CW\*(C`Prima/*.pm\*(C'\fR modules and each contains its own manual page, but for informational reasons here is the table of these, an excerpt of \f(CW\*(C`Prima\*(C'\fR manpage: .PP Prima::Buttons \- buttons and button grouping widgets .PP Prima::Calendar \- calendar widget .PP Prima::ComboBox \- combo box widget .PP Prima::DetailedList \- multi-column list viewer with controlling header widget .PP Prima::DetailedOutline \- a multi-column outline viewer with controlling header widget .PP Prima::DockManager \- advanced dockable widgets .PP Prima::Docks \- dockable widgets .PP Prima::Edit \- text editor widget .PP Prima::ExtLists \- listbox with checkboxes .PP Prima::FrameSet \- frameset widget class .PP Prima::Grids \- grid widgets .PP Prima::Header \- a multi-tabbed header widget .PP Prima::ImageViewer \- bitmap viewer .PP Prima::InputLine \- input line widget .PP Prima::Label \- static text widget .PP Prima::Lists \- user-selectable item list widgets .PP Prima::MDI \- top-level windows emulation classes .PP Prima::Notebooks \- multipage widgets .PP Prima::Outlines \- tree view widgets .PP Prima::PodView \- \s-1POD\s0 browser widget .PP Prima::ScrollBar \- scroll bars .PP Prima::Sliders \- sliding bars, spin buttons and input lines, dial widget etc. .PP Prima::TextView \- rich text browser widget .SH "Building a menu" .IX Header "Building a menu" In Prima, a tree-like menu is built by passing a nested set of arrays, where each array corresponds to a single menu entry. Such as, to modify the hello-world program to contain a simple menu, it is enough to write this: .PP .Vb 10 \& use Prima qw(Application MsgBox); \& my $window = Prima::MainWindow\-> new( \& text => \*(AqHello world!\*(Aq, \& menuItems => [ \& [ \*(Aq~File\*(Aq => [ \& [\*(Aq~Open\*(Aq, \*(AqCtrl+O\*(Aq, \*(Aq^O\*(Aq, sub { message(\*(Aqopen!\*(Aq) }], \& [\*(Aq~Save as...\*(Aq, sub { message(\*(Aqsave as!\*(Aq) }], \& [], \& [\*(Aq~Exit\*(Aq, \*(AqAlt+X\*(Aq, km::Alt | ord(\*(AqX\*(Aq), sub { shift\-> close } ], \& ]], \& ], \& ); \& run Prima; .Ve .PP Each of five arrays here in the example is written using different semantics, to represent either a text menu item, a sub-menu entry, or a menu separator. Strictly speaking, menus can also display images, but that syntax is practically identical to the text item syntax. .PP The idea behind all this complexity is to be able to tell what exactly the menu item is, just by looking at the number of items in each array. So, zero or one items are treated as a menu separator: .PP .Vb 2 \& [], \& [ \*(Aqmy_separator\*(Aq ] .Ve .PP The one-item syntax is needed when the separator menu item need to be later addressed explicitly. This means that each menu item after it is created is assigned a (unique) identifier, and that identifier looks like \f(CW\*(Aq#1\*(Aq\fR, \f(CW\*(Aq#2\*(Aq\fR, etc, unless it is given by the programmer. Here, for example, it is possible to delete the separator, after the menu is created: .PP .Vb 1 \& $window\-> menu\-> remove(\*(Aqmy_separator\*(Aq); .Ve .PP It is also possible to assign the identifier to any menu item, not just to a separator. The other types (text,image,sub\-menu) are discerned by looking at the type of scalars they contain. Thus, a two-item array with the last item an array reference (or, as before, three-item for the explicit \s-1ID\s0 set), is clearly a sub-menu. The reference, as in the example, may contain more menu items, in the recursive fashion: .PP .Vb 11 \& menuItems => [ \& [ \*(Aq~File\*(Aq => [ \& [ \*(Aq~Level1\*(Aq => [ \& [ \*(Aq~Level2\*(Aq => [ \& [ \*(Aq~Level3\*(Aq => [ \& [] \& ]], \& ]], \& ]], \& ]], \& ], .Ve .PP Finally, text items, with the most complex syntax, can be constructed with three to six items in the array. There can be set the left-aligned text string for the item, the right-aligned text string for the display of the hot key, if any, the definition of the hot hey itself, and the action to be taken if the user has pressed either the menu item or the hot key combination. Also, as in the previous cases, the explicit \s-1ID\s0 can be set, and also an arbitrary data scalar, for generic needs. This said, the text item combinations are: .PP Three items \- [ \s-1ID\s0, text, action ] .PP Four items \- [ text, hot key text, hot key, action ] .PP Five items \- [ \s-1ID\s0, text, hot key text, hot key, action ] .PP Six items \- [ \s-1ID\s0, text, hot key text, hot key, action, data ] .PP Image items are fully analogous to the text items, except that instead of the text string, an image object is supplied: .PP .Vb 2 \& use Prima qw(Application MsgBox); \& use Prima::Utils qw(find_image); \& \& my $i = Prima::Image\-> load( find_image( \*(Aqexamples/Hand.gif\*(Aq)); \& $i ||= \*(AqNo image found or can be loaded\*(Aq; \& \& my $window = Prima::MainWindow\-> new( \& text => \*(AqHello world!\*(Aq, \& menuItems => [ \& [ \*(Aq~File\*(Aq => [ \& [ $i, sub {} ], \& ]], \& ], \& ); \& run Prima; .Ve .PP The action item of them menu description array points to the code executed when the menu item is selected. It is either an anonymous subroutine, as it is shown in all the examples above, or a string. The latter case will cause the method of the menu owner ( in this example, the window ) to be called. This can be useful when constructing a generic class with menu actions that can be overridden: .PP .Vb 1 \& use Prima qw(Application); \& \& package MyWindow; \& use vars qw(@ISA); \& @ISA = qw(Prima::MainWindow); \& \& sub action \& { \& my ( $self, $menu_item) = @_; \& print "hey! $menu_item called me!\en" \& } \& \& my $window = MyWindow\-> new( \& menuItems => [ \& [ \*(Aq~File\*(Aq => [ \& [\*(Aq~Action\*(Aq, q(action) ], \& ]], \& ], \& ); \& \& run Prima; .Ve .PP All actions are called with the menu item identifier passed in as a string parameter. .PP Another trick is to define a hot key. While its description can be arbitrary, and will be displayed as is, the hot key definition can be constructed in two ways. It is either a literal such as \f(CW\*(C`^A\*(C'\fR for Control+A, or \f(CW@B\fR for Alt+B, or \f(CW\*(C`^@#F10\*(C'\fR for Control+Alt+Shift+F10. Or, alternatively, it is a combination of \f(CW\*(C`km::\*(C'\fR constants either with ordinal of the character letter or the key code, where the key code is one of \f(CW\*(C`kb::\*(C'\fR constants. The latter method produces a less readable code, but is more explicit and powerful: .PP .Vb 4 \& [ \*(Aq~Reboot\*(Aq, \*(AqCtrl+Alt+Delete\*(Aq, km::Alt | km::Ctrl | kb::Delete, sub { \& print "wow!\en"; \& }], \& [ \*(Aq~Or not reboot?\*(Aq, \*(AqCtrl+Alt+R\*(Aq, km::Alt | km::Ctrl | ord(\*(AqR\*(Aq), sub {}], .Ve .PP This concludes the short tutorial on menus. To read more, see Prima::Menu . .SH "AUTHOR" .IX Header "AUTHOR" Dmitry Karasik, . .SH "SEE ALSO" .IX Header "SEE ALSO" Prima