Skip to content

J-ottings 12

Vector 13:3, page 29

education user interfaces

Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 29

And now for something totally different! Previous J-ottings have been about language matters; this one aims to provide an easy introductory tutorial for windows programming as provided in freeware J. Although this is fully documented in the User Manual, the first-time reader may well find that the complexity of detail there is somewhat daunting, thereby disguising the underlying broad ideas. Taken a step at a time, these are not as formidable as they look at first sight.

The primary assumptions are that the system-supplied profile.js has been run, and that the reader wishes to pass a J application to third party users through mechanisms like dialog boxes, list boxes and so on, with which computer users nowadays are all intuitively familiar. A supplied script called wp.js supplies seventeen examples of these, and running this script (choose Run Window from the Tool Bar, then run '' from the execution window, pressing <Esc> after each window is displayed) gives a comprehensive demonstration of the facilities available, thereby obviating the need to fill many column inches here with bitmap illustrations. The script wp.js on my system is in \examples\archive and can itself be used as a tutorial. What follows here is an even more elementary description of the ground rules.

Windows programming in J is about passing seemingly arcane operating-system-like commands to a processor called the Windows Driver (wd for short). Although you still use J verbs, do not expect to find the sort of unities, subtleties, and expressive succinctness which make the J language, as with APL before it, such a source of programming delight.

First, it is important to have a feeling for the basic concepts of object-oriented programming such as parent, child, class and inheritance. Specifically, a bounding window is a parent, and subsidiary items within it, such as buttons and listboxes, are its children.

A simple requirement might be to have the user press one of a set of buttons. Relevant wd commands must cause first the display of the intended buttons, and secondly the detection of whichever button the user eventually presses. Commands to wd, which is just the verb 11!:0, are passed in the form of character strings in which blanks are delimiters. The command

   wd 'pc a;'

means ‘parent create’ with title ‘a’. All commands to wd are terminated by ;, and several may be included in one string, so that

   wd 'pc a;pshow;'

both creates a parent window and causes it to be displayed. If you can, do this now, and experience what may be your first encounter with the world of windows programming.

Suppose now that an application is to have two buttons marked FRESH and FROZEN, and that the user is to press just one of them. wd works in a co-ordinate system in which 4 units in the horizontal direction equals one character width, and 8 units in the vertical direction equals one character height. The next pair of commands are xywh (standing for x and y distances from top left, width, height) and cc (child create) which position and label the first button:

wd 'xywh 20 10 40 12;cc FRESH button;'

Assuming that the second button is to appear vertically below the first, its wd command can be consolidated with the others so far in a defined noun (character matrix):

   push=.0 : 0
pc a;pshow;
xywh 20 10 40 12;cc FRESH button;
xywh 20 30 40 12;cc FROZEN button;
)

The verb wd can accept a table as an argument, and so

   wd push       NB. No ';' since push is the argument of verb wd

causes the window to appear, ready for user input. To receive and interpret this input, you must use wait;. This command passes control to the user, following whose actions an n by 2 table is returned. The crucial information, that is the name of the button which was pressed, is in the second column of the third row. Once this is safely stored, say in a global variable RES, the window can be erased using the pclose; (parent close), or alternatively all windows can be closed by reset;. The actions described in this paragraph can be consolidated in a verb:

   runpush=.3 : 0
wd push
RES=:>(<2 1){wd 'wait;' NB.(<2 1) indexes the 2nd column of the 3rd row
wd 'pclose;'
)

Type runpush'', press the button of your choice, and the result string is stored in RES to await whatever processing follows.

This may not seem very appealing programming, but if you have followed the above successfully you will have mastered the essentials of using wd — everything else is a matter of absorbing more detail. The remaining examples use the same principle of defining a noun to set up a window, followed by a verb which applies wd to it. After running the window, the verb goes on to extract the required information. The general syntax of the cc command is :

   cc  name class style ;

There are ten class types of which the one investigated so far is button. Button has two other variations, check box and radio button. An appropriate noun/verb pair for two check boxes is:

   check=.0 : 0
pc a;pshow;
xywh 20 10 40 12;cc b1 button bs_autocheckbox;
                              NB. bs_autocheckbox is a style
xywh 20 30 40 12;cc b2 button bs_autocheckbox;
)

 runcheck=.3 : 0
wd check
RES=:4}.wd 'wait;'      NB. Results (button names plus 0/1 for nocheck/check) are in
wd 'pclose;'            NB. the final rows (all but the first 4) of the n by 2 table
)

Instead of repeating the lengthy parameter in the third line of check, it is possible to use cci , standing for create child and inherit, that is inherit from the last cc . Also computer users will be familiar with the way in which check buttons can be grouped in an encompassing box. Putting these two ideas together leads to the following revision of check:

   group=.0 : 0
pc a;pshow;
xywh 5 2 60 50;cc bgroup button bs_groupbox;
    NB. bgroup is the name of the group box
xywh 20 10 40 12;cc b1 button bs_autocheckbox;
    NB. b1 and b2 are the button names
xywh 20 30 40 12;cci b2 group;
    NB. bs_autocheckbox is a style
)

  rungroup=.3 : 0
wd group
RES=:4}.wd 'wait;'
wd 'pclose;'
)

Radio buttons differ from check boxes only in style. The example below demonstrates another feature, namely setting the initial state of one of the buttons to ‘on’ using csel standing for ‘child select’:

   radios=.0 : 0
pc a;pshow;
xywh 20 10 40 12; cc b1 button bs_autoradiobutton;
xywh 20 30 40 12; cci b2 group; csel b2 ccheck 1;
)

 runradios=.3 : 0
wd check
RES=:4}.wd 'wait;'
wd 'reset;'
)

The second window class is listbox. In principle, just one new command is needed, namely ctext which writes strings into the box. However Carriage Returns, which include spaces, are needed to separate list box lines, whereas spaces are already used to separate tokens in the wd command string. This is dealt with by bracketing the list box items within instances of EAV=. 255{a. (the last character in the atomic vector) as shown in the noun/verb pair below:

  list=.0 : 0
pc a;pshow;

xywh 20 10 40 30;cc list1 listbox ws_vscroll;  NB. style is Vertical Scroll
)
 wdctext=.('ctext ',EAV)&,@(,&(EAV,';'))    NB. Verb to add bracketing EAVs

   runlist=.3 : 0
t=.;('france';'germany';'italy';'spain'),&.>CR
                                NB. List box lines, each followed
wd list                         NB. CR=Carriage Return
wd wdctext t                    NB. Use wdctext to build ctext command
RES=:>(<4 1){wd 'wait;'         NB. Result is in 2nd column of 5th row
wd 'reset;'
)

The third class of window is editbox. This is similar in principle to listbox, except that the result is the (possibly edited) contents of the box. Several style parameters are used.

   edbox=.0 : 0
pc a;pshow;
xywh 20 10 50 70;cc e1 edit es_multiline ws_vscroll ws_hscroll ws_border;
)

   runedbox=.3 : 0
t=.'france';'is an';'interesting sort of';'country'
wd edbox
wd wdctext ;t,&.>CR
RES=:>(<4 1){wd 'wait;'
wd 'reset;'
)

Change, say, est to fer, and the result is the listbox text with this edit carried out.

The fourth class is combobox which allows any combination of the previous three to appear within one window. The fifth is scrollbar in which the user controls a slider, which may be horizontal or vertical, and the result is its one-dimensional co-ordinate when the user releases the mouse button. The arguments of ctext have a different meaning in the context of scrollbar; they are respectively the left position of the slider, the current position, the right position and the number of scaled units per click.

The sixth class is static which allows descriptive text to appear within a window using the command cn (child name). These last two classes are illustrated in the following noun/verb pair:

   sbar=.0 : 0
pc a;pshow;
xywh 10 10 80 12;cc s1 static;cn "Slider";  NB. Double quotes delimit text
xywh 10 30 80 12;cc s2 scrollbar;ctext 0 250 1000 25;
                                            NB. See note above on ctext
)

   runsbar=.3 : 0
wd sbar
RES=:4}.wd 'wait;'
wd 'pclose;'
)

Full details of all the classes and their parameters are given in Help/User Manual/8 Window Controls/Child Classes. Thus equipped, it is a simple matter to move to the next two classes isigraph and isipicture.

Taking the latter first, the following two examples should be an adequate demonstration:

   wd 'pc picture; cc p isipicture; ctext j2y.ico;pshow;'
   wd 'pc picture; cc p isipicture;
           ctext examples\data\ship.bmp; pshow;'

The bitmap ship.bmp is supplied with the J2 system.

Now try some graphs. Two new commands are grgb which defines a colour in terms of its red, blue and green constituents, each of which contributes on a scale of 0-255. gpen gives the line thickness and style respectively, and grect defines the rectangle whose diagonal points are (100,200) and (500,700). The effect of the second line is to display this rectangle in a window co-ordinate system whose ranges are from 0 to 1000 along each axis.

   graph=.0 : 0
pc graph; cc g isigraph; grgb 200 150 0; gpen 1 ps_dot;
     grect 100 200 500 700;
gshow; pshow;
)

   rungraph=.3 : 0
wd graph
wd 'pclose;'
)

Now enrich the graph noun by stages, a line at a time. The second line below draws an ellipse within the rectangular framework defined by the co-ordinates. The third changes the drawing colour to pure red, and draws the chord and arc of the ellipse which is cut off by the line joining the points (100,600) and (500,400).

  graph=.0 : 0
pc graph; cc g isigraph; grgb 200 150 0; gpen 1 ps_dot; grect 100 200 500 700;
grgb 0 200 200; gpen 50; gellipse 120 220 480 680;
grgb 255 0 0; gpen 10; gchord 120 220 480 680 100 600 500 400;
gshow; pshow;
)

   rungraph=.3 : 0
wd graph
wd 'pclose;'
)

Of course, there is much, much more by way of graphics possibility, which you are now in a position to explore by referring to the wd Commands section of the online manual, or by issuing either User Manual/Window Driver, or User Manual WD Reference. To complete the picture, the ninth and tenth classes relate to the more sophisticated areas of OLE and VBX extensions.

Tool bars and their associated drop-down menus are generated in the following way:

   menu=.0 : 0
pco a;pshow;
menupop "&File";                 NB. One menupop per Toolbar entry
menu open "&Open"; menusep;      NB. Two dropdown items, Open and Save
menu save "&Save";  menupopz;    NB. menupopz matches menupop
)

   runmenu=.3 : 0
wd menu
RES=:>(<2 1){wd 'wait;'
wd 'reset;'
)

Message boxes are in some ways the easiest windows of all to generate, for example:

   wd 'mb mess1 hello mb_ok;'

There is no requirement to generate a parent, and mb replaces cc as the command. The cc syntax applies to mb, so that mess1 above is the name of the message box. Ten essentially different styles are available of which mb_ok is the simplest, that is the message box contains a single button marked OK, pressing which closes the window. There is no requirement for an explicit pclose; or reset;. Five other button combinations are available, namely mb_okcancel, mb_retrycancel, mb_yesno, mb_yesnocancel and mb_abortretryignore. Four possibilities with icons are available, namely mb_iconinformation, mb_iconexclamation, mb_question, and mb_iconstop. An even simpler way to deliver a message is to use the verb wdinfo which is available as a result of running the standard profile. This uses the mb_iconinformation, using the character string right argument to wdinfo.