1pod::Prima::tutorial(3)User Contributed Perl Documentatiopnod::Prima::tutorial(3)
2
3
4

NAME

6       Prima::tutorial - introductory tutorial
7

DESCRIPTION

9       Programming graphic interfaces is often considered a somewhat boring
10       business, and not without a cause. It is a small pride in knowing that
11       your buttons and scrollbars work exactly as millions of others buttons
12       and scrollbars do, so whichever GUI toolkit is chosen, it is usually
13       regarded as a tool of small importance, and the less obtrusive, the
14       better. Given that, and trying to live up to the famous Perl 'making
15       easy things easy and hard things possible' mantra, this manual page is
16       an introductory tutorial meant to show how to write easy things easy.
17       The hard things are explained in the other Prima manual pages ( see
18       Prima ).
19

Introduction - a "Hello world" program

21       Prima is written and is expected to be used in some traditions of Perl
22       coding, such as DWIM ( do what I mean ) or TMTOWTDI ( there are more
23       than one way to do it).  Perl itself is language (arguably) most
24       effective in small programs, as the programmer doesn't need to include
25       lines and lines of prerequisite code before even getting to the problem
26       itself. Prima can't compete with that, but the introductory fee is low;
27       a minimal working 'Hello world' can be written in three lines of code:
28
29               use Prima qw(Application);
30               Prima::MainWindow-> new( text => 'Hello world!');
31               run Prima;
32
33       Line 1 here is the invocation of modules Prima and Prima::Application.
34       Sure, one can explicitly invoke both "use Prima" and "use
35       Prima::Application" etc etc, but as module Prima doesn't export method
36       names, the exemplified syntax is well-suited for such a compression.
37
38       Line 2 creates a window of Prima::MainWindow class, which is visualized
39       as a screen window, titled as 'Hello world'. The class terminates the
40       application when the window is closed; this is the only difference from
41       'Window' windows, that do nothing after their closing. From here,
42       "Prima::" prefix in class names will be omitted, and will be used only
43       when necessary, such as in code examples.
44
45       Line 3 enters the Prima event loop. The loop is terminated when the
46       only instance of Application class, created by "use Prima::Application"
47       invocation and stored in $::application scalar, is destroyed.
48
49       Strictly speaking, a minimal 'hello world' program can be written even
50       in two lines:
51
52               use Prima;
53               Prima::message('Hello world');
54
55       but it is not illustrative and not useful. "Prima::message" is rarely
56       used, and is one of few methods contained in "Prima::" namespace. To
57       display a message, the MsgBox module is often preferred, with its
58       control over message buttons and pre-defined icons. With its use, the
59       code above can be rewritten as
60
61               use Prima qw(Application MsgBox);
62               message('Hello world');
63
64       but where "Prima::message" accepts the only text scalar parameters,
65       "Prima::MsgBox::message" can do lot more. For example
66
67               use Prima qw(Application MsgBox);
68               message('Hello world', mb::OkCancel|mb::Information);
69
70       displays two buttons and an icon. A small achievement, but the
71       following is a bit more interesting:
72
73               use Prima qw(Application MsgBox);
74               message('Hello world', mb::OkCancel|mb::Information,
75                       buttons => {
76                               mb::Cancel => {
77                                       # there are predefined color constants to use
78                                       backColor => cl::LightGreen,
79                                       # but RGB integers are also o.k.
80                                       color     => 0xFFFFFF,
81                               },
82                               mb::Ok => {
83                                       text    => 'Indeed',
84                               },
85                       }
86               );
87
88       The definition of many object properties at once is a major feature of
89       Prima, and is seen throughout the toolkit. Returning back to the very
90       first example, we can demonstrate the manipulation of the window
91       properties in the same fashion:
92
93               use Prima qw(Application);
94               my $window = Prima::MainWindow-> new(
95                       text => 'Hello world!',
96                       backColor => cl::Yellow,
97                       size => [ 200, 200],
98               );
99               run Prima;
100
101       Note that the "size" property is a two-integer array, and color
102       constant is registered in "cl::" namespace. In Prima there is a number
103       of such two- and three-letter namespaces, containing usually integer
104       constants for various purposes. The design reason for choosing such
105       syntax over string constants ( as in Perl-Tk, such as "color =>
106       'yellow'" ) is that the syntax is checked on the compilation stage,
107       thus narrowing the possibility of a bug.
108
109       There are over a hundred properties, such as color, text, or size,
110       defined on descendants of Widget class. These can be set in "new" (
111       alias "create" ) call, or referred later, either individually
112
113               $window-> size( 300, 150);
114
115       or in a group
116
117               $window-> set(
118                       text => 'Hello again',
119                       color => cl::Black,
120               );
121
122       In addition to these, there are also more than 30 events, called
123       whenever a certain action is performed; the events have syntax
124       identical to the properties. Changing the code again, we can catch a
125       mouse click on the window:
126
127               use Prima qw(Application MsgBox);
128               my $window = Prima::MainWindow-> new(
129                       text => 'Hello world!',
130                       size => [ 200, 200],
131                       onMouseDown => sub {
132                               my ( $self, $button, $mod, $x, $y) = @_;
133                               message("Aww! You've clicked me right in $x:$y!");
134                       },
135               );
136               run Prima;
137
138       While an interesting concept, it is not really practical if the only
139       thing you want is to catch a click, and this is the part where a
140       standard button probably should be preferred:
141
142               use Prima qw(Application Buttons MsgBox);
143               my $window = Prima::MainWindow-> new(
144                       text     => 'Hello world!',
145                       size     => [ 200, 200],
146               );
147               $window-> insert( Button =>
148                       text     => 'Click me',
149                       growMode => gm::Center,
150                       onClick  => sub { message("Hello!") }
151               );
152               run Prima;
153
154       For those who know Perl-Tk and prefer its ways to position a widget,
155       Prima provides pack and place interfaces. Here one can replace the line
156
157               growMode => gm::Center,
158
159       to
160
161               pack     => { expand => 1 },
162
163       with exactly the same effect.
164

Widgets overview

166       Prima contains a set of standard ( in GUI terms ) widgets, such as
167       buttons, input lines, list boxes, scroll bars, etc etc. These are
168       diluted with the other more exotic widgets, such as POD viewer or
169       docking windows. Technically, these are collected in "Prima/*.pm"
170       modules and each contains its own manual page, but for informational
171       reasons here is the table of these, an excerpt of "Prima" manpage:
172
173       Prima::Buttons - buttons and button grouping widgets
174
175       Prima::Calendar - calendar widget
176
177       Prima::ComboBox - combo box widget
178
179       Prima::DetailedList - multi-column list viewer with controlling header
180       widget
181
182       Prima::DetailedOutline - a multi-column outline viewer with controlling
183       header widget
184
185       Prima::DockManager - advanced dockable widgets
186
187       Prima::Docks - dockable widgets
188
189       Prima::Edit - text editor widget
190
191       Prima::ExtLists - listbox with checkboxes
192
193       Prima::FrameSet - frameset widget class
194
195       Prima::Grids - grid widgets
196
197       Prima::Widget::Header - multi-column header widget
198
199       Prima::ImageViewer - bitmap viewer
200
201       Prima::InputLine - input line widget
202
203       Prima::Label - static text widget
204
205       Prima::Lists - user-selectable item list widgets
206
207       Prima::MDI - top-level windows emulation classes
208
209       Prima::Notebooks - multipage widgets
210
211       Prima::Outlines - tree view widgets
212
213       Prima::PodView - POD browser widget
214
215       Prima::ScrollBar - scroll bars
216
217       Prima::Sliders - sliding bars, spin buttons and input lines, dial
218       widget etc.
219
220       Prima::TextView - rich text browser widget
221

Building a menu

223       In Prima, a tree-like menu is built by passing a nested set of arrays,
224       where each array corresponds to a single menu entry. Such as, to modify
225       the hello-world program to contain a simple menu, it is enough to write
226       this:
227
228               use Prima qw(Application MsgBox);
229               my $window = Prima::MainWindow-> new(
230                       text => 'Hello world!',
231                       menuItems => [
232                               [ '~File' => [
233                                       ['~Open', 'Ctrl+O', '^O', sub { message('open!') }],
234                                       ['~Save as...', sub { message('save as!') }],
235                                       [],
236                                       ['~Exit', 'Alt+X', km::Alt | ord('x'), sub { shift-> close } ],
237                               ]],
238                       ],
239               );
240               run Prima;
241
242       Each of five arrays here in the example is written using different
243       semantics, to represent either a text menu item, a sub-menu entry, or a
244       menu separator. Strictly speaking, menus can also display images, but
245       that syntax is practically identical to the text item syntax.
246
247       The idea behind all this complexity is to be able to tell what exactly
248       the menu item is, just by looking at the number of items in each array.
249       So, zero or one items are treated as a menu separator:
250
251               [],
252               [ 'my_separator' ]
253
254       The one-item syntax is needed when the separator menu item need to be
255       later addressed explicitly. This means that each menu item after it is
256       created is assigned a (unique) identifier, and that identifier looks
257       like '#1', '#2', etc, unless it is given by the programmer. Here, for
258       example, it is possible to delete the separator, after the menu is
259       created:
260
261               $window-> menu-> remove('my_separator');
262
263       It is also possible to assign the identifier to any menu item, not just
264       to a separator.  The other types (text,image,sub-menu) are discerned by
265       looking at the type of scalars they contain. Thus, a two-item array
266       with the last item an array reference (or, as before, three-item for
267       the explicit ID set), is clearly a sub-menu. The reference, as in the
268       example, may contain more menu items, in the recursive fashion:
269
270                       menuItems => [
271                               [ '~File' => [
272                                       [ '~Level1' => [
273                                               [ '~Level2' => [
274                                                       [ '~Level3' => [
275                                                               []
276                                                       ]],
277                                               ]],
278                                       ]],
279                               ]],
280                       ],
281
282       Finally, text items, with the most complex syntax, can be constructed
283       with three to six items in the array. There can be set the left-aligned
284       text string for the item, the right-aligned text string for the display
285       of the hot key, if any, the definition of the hot key itself, and the
286       action to be taken if the user has pressed either the menu item or the
287       hot key combination. Also, as in the previous cases, the explicit ID
288       can be set, and also an arbitrary data scalar, for generic needs. This
289       said, the text item combinations are:
290
291       Three items - [ ID, text, action ]
292
293       Four items - [ text, hot key text, hot key, action ]
294
295       Five items - [ ID, text, hot key text, hot key, action ]
296
297       Six items - [ ID, text, hot key text, hot key, action, data ]
298
299       Image items are fully analogous to the text items, except that instead
300       of the text string, an image object is supplied:
301
302               use Prima qw(Application MsgBox);
303               use Prima::Utils qw(find_image);
304
305               my $i = Prima::Image-> load( find_image( 'examples/Hand.gif'));
306               $i ||= 'No image found or can be loaded';
307
308               my $window = Prima::MainWindow-> new(
309                       text => 'Hello world!',
310                       menuItems => [
311                               [ '~File' => [
312                                       [ $i, sub {} ],
313                               ]],
314                       ],
315               );
316               run Prima;
317
318       The action item of them menu description array points to the code
319       executed when the menu item is selected.  It is either an anonymous
320       subroutine, as it is shown in all the examples above, or a string.  The
321       latter case will cause the method of the menu owner ( in this example,
322       the window ) to be called. This can be useful when constructing a
323       generic class with menu actions that can be overridden:
324
325               use Prima qw(Application);
326
327               package MyWindow;
328               use vars qw(@ISA);
329               @ISA = qw(Prima::MainWindow);
330
331               sub action
332               {
333                       my ( $self, $menu_item) = @_;
334                       print "hey! $menu_item called me!\n"
335               }
336
337               my $window = MyWindow-> new(
338                       menuItems => [
339                               [ '~File' => [
340                                       ['~Action', q(action) ],
341                               ]],
342                       ],
343               );
344
345               run Prima;
346
347       All actions are called with the menu item identifier passed in as a
348       string parameter.
349
350       Another trick is to define a hot key. While its description can be
351       arbitrary, and will be displayed as is, the hot key definition can be
352       constructed in two ways. It is either a literal such as "^A" for
353       Control+A, or @B for Alt+B, or "^@#F10" for Control+Alt+Shift+F10. Or,
354       alternatively, it is a combination of "km::" constants either with
355       ordinal of the character letter or the key code, where the key code is
356       one of "kb::" constants. The latter method produces a less readable
357       code, but is more explicit and powerful:
358
359               [ '~Reboot', 'Ctrl+Alt+Delete', km::Alt | km::Ctrl | kb::Delete, sub {
360                       print "wow!\n";
361               }],
362               [ '~Or not reboot?', 'Ctrl+Alt+R', km::Alt | km::Ctrl | ord('r'), sub {}],
363
364       This concludes the short tutorial on menus. To read more, see
365       Prima::Menu .
366

Adding help to your program

368       The toolkit comes with a POD viewer program "podview" that can be
369       incorporated into an application. This is rather straightforward as you
370       can write the application manual in POD format.
371
372       •   First, add some pod content to your main script, such as f ex:
373
374              #!/usr/bin/env perl
375              ...
376              =pod
377
378              =head1 NAME
379
380              My program
381
382              =cut
383
384           exactly as if you wanted "perldoc" to display it.
385
386       •   Second, add an invocation code, possibly inside a menu:
387
388                   ['~Help' => 'F1' => 'F1' => sub {
389                           $::application-> open_help("file://$0|DESCRIPTION");
390                   }],
391
392           "open_help" can also take a standard "L<link>" syntax so for
393           example
394
395              open_help("My::Module/help")
396
397           is also okay.
398
399       •   Finally, consider if text-only POD is okay for you or you need
400           images embedded in the pod.  This is somewhat tricky because the
401           perl maintainers actively reject the idea of having images in pod,
402           however metacpan.org can display images in the perl documentation
403           alright, and so does Prima, however both use different syntax.
404
405           Here is an example of a mixed content that will show graphic when
406           the graphic display is available, and just plain text otherwise:
407
408              =for podview <img src="illustration.gif" cut=1 title="Horizontal font measurements">
409
410              =for html <p>
411              <figure>
412              <img src="https://raw.githubusercontent.com/dk/Prima/master/pod/Prima/leadings.gif">
413              <figcaption>Horizontal font measurements</figcaption>
414              </figure>
415              <!--
416
417                 .. plain text illustration ..
418
419              =for html -->
420
421              =for podview </cut>
422
423           GIF is chosen because Prima keeps all of its internal images into
424           this format, so it is a most safe fallback.  However any other
425           format is okay too.
426
427           If you don't need a text fallback, just just this:
428
429             =for podview <img src="illustration.gif">
430
431             =for html <p><img src="https://raw.githubusercontent.com/me/myproject/master/illustration.gif">
432

AUTHOR

434       Dmitry Karasik, <dmitry@karasik.eu.org>.
435

SEE ALSO

437       Prima
438
439
440
441perl v5.38.0                      2023-07-21           pod::Prima::tutorial(3)
Impressum