I have two problems in this iup.lua program
they are described in the header comments and located in the code itself with
all other pertinent information (search for ****). How can I resolve these
issues by a generalized means? I intend to 'objectivise' this program so that
it can become a simple require to display simple tables. I will consider more
complex tables once I am certain the iup functions are robust and correct.
thank you,
Ron Melby
--[[
Windows 10 64 Bit
Lua version 5.1
iup.lua version 3.11.2
functions:
search for **** <<<< explains the *PROBLEM*
dbg = dbg <<<< set the breakpoint
_sfl_WRITE(_tbl)
takes an input table and writes it into the gridbox
_set_IO
determines whether a field is label or text
_get_IO
if a _usrdfn{buf} description is 'var' then call users program function cb_io
_set_ptr *PROBLEM*
sets row start handle and io fields handles
_sfl_CTL
vbox, hbox, buttons etc pack them up and display them
_sfl_READC *PROBLEM*
read and return changed records by handle
cb_io
callback program if _usrdfn['buf'][n] = 'var'
simple test function included in this program for testing.
in my program may need to pcall it to provide better error indications.
* ColeValleyGirl on FHUG.org.uk which uses lua and iup.lua for plugins
explained a more rigorous callback function, but I did not understand it.
abbreviations:
sfl = subfile
ctl = control
fld = field
buf = buffer
readc = read changed records
var = variable
dsp = display
rtx = return table external
ptr = pointer (handle)
*TODO build similar program using matrix
header under title.
opt (handle) opt_01 etc tonumber(opt) changes meaning of readonly
posn to
_usrdfn header
expand to 'tree-d' subfile --nested table, two dependent tables? hbox and
vbox combined? ie:
will build like:
Morris and Ruth Melby
Morralee
Ronalee
Ronald
Donald
Richard
*TODO END
two required args.
1) table to display (for development using qsysval)
2) a table that describes the fields to display
and whether or not they are changeable
... the prototype is _usrdfn
]]
-- constants until require installed
local WS_Abort = 'Abort'
local WS_CANCEL = false
local WS_Cancel = 'Cancel'
local WS_ENTER = true
local WS_Ignore = 'Ignore'
local WS_OK = 'OK'
local WS_Retry = 'Retry'
local WS_ERR = 2
local WS_YES = 'Yes'
local WS_NO = 'No'
local _usrdfn = {} -- user instructions for subfile display
local fld_elem = 0 -- counter to perform checks at .new
local buf_elem = 0 -- counter to perform checks at .new
-- local atr_elem = 0 -- counter to perform checks at .new
local rtx = {} -- return changed records via callback when I get readc working
local row = 0
local col = 0
-- using supplied instruction table _usrdfn ['fld'] and ['buf']
-- write subfile object
-- QSYSVAL table to write for testting
function _sfl_WRITE(_tbl)
local hdl -- build handles for records, and io flds
local __ptr = {} -- _cp = record handles, _dp = fld dta handles
--[[
__ptr[1] =
{
_cp = { '_cp_01' == (handle) }, -- rcd nbr lookup handle, record
handle(pointer)
_dp[3] = { '_dp_03' == (handle) }, -- fld dta lookup handle, field
handle(pointer)
_dp[7] = { '_dp_07' == (handle) }, -- fld dta lookup handle, field
handle(pointer)
IO =
},
__ptr[2] =
{
_cp = { 'cp_02' == (handle) }, -- rcd lookup handle, record
handle(pointer)
- _dp = nil: does not exist for output only records.
},
]]
-- create a field io attribute if conditions are met to insert into subfile.
function _set_IO(_OBJ)
local _fldobj
local function _get_IO()
if (_OBJ._buf == 'KEY'
or _OBJ._buf == 'o') then
_OBJ._io = 'o'
_OBJ.readonly ='YES'
return
end
if _OBJ._buf == 'io' then
_OBJ._io = 'io'
_OBJ.readonly ='NO'
return
end
if _OBJ._buf == 'var' then
-- send key of file and fld decide if it should be 'io' or 'o'
-- 'u' for planned expansion
local _buf = cb_io('u', _OBJ._key, _OBJ._fld)
if _buf == 'io' then
_OBJ.readonly ='NO'
_OBJ._io = _buf
return
end
if _buf == 'o' then
_OBJ._io = _buf
_OBJ.readonly ='YES'
return
end
error("cb_io returned value that is not 'o' or 'io'.")
end
end -- fn _get_IO
-- entry point
_get_IO()
if _OBJ._io == 'o' then
_fldobj = iup.label(_OBJ)
return _fldobj
end
if _OBJ._io == 'io' then
_fldobj = iup.text(_OBJ)
return _fldobj
end
error(string.format("_OBJ._io for %s is not 'o' or 'io'", _OBJ._fld))
end
function _set_ptr(matobj, row, col, _OBJ)
-- data pointer subfile record number field and offset pointers
if matobj == '_dp' then
-- bld value handles
if not (__ptr[row][matobj]) then
__ptr[row][matobj] = {}
__ptr[row][io] = {}
end -- exists
hdl = string.format('%s_%s_%s', matobj, row, col)
iup.SetHandle(hdl, _OBJ)
__ptr[row][matobj][col] = {hdl = hdl}
--[[
hdl = string.format('io_%s', row)
dbg = dbg
iup.SetHandle(hdl, _OBJ.title)
**** bad argument #2 to 'SetHandle' (iup handle expected)
__ptr[row][io] = {hdl = hdl}
]]
return __ptr -- upvalue must return it
end -- fld pointer
-- space pointer subfile record number key pointers
if matobj == '_cp' then
if not (__ptr[row]) then
__ptr[row] = {}
end -- exists
hdl = string.format('%s_%s', matobj, row)
iup.SetHandle(hdl, _OBJ)
__ptr[row][matobj] = {hdl = hdl}
--[[ this will not work to set a pointer but it should see above
if _usrdfn.opt then
if not (__ptr[row][opt]) then
__ptr[row][opt] = {}
end
hdl = string.format('opt_%s', row)
iup.SetHandle(hdl, _OBJ.opt)
__ptr[row][opt] = {hdl = hdl}
return __ptr
end
]]
return __ptr -- upvalue must return it
end -- key pointer
end -- rn _set_ptr
local _sflobj =
{
numdiv = fld_elem, -- from count at .new
expandchildren = 'HORIZONTAL',
orientation = 'HORIZONTAL',
alignmentlin = 'ACENTER',
normalizesize = 'YES',
gaplin = '8',
gapcol = '8',
_ptr = {}
}
local _sfl = iup.gridbox(_sflobj)
for KEY, _ in pairs(_tbl) do -- _ = ARRAY
-- start of key
local this = _tbl[KEY]
local __val
local _wsf = _usrdfn['fld'] -- subfile field name
local _wsb = _usrdfn['buf'] -- io buffer attribute
local _wsa = _usrdfn['atr'] -- for expansion
-- materialize unique hdl names
local matobj
-- start of fld by row
row = row + 1
col = 0 -- new row restart column count
for s = 1, _sfl.numdiv do
col = col + 1
if s > 1 then -- field get
-- this.fld
matobj = '_dp'
_sflval = this[_wsf[s]]
else -- key get
-- this.key
matobj = '_cp'
_sflval = KEY -- key always starts subfile line
end
local _OBJ =
{
title = _sflval, -- SFL DSP VALUE
_key = KEY, -- KEY VALUE (from
_tbl)
_fld = _wsf[s], -- FIELD NAME
_fldval = this[_wsf[s]], -- FIELD VALUE from
_tbl
_typ = type(this[_wsf[s]] or _wsb[s]), -- type(from _tbl)
_buf = _wsb[s], -- io from
_usrdfn['buf']
_io = _wsb[s], -- o, io >
crt_IO('var' > cb_io)
_atr = (_wsa[s] or 'rsv'), -- unused(for
expansion)
readonly = '', -- YES, NO >
crt_IO('var' > cb_io)
multiline = 'NO', -- for now, one line.
}
_OBJ = _set_IO(_OBJ) -- create io display attributes
-- need pointer?
if matobj == '_cp'
-- _ptr[row][matobj]
or _OBJ._io == 'io' then
-- _ptr[row][matobj][col] = {}
__ptr = _set_ptr(matobj, row, col, _OBJ)
end
-- add the object
_sfl:append(_OBJ)
end -- sfl_flds
end -- for _tbl
_sfl._ptr = __ptr
return _sfl
end
function _sfl_CTL(_sfldsp)
local btn_atr = {}
btn_atr =
{
title = 'ENTER',
action = function(self)
_sfl_READC(_sfldsp) --error
rtx.rc = WS_ENTER
return iup.CLOSE
end
}
local btn_ENTER = iup.button(btn_atr)
btn_atr =
{
title = 'EXIT',
action = function(self)
rtx.rc = WS_CANCEL
rtx.TAG = ''
return iup.CLOSE
end
}
local btn_EXIT = iup.button(btn_atr)
-- Creates vbox-scrollbox
local _dsp = iup.vbox{iup.scrollbox{_sfldsp}}
local fn_keys = iup.hbox{btn_ENTER, btn_EXIT}
-- Creates a dialog with frame(s) and title
local ws_dsp =
{
iup.vbox{_dsp, iup.hbox{fn_keys}},
title = 'System Values',
size = '180xHALF',
margin = '8x8'
}
local _sfl = iup.dialog(ws_dsp)
return _sfl
end -- fn _sfl_CTL
function _sfl_READC(_sfl)
local _rcd = _sfl._ptr
local rtx = {}
-- local sfl_div = tonumber(_sfl.numdiv) -- '3'
-- local sfl_flds = tonumber(_sfl.numcol) -- '3'
-- local sfl_siz = tonumber(_sfl.numlin) -- '10'
-- for row, key in ipairs(_rcd) do
for row = 1, _sfl.numlin do
local _Kptr = _rcd[row]._cp
local _Fptr = _rcd[row]._dp
-- not being used at the moment
local rcd = iup.GetChild(_sfl, ((row - 1) * _sfl.numcol))
--[[get return values here -- none of this works
local _IOptr = _rcd[row].io
if _usrdfn[opt] then
local _iohdl = iup.GetHandle(_IOptr.hdl)
local _ioval = _io.title
]]
if _Fptr then
local _sflval, KEY, FLD, _fldval, _typ, _buf, _io, _atr, readonly,
multiline
for col, obj in pairs(_Fptr) do
-- bld value handles
local _OBJ = iup.GetHandle(_Fptr[col].hdl)
_sflval = _OBJ.title -- SFL DSP and Entry VALUE
KEY = _OBJ._key -- KEY VALUE (from _tbl)
FLD = _OBJ._fld -- FIELD NAME
_fldval = _OBJ._fldval -- FIELD VALUE from _tbl
_typ = _OBJ._typ -- type(from _tbl)
_buf = _OBJ._buf -- io from _usrdfn['buf']
_io = _OBJ._io -- o, io > crt_IO('var' > cb_io)
_atr = _OBJ._atr -- unused(for expansion)
readonly = _OBJ.readonly -- YES, NO > crt_IO('var' > cb_io)
multiline = _OBJ.multiline -- for now, one line.
dbg = dbg
--[[
**** inspect _OBJ.title, _sflval
where is the returned value from iup?
I expect it to be in the field title,
which is what displays and what is entered in the field.
how do I get the entries from the display?
]]
if _sflval
and _sflval ~= _fldval then
rtx[#rtx + 1] = {KEY = KEY, FLD = FLD, OLDVAL = _fldval, NEWVAL =
_sflval}
end -- chgrcd
-- not being used at the moment
local ctx = iup.GetBrother(iup.GetHandle(_Fptr[col].hdl))
end -- all flds in row
end -- fields in the row
end -- records
-- install callback for changed records
-- cb_chgrcd{rtx)
end -- fn readc
-- this is for testing purposes and will be contained in the usr pgm as a
callback
function cb_io(_u, key, fld)
if QSYSVAL[key].QALWCHG == '1' then
return 'io'
end
if QSYSVAL[key].QALWCHG == '0' then
return 'o'
end
end
QSYSVAL =
{
["QPRTFS"] = {
["QCTX"] = "*USR",
["QTYP"] = "",
["QDESC"] = "field separator",
["QALWCHG"] = "1",
["QRULES"] = {
},
["QVAL"] = "",
},
["QPRTPG"] = {
["QCTX"] = "*USR",
["QTYP"] = "",
["QDESC"] = "field paragraph",
["QALWCHG"] = "1",
["QRULES"] = {
},
["QVAL"] = "",
},
["QPRTLSC"] = {
["QCTX"] = "*SYS",
["QTYP"] = 0,
["QDESC"] = "Landscape PrintFile length",
["QALWCHG"] = "0",
["QRULES"] = {
},
["QVAL"] = 198,
},
["QBASLATI"] = {
["QCTX"] = "*USR",
["QTYP"] = 0,
["QDESC"] = "home base latitude",
["QALWCHG"] = "1",
["QRULES"] = {
},
["QVAL"] = 46.4598781,
},
["QAWBAS"] = {
["QCTX"] = "*USR",
["QTYP"] = "",
["QDESC"] = "Aboville length",
["QALWCHG"] = "1",
["QRULES"] = {
},
["QVAL"] = "",
},
["QPRTFD"] = {
["QCTX"] = "*USR",
["QTYP"] = "",
["QDESC"] = "field delimiter",
["QALWCHG"] = "1",
["QRULES"] = {
},
["QVAL"] = "",
},
["QGABAS"] = {
["QCTX"] = "*USR",
["QTYP"] = "",
["QDESC"] = "grave address length",
["QALWCHG"] = "1",
["QRULES"] = {
},
["QVAL"] = "",
},
["QBASLONG"] = {
["QCTX"] = "*USR",
["QTYP"] = 0,
["QDESC"] = "home base longitude",
["QALWCHG"] = "1",
["QRULES"] = {
},
["QVAL"] = -95.660015,
},
["QPRTPTT"] = {
["QCTX"] = "*SYS",
["QTYP"] = 0,
["QDESC"] = "Portrait PrintFile length",
["QALWCHG"] = "0",
["QRULES"] = {
},
["QVAL"] = 198,
},
["QFMBAS"] = {
["QCTX"] = "*USR",
["QTYP"] = "",
["QDESC"] = "Family Marriage length",
["QALWCHG"] = "1",
["QRULES"] = {
},
["QVAL"] = "",
},
}
_usrdfn =
{
-- more to follow
-- opt = (1 or 2 ' '),
--[[ *REQUIRED ]]
['fld'] = {[1] = 'KEY', [2] = 'QCTX', [3] = 'QVAL',},
['buf'] = {[1] = 'KEY', [2] = 'o', [3] = 'var',},
--[[ end *REQUIRED ]]
-- ['atr'] = {}, -- for expansion after readc
}
for _,_ in ipairs(_usrdfn['fld']) do
-- check for is %q etc
fld_elem = fld_elem + 1
end
for _,_ in ipairs(_usrdfn['buf']) do
-- check for {'KEY', 'o', 'io', 'var',}
buf_elem = buf_elem + 1
end
--[[
for _,_ in ipairs(_usrdfn['atr']) do
-- expansion
atr_elem = atr_elem + 1
end
]]
if fld_elem ~= buf_elem then
error(" ['fld'] and ['buf'] not equal.")
end
local _sflobj = _sfl_WRITE(QSYSVAL)
local ws_dsp = _sfl_CTL(_sflobj)
ws_dsp:show(iup.CENTER, iup.CENTER)
iup.MainLoop()
ws_dsp:destroy()
return
_______________________________________________
Iup-users mailing list
Iup-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/iup-users