User:Joe Bogner/QtLayout
This essay is written in response to http://jsoftware.com/pipermail/beta/2015-October/008316.html
Methods of laying out controls in jqt
This essay will explore 3 different methods of laying out controls in a jqt form.
- Grid cell - pros: more control in exact placement. cons: rearranging or inserting requires changing indices
- Grid razed - pros: minimal syntax, fluid, adapts to display. cons: exact placement may be challenging
- bins - pros: limitless flexibility. cons: may be tedious and difficult to comprehend
Desired result
Based on the forum post, the goal is to create an interface that looks like this:
Cmd 1: _____________ [Button 1] Cmd 2 : _____________ [Button 2] Output 1: __________ __________ Output 2: __________ __________ Plot Cmd 1: ___________ [Plot Button 1] Plot Cmd 2: ___________ [Plot Button 2] +-------------------------------+ | | | PLOT 1 | | | +-------------------------------+ +-------------------------------+ | | | PLOT 2 | | | +-------------------------------+
NOTE: This example does not put a plot control on the form. That is outside the scope of the article as is wiring up the control.s
Grid Cell
The grid cell method will instruct jqt to place controls at precise cell locations in a grid. The grid size will automatically be determined based upon the cells that are added. It is typical to specify the text for a control at the same time as creating the control. Controls also require IDs. The ID of the control can be user specified. The ID might be considered a system concern and not a programmer concern. A small helper is provided to combine creating and setting the text into a single call and returns the id of the new control - in case it is needed in the future.
idUI =: 0 addUI =: 4 : 0 pos=: x if. 2=(#y) do. 'type text' =. y end. if. 3=(#y) do. 'type text cellwh' =. y end. id =. 'ux', ": idUI wd 'grid cell ', pos NB. maxwh needs to be called before cc but on the cell if. 3=(#y) do. wd cellwh end. wd 'cc ', id , ' ',type if. (#text) > 0 do. wd 'set ', id , ' text ', text end. idUI=:idUI+1 id ) NB. ========================================================= grid=: 3 : 0 wd 'pc grid' '1 1' addUI 'static';'Cmd 1' '1 2' addUI 'edit';'' '1 3' addUI 'button';'Run Cmd 1' '2 1' addUI 'static';'Cmd 2' '2 2' addUI 'edit';'' '2 3' addUI 'button';'Run Cmd 2' '3 1' addUI 'static';'Output 1' NB. make editm smaller than default '4 1 1 3' addUI 'editm';'Output 1';'maxwh 1000 75' '5 1' addUI 'static';'Output 2' '6 1 1 3' addUI 'editm';'Output 2';'maxwh 1000 75' '7 1' addUI 'static';'Plot Cmd 1' '7 2' addUI 'edit';'' '7 3' addUI 'button';'Run Cmd 1' '8 1' addUI 'static';'Plot Cmd 2' '8 2' addUI 'edit';'' '8 3' addUI 'button';'Run Cmd 2' '9 1 1 3' addUI 'isigraph';'';'minwh 500 100' '10 1 1 3' addUI 'isigraph';'';'minwh 500 100' wd 'pshow' ) NB. ========================================================= grid_close=: 3 : 0 wd 'pclose' ) NB. ========================================================= grid''
Grid Razed (w/bin)
Razed grids allow controls to be added in sequential order and rearranged without specifying the exact row/column. This style may require the use of bins if all controls don't fit into a NxN grid. The desired layout above has the structure of:
3 controls 3 controls 1 control 1 control 1 control 1 control 3 controls 3 controls 1 control 1 control
As such, this layout cannot be supported purely by using a razed grid since rowspan/colspan cannot be specified. The solution mixes bins and grids
idUI =: 0 addUI =: 3 : 0 if. 2=(#y) do. 'type text' =. y end. if. 3=(#y) do. 'type text cellwh' =. y end. id =. 'ux', ": idUI NB. grid cell can't be called in razed grid NB. wd 'grid cell ', pos NB. maxwh needs to be called before cc but on the cell if. 3=(#y) do. wd cellwh end. wd 'cc ', id , ' ',type if. (#text) > 0 do. wd 'set ', id , ' text ', text end. idUI=:idUI+1 id ) NB. ========================================================= grid=: 3 : 0 wd 'pc grid' wd 'grid size 3 3' NB. optional to show how columns widths can be specified wd 'grid colwidth 0 100' wd 'grid colwidth 2 100' addUI 'static';'Cmd 1' addUI 'edit';'Grid/Bin Layout' addUI 'button';'Run Cmd 1' addUI 'static';'Cmd 2' addUI 'edit';'' addUI 'button';'Run Cmd 2' NB. need to end previous grid and start a vertical bin wd 'bin zv' addUI 'static';'Output 1' addUI 'editm';'Output 1';'maxwh 1000 75' addUI 'static';'Output 2' addUI 'editm';'Output 2';'maxwh 1000 75' NB. stop previous vertical bin and create new vertical grid wd 'bin zvg' wd 'grid size 3 3' wd 'grid colwidth 0 100' wd 'grid colwidth 2 100' addUI 'static';'Plot Cmd 1' addUI 'edit';'' addUI 'button';'Run Cmd 1' addUI 'static';'Plot Cmd 2' addUI 'edit';'' addUI 'button';'Run Cmd 2' NB. need to end previous grid and start a vertical bin wd 'bin zv' addUI 'isigraph';'';'minwh 500 100' addUI 'isigraph';'';'minwh 500 100' wd 'pshow' ) NB. ========================================================= grid_close=: 3 : 0 wd 'pclose' ) NB. ========================================================= grid''
The result is nearly identical to the first
JHS
JHS does not use the same layout engine as jqt, but one can be emulated. That same emulation can allow the jqt wd commands, wrapped in addUI, to be called on jhs.
Save this file somewhere (e.g. ~Projects/layout.ijs) and load from JHS using
load '~Projects/layout.ijs'
Then browse to http://127.0.0.1:65001/layout
coclass'layout' coinsert'jhs' CURRENTCOL=:1 GRIDCOLS=:0 NB. helper to add controls addUI =: 3 : 0 css=.'' if. 2=(#y) do. 'type text' =. y end. if. 3=(#y) do. 'type text cellwh' =. y parts=. ' ' cut cellwh if. (0{parts) -: (<'maxwh') do. css=. ' style="height: ', (> {: parts), 'px"' end. end. CURRENTCOL=:CURRENTCOL + 1 HTML=: HTML, '<div class="field">' if. type -: 'static' do. HTML=:HTML,'<label>',text,'</label></div>',LF elseif. type -: 'edit' do. HTML=:HTML,'<input type="text" value="',text,'"',css,'>',LF elseif. type -: 'button' do. HTML=:HTML,'<input type="button" value="',text,'"',css,'>',LF elseif. type -: 'editm' do. HTML=:HTML,'<textarea',css,'>',text,'</textarea>',LF end. HTML=: HTML,'</div>' if. CURRENTCOL >: (GRIDCOLS+1) do. CURRENTCOL=:1 HTML=:HTML,'<br style="clear:both">' end. HTML ) NB. stub to allow jqt code to pass through wd =: 3 : 0 params=. ' ' cut y if. ((0{params) -: (<'grid')) *. ((1{params) -: (<'size')) do. GRIDCOLS =: ". > {: params CURRENTCOL=: 1 smoutput GRIDCOLS elseif. ((0{params) -: (<'bin')) *. ((1{params) -: (<'zv')) do. GRIDCOLS=: 0 end. ) NB. css for the form CSS=: 0 : 0 div.field { float: left;margin-bottom:10px } body { padding: 20px; } ) NB. executed on GET request jev_get=: 3 : 0 'layout test'jhr'' ) NB. build the html HBS=: 0 : 0 HTML=:'' grid'' ) NB. commands to build the grid/form grid =: 3 : 0 wd 'pc grid' wd 'grid size 3 3' addUI 'static';'Cmd 1' addUI 'edit';'Grid/Bin Layout' addUI 'button';'Run Cmd 1' addUI 'static';'Cmd 2' addUI 'edit';'' addUI 'button';'Run Cmd 2' NB. need to end previous grid and start a vertical bin wd 'bin zv' addUI 'static';'Output 1' addUI 'editm';'Output 1';'maxwh 1000 75' addUI 'static';'Output 2' addUI 'editm';'Output 2';'maxwh 1000 75' NB. stop previous vertical bin and create new vertical grid wd 'bin zvg' wd 'grid size 3 3' addUI 'static';'Plot Cmd 1' addUI 'edit';'' addUI 'button';'Run Cmd 1' addUI 'static';'Plot Cmd 2' addUI 'edit';'' addUI 'button';'Run Cmd 2' NB. need to end previous grid and start a vertical bin wd 'bin zv' addUI 'isigraph';'';'minwh 500 100' addUI 'isigraph';'';'minwh 500 100' )
Summary
There is no right answer on how to lay out a form. The grid/bin approach has a steeper learning curve but is worth learning. Study http://code.jsoftware.com/wiki/Guides/Window_Driver/Layout for further examples.