User:Andrew Nikitin/buttongrid

From J Wiki
Jump to: navigation, search

ButtonGrid -- command buttons array


Sometimes during J data analysis session, certain commands need to be executed over and over. Notable examples would be pd 'clip', pd 'keypos rti;show', etc. This application allows to assign a j phrase to a command button and execute this phrase (in base locale) with one button click. Download script: buttongrid.ijs

cocurrent 'jzbg'
HELP=:0 : 0


Download script: utilities

controlgrid=:(,~"0/&([: +/\ }:@(0&,)) ,"1 ,~"0/)&,
ltrb=:0 1 _2 _1{(<./ , >./) ,/ (2&{. , [: +/ _2 ]\ ])"1
NB. turn any array of rectangles into a list of rectangles (2d array)
rravel=:(, $~ (*/@}: , {:)@$)

NB. bounding rectangle of the list of rectangles
runion=:[: (<./ ([ , -~) >./) [: ,/ ([: +/\ _2 ]\ ])"1

rexpand=:4 : '((-x)+2{.y),(2*x)+2}.y'
NB. top left point
rnw=:rtl=:2 & {.
NB. bottom right point
rse=:rbr=:[: +/ _2 ]\ ]
NB. top right point
rne=:rtr=:0 2&(+/@:{) , 1&{
NB. bottom left point
rsw=:rbl=:0&{ , 1 3&(+/@:{)
NB. place rectangle identical to y next to y
rxnext=:(+ 2&{ 0} 0">)

require 'regex'
template=:(4 : 0)"1
  m=. '%(\d+)%?' rxmatches x
  i=.(#y) <. (1&{"2 m) ".@>@rxfrom x
  <(i{(":each y),<,'?') (0&{"2 m) rxmerge x
once=: [: ".^:((('=:'&-:)@>@{: *. (0>4!:0)@{.)@(2 {. ;:)) ;._2 ,&LF

These are copied from elsewhere. Most of these verbs manipulate rectangles for programmatic GUI generation. once executes assignment unless the name is already defined.

Actions and Labels

Download script: access

once 'ACTION=:0 0 2$ a:'

Program stores actions and labels in boxed 3d array ACTION. It has shape m×n×2. Each "1 item contains j expression (action) and arbitrary string (label) in that order


Download script: data

NB. --- Default and initial values of configuration parameters

Download script: data

once 'COCREATOR=:<''base'''

The form is executed in its own locale, jzbg. Right now there can only be one command button array per session. I considered making it a class (like plot or adjust), but I never seem to want more than one command button array at a time anyway. Download script: form

bg_makeform=:3 : 0
    wd 'pc ',FID,';pn "ButtonGrid (',(>COCREATOR),')"'
    wd 'pas ',(":2$MARGIN),';pshow'
    BForm=:wd 'qhwndp'
    wd 'pmovex ',":(2{.LASTPOS),2}.".wd 'qformx'

This form should look something like this: Buttongrid-form.png Download script: button_array

    xywh=.<"1 (2$MARGIN) moveby BUTTON,~"1 s*"1 |."1 (#: i.) y
    wd&> 'xywh %0%;cc %1% button;cn "%2%"' template xywh ,"_2 ID ,"_2 get_label ACTION

The main functional component of a form is an array of command buttons. When user clicks on a button, event handler executes j phrase associated with this button. As a feedback the executed phrase is placed into editbox (named worktext in the code). Download script: worktext

    tb=.(0,MARGIN) moveby (rbl , 2&{ , EH"_) runion rravel >xywh
    wd 'xywh ',(":tb),';cc worktext edit es_autohscroll;cn ""'

Download script: shift_switches

    cb0=.(_1 1*MARGIN) moveby (rbl tb), 0,RBH
    cb1r=. 25 (2}) (MARGIN,0) moveby rxnext cb0
    cb2r=. 25 (2}) (MARGIN,0) moveby rxnext cb1r
    cb3r=. 20 (2}) (MARGIN,0) moveby rxnext cb2r
    t=.'xywh %0%;cc %1% radiobutton group;cn "%2%"'
    wd > t template cb1r;'cblabel';'label'
    wd > t template cb2r;'cbview';'view'
    wd > t template cb3r;'cbsetexec';'set'

Radio buttons below the text box work kind of like calculator shift keys. User selects one of the radio buttons and then clicks one of the buttons on the command button array. This will modify appropriate setting for the button or display pertinent information. After this radio button is turned off and command buttons return to their normal "execute j phrase" mode.

  • label -- text from worktext becomes label on a command button
  • view -- j phrase associated with the button is copied into worktext
  • set -- worktext becomes new j phrase associated with a button

Download script: service_switches

    r=.+/0 2{tb
    t=.'xywh %0%;cc %1% checkbox;cn "%2%"'
    wd >t template cbq;'cbq';'&Q'
    wd >t template cbt;'cbt';'&T'

Two checkboxes modify the default behavior of the form. "Quiet" (Q) does not display the expression and its result in .ijx window. "On top" (T) makes form "always on top". They are placed in the same row as shift switches and aligned to the right edge of workbox. If workbox is not wide enough, the 2 areas may overlap. Download script: event_handlers

bg_cbt_button=:3 : 0
  wd 'ptop ',cbt


All defining globals must be set by the time bg_makeform verb is run. They are: Download script: data

once 'BUTTON=:30 30'

Download script: help

button <w> <h> -- change size of a command button

Each command button size. Download script: data

once 'MARGIN=:3'

Download script: help

margin <x> -- change space between buttons

Intervals between buttons and extra space around the entire array. Download script: data

once 'EH=:14'

Download script: help

eh <height> -- height of textbox

Heigh of a textbox where user enters J command or button label. This is a single line textbox. Changing its height makes sense when font is smaller or larger than anticipated. Download script: data

once 'RBH=:12'

Download script: help

rbh <height> -- height of checkboxes and radio buttons

Download script: data

once 'CBW=:15'

Download script: help

cbw <width> -- T and Q checkbox width

Service checkbox width. Should be able to accomodate single character plus checkbox itself.


Download script: command_handlers

bg_cmd=:3 : 0
  'cmd rest'=.y({.~ ; (}.~ >:))y i. ' '
  if. 3=nc :: _1: <'bgc_' (, :: [)cmd do.
    ('bgc_',cmd)~ rest
  elseif. 0=nc :: _1: <toupper cmd do.
    (toupper cmd)=:0".rest

  NB. *** numeric or empty argument -- build as needed and show
  if. ''-:y do. y=.2{.$ACTION end.
  if. 0=*/y do. y=.3 4 end.
  ID=:('b' <@, ":)">i. y

  bg_close ''
  bg_makeform ''
  bgc_show ''

bg_cmd is an interface to entire command button array functionality. It has cover verb bg in z locale for convenience. It does several things.

If input (y) is numeric 2 element vector, it is interpreted as a number of rows and columns in the command button array. bg_cmd resizes internal storage structures for j phrases and button labels, generates necessary GUI elements and assigns id's to them.

If input is empty vector, bg_cmd activates the form with current parameters. If form was accidentally or intentionally closed, empty argument will restore it.

If input is a string, it is considered a command. It is split into first word and rest of the string.

If first word after capitalization becomes one of the internal noun names, te command means "change the name and regenerate form". For example:

bg 'button 40 20'

sets button size noun BUTTON to 40 20 and regenerates form with buttons of this new size.

Otherwise, program looks for a verb named bgc_first-word. If found, program runs this verb and passes the rest of the string as a y parameter.


Download script: command_handlers

bgc_help=:3 : 0
 if. 'r'e. y do.
   NB. list allcaps nouns
   l=.(#~ (-: toupper)&>) nl 0
   NB. list bgc_* named verbs
   l=.l,(#~ ('bgc_' -: 4&{.)&>) nl 3
   list l

Download script: help

help [r] -- list of commands (r -- raw list)

bgc_help is a handler for help command.

There are 2 help modes. Automatically generated help ('r' for raw) shows all bgc_* verbs that may be called by bg_cmd and capitalized nouns that can be changed by bg_cmd. Preformatted help (default) is more human readable, but may be behind.


Download script: command_handlers

bgc_show=:3 : 0
  if. '0' e. y do.
    bg_close ''
      wd 'psel ',FID,';pactive;pshow'
      bg_savepos ''
      bg_makeform ''
    wd 'pmovex ',":(2{.LASTPOS),2}.".wd 'qformx'

Download script: help

show [0] -- show form if it was closed before (hide when 0)


Download script: command_handlers

bgc_save=:3 : 0
s=.(CRLF,~ [ , '=:' , [: 5!:5 <)
  self=.(>(4!:3 ''){~(4!:4 <'bg_save_jzbg_'))
r=. 'require ''',self,'''',CRLF
r=.r,'cocurrent ''',(>coname''),'''',CRLF
r=.r,'bg ''''',CRLF
(1!:2&(<y))^:(-.''-:y) r

Download script: help

save <filename> -- save form configuration to a file including button
        asignments, dimensions and form position. use j `load` command
        to load the saved form.

bg 'save'

generates j script that loads command button array and initializes it with currently set-up parameters, including all sizes, button labels and j phrases attached to them.

bg 'save filename.ijs'

saves this sript to a file so that

load 'filename.ijs'

creates same form again. Download script: data


Script generated by bgc_save needs to load this script first. The location of this script may be specified in PREDEFINEDLOCATION configuration noun. (I made a PUBLIC_j_ alias bg for this script on my system.) If PREDEFINEDLOCATION is left empty, it will attempt to make a guess using 4!:3 and 4!:4 (list of scripts and index in a list of scripts) foreigns.

This variable is intended to be modified in the source code to whatever is appopriate for the specific installation.


Download script: command_handlers

bgc_compact=:3 : 0
wd 'psel ',FID
if. (''-:y) +. 0~: 0".y do.
  wd 'pas ',":MARGIN,-+/EH,MARGIN,RBH
  wd 'pas ',":2#MARGIN

Download script: help

compact [0] -- hide (or show) non-button area of the form

Hide worktext, shift and service switches, leave only buttons visible.

bg 'compact 0'

turns this off and restores service area.


Download script: command_handlers

bgc_exch=:3 : 0
  y=.4({.!._) _".y
  assert. (4=#y) *. *./,_2 (0&<:*.(2{.$ACTION)>])\ y
  i=._2 <\ y
  bg_close ''
  bg_makeform ''

Exchange contents and labels of 2 buttons with given row and column coordinates. Download script: help

exch <row1> <col1> <row2> <col2> -- exchange 2 buttons and specified


Download script: command_handlers

bgc_size=: 3 : 0
bg_cmd 2({.!.1) 1".y

Download script: help

size <rows> <cols> -- change number of buttons, equivalent of `bg rows,cols`

Event handlers

Download script: event_handlers

bg_default=:3 : 0
  if. -.'button'-:'systype' wdget wdq do. return. end.
  ind=.<"1 ($ #: I.@,) (<'syschild' wdget wdq) = ID
  if. 1~:#ind do. return. end.
  NB. --- "shifted" keys (radio buttons) processings
  if. ".cblabel do.
    ACTION=: (<worktext) (ind,&.>1)} ACTION
    wd 'setcaption ',(>ind{ID),' *',worktext
  elseif. ".cbview do.
    wd 'set worktext *',(>ind{get_action ACTION)
  elseif. ".cbsetexec do.
    ACTION=: (<worktext) (ind,&.>0)} ACTION
    if. (ind{get_label ACTION)-:a: do.
      ACTION=: (<worktext) (ind,&.>1)} ACTION
      wd 'setcaption ',(>ind{ID),' *',worktext
  elseif. 1 do.
    exec=.>ind{get_action ACTION
    wd 'set worktext *',exec
  wd 'set cblabel 0'
  wd 'set cbview 0'
  wd 'set cbsetexec 0'
  if. -.''-:exec do.
    r=.do__COCREATOR exec
    if. -. ".cbq do. NB. -.0 0-:$r
      smoutput '   ',exec
      smoutput r

Since the number of buttons is not known beforehand, all processing is performed in default form handler. Events from radio buttons could have been processed separately, but i found it easier to keep everything in one place. Download script: data

once 'LASTPOS=:16 16 0 0'

Download script: event_handlers

bg_savepos=: 3 : 0
  wd 'psel bg'
  LASTPOS=:".wd 'qformx'

Form stores its last know position in LASTPOS noun and tries to keep it up to date at every opportunity. Download script: event_handlers

bg_close=:3 : 0
    bg_savepos ''
  wd 'pclose'

Close event needs to be processed to capture last known position to be able to restore it at next start.


Download script: locale_cover


Cover verb for main command processor placed in z locale to simplify typing. Download script: data

NB. --- end of configuration section
VERSION=:'$Revision: 1.12 $'

See also: adjust.lit

Tips and tricks

A button can be assigned to a command of saving current button configuration to a predefined file:

bg 'save C:\Data\p\ttqtopos\2012-02-08-11p99583\buttons.ijs'

To make a button that makes current window permanent on top, assign:

wd 'ptop 1'

A button to restore normal status:

wd 'ptop 0'

To hide radiobuttons and worktext use:

wd 'psel bg;pas ',":do_jzbg_ 'MARGIN,-+/EH,MARGIN,RBH'

To restore use

wd 'psel bg;pas ',":2#MARGIN_jzbg_

Some pretty unicode symbols to use in button labels (copy and paste)

← ↓ ↑ →
◄ ▼ ▲ ►
∑ ∏ σ √ ∫ ∂ ∆ ∞ ∩ ∪

Ideas for further improvements

I try to keep both interface and operation as simple as possible. Most of these ideas defeat this goal and therefore unlikely to be implemented. Nevertheless, I list them here as a food for thought.

multiline button labels

There seems to be no way to do it in wd

Color buttons

Buttons may have color. Static coloring enhances button grouping by function. Dynamic coloring may indicate "state" of some variable that this button affects.

Moving rectangular blocks of buttons around

Expanding button array to fit more buttons often requires existing buttons to be slightly rearranged. 'exch' command allows to do it on small scale. Direct manipulation of ACTION global does it on larger scale, but is inconvenient due to lack of convenient multidimensional indexing in J.


The whole point is to have all commands available one click away. Having them on different tabs makes it two clicks away.