* IUP again

Writing and using plugins for Version 5 and above.
Post Reply
User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

IUP again

Post by Ron Melby » 30 Jun 2020 11:51

problem statement:
I am making a utility that will search for tags in my file. when it finds them, it reports on them.
I have a function that reads all the tags in the file.
I can load them into a table.
I have what code I understand below. I realize it is formatted terribly for lua, but it is how I go about understanding line by line.
I realize this only shows the screen and will not leave the mainloop.
my first and most confounding issue is loading my table into iup.list()

issues:
how do I get from my table and drop that table into iup.list?
how do I show at least part of the list? I thought the visible 4 would show the first 4 (like pagination) until I poked the twistie. at present it shows nothing until I poke the twistie and it shows all 8. I will have more than one page per screen of tags, so I will need to implement a slider (vbox?) in the display.
I will need to implement an ok and cancel button as well.
I expect when I select one I need some cb function to get it.
it will be a single selection. is there a double click and go or do need to click and ok button (that is, does the callback have to be connected to the buttons?

I havent done a great deal with iup, I have made several attempts, but find the documentation massively obscure.

ColeValleyGirl, I read your question and self-answers on this load thing on stack overflow of an instant some 5+ years ago, and was not enlightened.... LOL. It was and is too sophisticated for me at the present time.

Code: Select all

function sltTAG()
  local Opt     = 0

-- Create a list and set:
-- contents
-- dropdown 
-- expansion
-- # of visible items 
  list_tags = iup.list 
  {
    'TAG1',
    'TAG2',
    'TAG3',
    'TAG4',
    'TAG5',
    'TAG6',
    'TAG7',
    'TAG8',
    dropdown = 'YES', 
    expand   = 'YES',
    visible_items = 4
  }

-- Creates frame with dropdown list and sets its title
  frame_tags = iup.frame 
  {
    list_tags,
    title = 'Drop Down',
    size  = 'QUARTERxQUARTER'
  }

-- Creates a dialog with the frame and sets its title
  dlg = iup.dialog 
  {iup.hbox 
    {
      frame_tags
    },
    title = 'IupList',
    size  = 'QUARTERxQUARTER'
  }

-- Shows dialog in the center of the screen
  dlg:showxy(iup.CENTER, iup.CENTER)


  if (iup.MainLoopLevel() == 0) then
    iup.MainLoop()
  end

  if WS_RC == WS_ENTER then
    return WS_RC, Opt
  end
  return WS_CANCEL, ''
end -- fn sltTAG

sltTAG()
FH V.6.2.7 Win 10 64 bit

User avatar
ColeValleyGirl
Megastar
Posts: 1685
Joined: 28 Dec 2005 22:02
Family Historian: V6.2
Location: Cirencester, Gloucestershire
Contact:

Re: IUP again

Post by ColeValleyGirl » 30 Jun 2020 11:57

This is my goto function for populating a list from a table.

Code: Select all

        function PopulateList(l, tblVals)
            local is_indexed = (rawget( tblVals, 1 ) ~= nil)
            l.REMOVEITEM = "ALL"
            if not is_indexed then
                local i=1
                for k, _ in pairs(tblVals) do
                    l[tostring(i)]=k
                    i=i+1
                end
            else
                for i, v in ipairs(tblVals) do
                    l[tostring(i)]=v
                end	
            end
        end

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 30 Jun 2020 12:15

I have that from stackoverflow, I dont understand it. what is l? in the case of my code? tblVals is my table got that.
l is iup.list? l is list_tags?

again, I saw your answer and dont understand how to implement it.
list_tags = iup.list{}
list_tags = PopulateList(list_tags, my_tbl)
like that?
FH V.6.2.7 Win 10 64 bit

User avatar
ColeValleyGirl
Megastar
Posts: 1685
Joined: 28 Dec 2005 22:02
Family Historian: V6.2
Location: Cirencester, Gloucestershire
Contact:

Re: IUP again

Post by ColeValleyGirl » 30 Jun 2020 13:21

l is any iup.list; tblVals is any Lua table (indexed or non-indexed). It take the values in the table and drops them into the list.

You code is a good start, but how are you constructing your iup list?
You'll also want to think about how you handle what happens when a value is selected.

Have a look at my Research Planner plugin and search for the code that starts with something like:

Code: Select all

--[[ Dialog
@Author:      Helen Wright
@Version:      1.0
@LastUpdated:  29 October 2019
@Description:  Helper functions for IUP dialogs
@V1.0:        Initial version.
]]--
There are a number of routines you might want to 'borrow' in the section called "List handling". Treat them as black boxes intitially, and take your time understanding what each bit does.

Mike probably has some equivalents, and I won't cry if you borrow his instead :)

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 01 Jul 2020 13:19

taglist => (table #64)
[1] => (table .1)
TAG => "NAME"
[2] => (table .1)
TAG => "SEX"
[3] => (table .1)
TAG => "FAMS"
[4] => (table .1)
TAG => "BIRT"
[5] => (table .1)
TAG => "FAMC"
[6] => (table .1)
TAG => "DEAT"
[7] => (table .1)
TAG => "BURI"
[8] => (table .1)
TAG => "SOUR"
[9] => (table .1)
TAG => "CENS"

my table looks like this ^^^^.

I have had to import and change some code due to errors, most of it is clash with my codevariables here is the change:

function crtList(tbl)
local lst = iup.list{}

--[[
if options.norm then
l.normalizergroup = options.norm
end
]]

bldList(lst, tbl)

-- add options
lst.editbox = 'NO'
lst.sort = 'YES'
lst.dropdown = 'YES'
lst.visibleitems = '8'
lst.expand = 'HORIZONTAL'
lst.multiple = 'NO'
-- now handle callbacks
lst.action = function(self, text, item, state) end
return lst
end


function bldList(lst, tbl)
lst.REMOVEITEM = 'ALL'
local is_indexed = (rawget(tbl, 1) ~= nil)

if not is_indexed then
local i = 1
for k, _ in pairs(tbl) do
lst[tostring(i)] = k
i = i + 1
end
else
for i, v in ipairs(tbl) do
lst[tostring(i)] = v
end
end
end

i execute the else here and it returns '1' and done
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 02 Jul 2020 22:37

I send into the equivalent of your MakeList(options)
tbl => (table #64)
[1] => "NAME"
[2] => "SEX"
[3] => "FAMS"
[4] => "BIRT"
[5] => "FAMC"
[6] => "DEAT"
[7] => "BURI"
[8] => "SOUR"
[9] => "CENS"
[10] => "RESI"
[11] => "EVEN-OBIT"
[12] => "OCCU"
[13] => "EVEN-BIO"
[14] => "_ATTR-MILT"
[15] => "EVEN-TODO"

which appears to be an indexed table
what arrives there immediatly after I am in the function is:

tbl => (table #1)
[1] => (table #64)
[1] => "NAME"
[2] => "SEX"
[3] => "FAMS"
[4] => "BIRT"
[5] => "FAMC"
[6] => "DEAT"
[7] => "BURI"
[8] => "SOUR"
[9] => "CENS"
[10] => "RESI"
[11] => "EVEN-OBIT"
[12] => "OCCU"
[13] => "EVEN-BIO"
[14] => "_ATTR-MILT"
[15] => "EVEN-TODO"

the for k, v in ipairs in populate list reads it once, and returns an empty string. how can this possibly be true? I have debugged and tried to do everything I can think of.
FH V.6.2.7 Win 10 64 bit

User avatar
ColeValleyGirl
Megastar
Posts: 1685
Joined: 28 Dec 2005 22:02
Family Historian: V6.2
Location: Cirencester, Gloucestershire
Contact:

Re: IUP again

Post by ColeValleyGirl » 03 Jul 2020 05:22

Can you post the actual code please -- formatted as code "I send into the equivalent of your MakeList(options)" doesn't tell me enough about how you're calling it.

As a clue, Makelist takes as its single parameter a table of named options, so you invoke it as e.g.

Code: Select all

listQuality = MakeList{sort = "NO", action = CheckQualityValue, values = tblAssessment, norm = norm2, name = "quality"}

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 03 Jul 2020 12:16

I have resolved the issue with not loading iup.list. and the error was not your code.

it initially starts as a blank box with the twistie, and when you poke the twistie the list comes up, I dont see a way to make the first list item show on the intitial screen

this is what I am using for documentation because this is what I can find:
https://webserver2.tecgraf.puc-rio.br/i ... plist.html

I dont know what level of iup.list we are on, but sure it aint this one, meaning that 3.0 stuff probably is not useful,
OK so when I poke something on the list, I am unsure if I want double click to select the item, for now I probably have to poke it and hit ok,

so I need an ok and cancel button, and the callback would be in the ok button and cancel to get me out of the loop in the cancel button.

Now am I to understand whatever my callback is in the OK button would receive action?
lst.action = function(self, text, item, state) end

https://webserver2.tecgraf.puc-rio.br/i ... utton.html
so if I have button_cb(self, text, item, state) thats the link?

Code: Select all

function MakeButton(options)
    local b = iup.button{}
    local callback = options.callback
    if callback ~= nil then
      if options.close ~= nil then 
        -- this is a close button
        b = iup.button
        {
          action = function(self) 
            if callback() == true then
              return iup.CLOSE 
            end 
          end
        }
      else
        b = iup.button
        {
          action = 
          function(self)
            callback() 
          end
        }
      end
    else 
      -- if callback isn't specified this is a cancel button
      b = iup.button
      {
        action = function(self)
          return iup.CLOSE 
        end
      }
    end

    b.alignment='ALEFT'
    b.padding ='10x0'
    b.normalizergroup = options.norm or norm
    b.title = options.title or ''
    if options.tip then 
      b.tip = options.tip 
    end
    if options.name then
      iup.SetHandle(options.name, b) 
    end
    return b
  end
end
there is your makebutton, and I dont see how I use it. there must be other code to set this up,
FH V.6.2.7 Win 10 64 bit

User avatar
ColeValleyGirl
Megastar
Posts: 1685
Joined: 28 Dec 2005 22:02
Family Historian: V6.2
Location: Cirencester, Gloucestershire
Contact:

Re: IUP again

Post by ColeValleyGirl » 03 Jul 2020 12:31

Version information is here: Knowledge Base > IUP GUI Builder References as is link to documentation. 3.11.2 so the v3 stuff is what you want, but you need to look out for annotations saying things were introduced after that, and not use them.

Yep, the list is blank until you start the process of selecting something. After all, blank = nothing selected is a meaningful state.

Make sure you understand the callbacks and the configurations in which each is available.

I often use the action callback to check that the value currently selected is valid in the context of any other data entered, but only use the value when (as you suggest) an OK or cancel button is pressed. My dialog code includes routines to get selected value or values...

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 03 Jul 2020 12:55

uuuuuuuuuuuuuuuuuuhhhhhhhhhhhhhhhhhhhhhhhh yeah, ok???????????????????????????????

so

how do I receive action?

I mimic but I do not understand. I don't have any fundamental frame of reference for this what appears to me to be maismatic spaghetti iup stuff.

I know I have to receive action it contains the item, I dont care right now about anything else in that action but of course I want to see the values to learn what it means of the other parms.

if item ~= ''
and ??button ok is pressed?? then
return item
end
else go it again

I dont see where or how to recieve:
action(self, text, item, state)
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 03 Jul 2020 14:03

Code: Select all

fhSetStringEncoding('UTF-8')

function bldTAGS()
  local ptr     = fhNewItemPtr()
  local ptrENT  = fhNewItemPtr()
  local ptrTAG  = fhNewItemPtr()
  local tbl     = {}
  local tmp     = {}

  ptr:MoveToFirstRecord('INDI')
  while ptr:IsNotNull() do
    ptrENT:MoveToFirstChildItem(ptr)
    while ptrENT:IsNotNull() do
      ptrTAG:MoveTo(ptrENT)
      local TAG = fhGetTag(ptrTAG)
      if tbl[TAG] then
        tbl[TAG].NBR = tbl[TAG].NBR + 1
      else
        tbl[TAG] = {TAG = TAG, NBR = 1}
      end
      ptrENT:MoveNext()
    end
    ptr:MoveNext()           
  end  

  for k, v in pairs(tbl) do
    table.insert(tmp, v)
  end
  table.sort(tmp, function(a, b) return a.NBR > b.NBR end)

  tbl = {}
  for k, v in pairs(tmp) do
    table.insert(tbl, tmp[k].TAG)
  end
  return tbl
end

function bldList(lst, tbl)
  lst.REMOVEITEM = 'ALL'
  local is_indexed = (rawget(tbl, 1) ~= nil)

  if is_indexed then
    for k, v in ipairs(tbl) do
      lst[tostring(k)] = v
    end 
  else
    local i = 1
    for k, _ in pairs(tbl) do
      lst[tostring(i)] = k
      i = i + 1
    end
  end

end

function crtList(tbl)
-- Create a list and set:
  local lst        = iup.list{}
  -- add options
  lst.editbox      = 'NO'
  lst.sort         = 'NO'
  -- dropdown 
  lst.dropdown     = 'YES' 
  -- # of visible items 
  lst.visibleitems = '12'
  -- expansion
  lst.expand       = 'HORIZONTAL'
  lst.multiple     = 'NO' 

  --[[
  if options.norm then
    l.normalizergroup = options.norm
  end
  ]]

  -- contents
  bldList(lst, tbl)

  -- now handle callbacks
  lst.action       = function(self, text, item, state) end
  return lst
end

function sltTAG(tbl)

  list_tags = crtList(tbl)

  -- Creates frame with dropdown list and sets its title
  frame_tags = iup.frame 
  {
    list_tags,
    size  = 'QUARTERxQUARTER'
  }

  local res
  local btn_ok = iup.button
  {
    name   = 'ok',
    title  = 'OK', 
    action = function(self) 
      res  = self.name 
      return iup.CLOSE 
    end
  }
  local btn_cancel = iup.button
  {
    name   = 'cancel',
    title  = 'Cancel', 
    action = function(self) 
      res  = self.name 
      return iup.CLOSE
    end
  }
-- Creates a dialog with the frame and sets its title
  dlg = iup.dialog 
  {
    iup.hbox 
    {
      frame_tags,
      iup.hbox 
      {
        btn_ok,
        btn_cancel
      },
    },

    title = 'Select TAG',
    size  = 'QUARTERxQUARTER'
  }

  -- Shows dialog in the center of the screen
  dlg:showxy(iup.CENTER, iup.CENTER)

  print(tostring(self))
  print(text)
  print(item)
  print(state)

  if (iup.MainLoopLevel() == 0) then
    iup.MainLoop()
  end
end -- fn sltTAG

tbl = bldTAGS()
sltTAG(tbl)
this is the entirety of my code so far.

I am trying to get the OK and Cancel buttons at the bottom of the dropdown.. absolutely no idea how I will get selected item. I dont see the connection, the prints print nil.
FH V.6.2.7 Win 10 64 bit

User avatar
ColeValleyGirl
Megastar
Posts: 1685
Joined: 28 Dec 2005 22:02
Family Historian: V6.2
Location: Cirencester, Gloucestershire
Contact:

Re: IUP again

Post by ColeValleyGirl » 03 Jul 2020 14:27

You receive the action if you program the callback. Unless you want to check the validity of the selection, you probably won't program a callback on the list.

You will program a callback on an OK button and in that button you can get the selected value(s) from the list and then do whatever you want with the value(s).. Start from my code (this is from the boilerplate I've pointed you to before. It does depend on Penlight for the utils element!

Code: Select all

 
        function GetSingleValue(list)
            return utils.choose(list.value ~=0, list[tostring(list.value)], "")
        end      
        function GetSelectedValues(list)
            local tbl = {} --assume nothing selected
            local intLength = tonumber(list.COUNT)
            if intLength > 0 then
                local strSelectionState = list.value -- a sequence of + and -
                for i = 1, intLength do
                    if strSelectionState:sub(i,i) == '\+' then --item is selected
                        table.insert(tbl, list[tostring(i)]) --insert the list item text in the table
                    end
                end
            end
            return tbl --an indexed list of strings
        end
You'll need to do a loadrequire for Penlight, but you really should get used to using it -- think of it as a swissknife of routines. Instructions are in the knowledgebase or use this code towards the top of your plugin:

Code: Select all

    function fhloadrequire(module,extended)
        local function httpRequest(url)
            local http = luacom.CreateObject("winhttp.winhttprequest.5.1")
            http:Open("GET",url,false)
            http:Send()
            http:WaitForResponse(30)
            return http
        end -- local function httpRequest
        if not(extended) then extended = module end
        local function installmodule(module,filename,size)
            local bmodule = false
            if not(filename) then
                filename = module..'.mod'
                bmodule = true
            end
            local storein = fhGetContextInfo('CI_APP_DATA_FOLDER')..'\\Plugins\\'
            -- Check if subdirectory needed
            local path = string.match(filename, "(.-)[^/]-[^%.]+$")
            if path ~= "" then
                path = path:gsub('/','\\')
                -- Create sub-directory
                lfs.mkdir(storein..path)
            end
            local attr = lfs.attributes(storein..filename)
            if attr and attr.mode == 'file' and attr.size == size then return true end
            -- Get file down and install it
            local url = "http://www.family-historian.co.uk/lnk/getpluginmodule.php?file="..filename
            local isOK, reply = pcall(httpRequest,url)
            if not isOK then
                fhMessageBox(reply.."\nLoad Require module finds the Internet inaccessible.")
                return false
            end
            local http = reply
            local status = http.StatusText
            if status == 'OK' then
                --           local length = http:GetResponseHeader('Content-Length')
                local data = http.ResponseBody
                if bmodule then
                    local modlist = loadstring(http.ResponseBody)
                    for x,y in pairs(modlist()) do
                        if type(x) == 'number' and type(y) == 'string' then
                            x = y -- revert to original 'filename' ipairs modlist
                            y = 0
                        end -- otherwise use ['filename']=size pairs modlist
                        if not(installmodule(module,x,y)) then
                            break
                        end
                    end
                else
                    local function OpenFile(strFileName,strMode)
                        local fileHandle, strError = io.open(strFileName,strMode)
                        if not fileHandle then
                            error("\n Unable to open file in \""..strMode.."\" mode. \n "..
                                strFileName.." \n "..tostring(strError).." \n")
                        end
                        return fileHandle
                    end -- OpenFile
                    local function SaveStringToFile(strString,strFileName)
                        local fileHandle = OpenFile(strFileName,"wb")
                        fileHandle:write(strString)
                        assert(fileHandle:close())
                    end -- SaveStringToFile
                    SaveStringToFile(data,storein..filename)
                end
                return true
            else
                fhMessageBox('An error occurred in Download please try later')
                return false
            end
        end
        local function requiref(module)
            require(module)
        end
        local _, err = pcall(requiref,extended)
        if err then
            if  err:match("module '"..extended:gsub("(%W)","%%%1").."' not found") then
                local ans = fhMessageBox(
                    'This plugin requires '..module..' support, please click OK to download and install the module',
                    'MB_OKCANCEL','MB_ICONEXCLAMATION')
                if ans ~= 'OK' then
                    return false
                end
                if installmodule(module) then
                    package.loaded[extended] = nil -- Reset Failed Load
                    require(extended)
                else
                    return false
                end
            else
                fhMessageBox('Error from require("'..module..'") command:\n'..(err or ''))
                return false
            end
        end
        return true
    end
    if not fhloadrequire("pl","pl.init") then return end -- Load required Penlight modules
    pl = require("pl.import_into")

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 03 Jul 2020 16:41

Code: Select all

function sltTAG(tbl)

  list_tags = crtList(tbl)

  -- Creates frame with dropdown list and sets its title

  local rtx
  local btn_ok = iup.button
  {
    name   = 'OK',
    title  = 'OK', 
    action = getSingleValue(list) 
  }
  local btn_cancel = iup.button
  {
    name   = 'CANCEL',
    title  = 'CANCEL', 
    action = function(self) 
      rtx  = self.name 
      return iup.CLOSE
    end
  }
-- Creates a dialog with the frame and sets its title

-- Creates frame with dropdown list and sets its title
  frame_tags = iup.frame 
  {
    list_tags,
    size  = 'QUARTERxQUARTER'
  }
  dlg = iup.dialog 
  {
    iup.hbox 
    {
      frame_tags,
      iup.hbox 
      {
        btn_ok,
        btn_cancel
      },
    },

    title = 'Select TAG',
    size  = 'QUARTERxQUARTER'
  }

-- Shows dialog in the center of the screen
  dlg:showxy(iup.CENTER, iup.CENTER)
end -- fn sltTAG
does not execute screen and immediately calls GetSingleValue(list_tags)
and completes.
does same if it is BUTTON_CB
FH V.6.2.7 Win 10 64 bit

User avatar
ColeValleyGirl
Megastar
Posts: 1685
Joined: 28 Dec 2005 22:02
Family Historian: V6.2
Location: Cirencester, Gloucestershire
Contact:

Re: IUP again

Post by ColeValleyGirl » 03 Jul 2020 17:12

Ron, at some point (a) you need to debug your own code; and (b) you need to actually do the coding. Please look at other plugins and understand all the underpinnings!

As an aside, your code when the OK button is pressed gets the selected list value and does absolutely nothing with it.

Please, stop using us an excuse to learn how to work with Lua and IUP. Thousands (or more) of people can use the relevant documentation to achieve what they want to do so it can't be totally unintelligible.

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 03 Jul 2020 19:02

I HAVE DONE MY OWN DEBUGGING.

(USERVALUE)

I have looked at lots of code, and none is enlightening.

It does absolutely nothing with it, because it is called and the program ends, this is unexpected behavior:

not that I understand any of this, but

CALLBACKS
ACTION
Action generated when the element is activated. Affects each element differently.

Callback handler prototype:

sub action_handler {
my ($self) = @_;
#...
}
ok I says to myself when the element is activated, who knows exactly what that means? perhaps the list activated on the screen? OK, i will use BUTTON_CB

BUTTON_CB
Action generated when a mouse button is pressed or released.
(no it isnt that is not correct I DEBUG and watch it execute before a screen is shown)
Callback handler prototype:

sub button_cb_handler {
my ($self, $button, $pressed, $x, $y, $status) = @_;
#...
}
not that anything in the button_cb handler is useful I just want item.list back
but it also executes immediately and does not show a screen

what do you want me to do with nil?

all your code, the pieces you showed me, I had already known I had to use every one. long before I asked my questions, but perhaps this will help you

it is trivial to forge a pointer to an object under OS400 even though they say you cant do it in the documentation.

copy and change the #rslvsp microcode module, of course you will have to forge a pointer to #auth to install it as a system module.
you have the underpinnings. code it.

so, one of two things is true, either the iup system is useless and nobody here knows how to use it, or I am not coding something correctly and debug does not indicate it to me in any useful fashion,

pick any line in function sltTAG and this is the debug
Untitled.png
Untitled.png (132.52 KiB) Viewed 188 times
what can we all learn from that, prithee? I know whats in tbl. I built it.

I hit showxy, no screen shows and it goes to end.
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 03 Jul 2020 20:45

confirmed:
BUTTON_CB = GetSingleValue(list_tags)
called infinitely
@ GetSingleValue
if rtx == nil then
1>>>iup.MainLoop()
end
called forever as I found out in DEBUG

all values except rtx which == nil
and tbl which is now throwaway
(like 5 of them, not too many I dont think to debug this right?
are-- get this -- how is it possible = userdata

no screen is shown
showxy never reached.
documentation is wrong, and iup does not work as specced nevermind the documentation is uselessly vague and unintelligible, as are any examples.
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 18445
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: IUP again

Post by tatewise » 03 Jul 2020 21:26

If you convince yourself that iup does not work as specified, and the documentation is wrong, uselessly vague and unintelligible, then I guarantee you will never succeed in getting iup to work.

It really does work, as many of my Plugins prove, and the documentation and examples are mostly quite good.
As Helen said, thousands of other people use it very successfully.

So, convince yourself it does work, look through the documentation and examples again with a positive attitude, and investigate where your code has mistakes, then you will succeed. Perhaps start with some simple experimental scripts and gradually enhance them to accommodate your requirements. If you attempt the all singing and dancing version from the start then even quite small mistakes will stop it working.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 03 Jul 2020 22:20

the documentation is wrong prima facie

BUTTON_CB is absolutely wrong in its description.

I thought this was a place for help. While I cannot offer it often, most being leagues ahead of me coding this trivial language, I go all out. (is that not correct?)

Now, I dont need a bunch of labcoats saying debug it. the little bit of code I have posted here to get a screen up at all was over 30 hours of debugging and research.

I start this at ZERO.

I don't really feel comfortable doing this but---

so I have had a series of mini-strokes going back a ways. I remember some things very clearly, others are like holes or cobwebs ...

so I dont go from A>B>C>D>E>F>G>H>I>
at some point I go A>B>C> ...wait, how did we get to I?

so when you say you know this ron, we did this 100 times, its that I havent remembered it yet. My memory might or not be ephemeral time to time on certain things. But I dont want no pity or special treatment at all. I will put up with some level of chiding over what I do. But at some point----

Clearly---------------let me repeat this because it bears repeating, I did all my code on my own without anyone here,
I got it as far as I got it by lots of debugging.

I looked at Helens stuff and recognized what I needed from her stuff. it is far from blackboxable.

booOK and StrstrStrStr is worthless, I can debug it and see if its true or false or a string or an 07FDDA7, so the conventions used out here are rather obtuse in coding.

I have her helpers in a require. I look at it and try to remember as much as I can.

I read her posts from 5 years ago, she had trouble loading the list, I had trouble loading the list.

NOW--- LISTEN CLOSELY, to the following.

I have shown you the debug. Explain line by line in the debug window what I should glean in the logic error. You guys who say do your own debug are real smart, and can find all sorts of information I cannot ken in a single variable.

if I change button_ok to work like button_cancel, the screen executes, and I can choose an item from the drop down..
however as I STATED IN MY ORIGINAL WORKING POST I CAN DO NOTHING WITH IT.

OK, now, I put in code (changing only two or three lines sequentiallly in only one chunk of code ---
I end up with no screen displayed and stuck in a little function for eternity.

What do you think the chances of my statements and logic being wrong are? maybe make a percent list:
my code understanding some form of problem : 0% (virtual impossibility that is the case)
IUP is junk: 90%
fh which uses Lua is junk: 120%
---
total 100% (I think I have covered it all, what say you Mike?)
oh, there is the almost nanopercentage of a chance that SOMEHOW https://webserver2.tecgraf.puc-rio.br/i ... utton.html that very striaghtforward and informational (instead of data) spewing bit of fluff is wrong?

so, the statement is:

useless_info=button_ok:action(BUTTON_CB(item) (or not LOL)

or, and this is the least likely---
I don't understand how to code and use the callback because i want item, and if its '' reexecute, or if its > '' then grab it and go, because it has already been validated as a tag.

Now, I am not really happy I had to say some stuff out here in public, cuz you certainly aint my mates....

Bottom line, I dont understand the callback (as I did not on pplot sometime ago, and rereading that, no help)

and no amout of hints or look at my complex code in Map Life Facts, or ResearchPplanner, neither of which has an OK button with a callback I can trace, (OH, yeah, traced those plugins, more than a few times) is of any enlightenment. I cannot learn it without a working chunk.

BTW Mike, I once long ago did some variations on keyed by index and keyed by dictionary key, and you said why you wanna do all that? so, the finding of whether a key is numeric indexed or an array is old hat, and I have searched all over in the documentation for removeitem'ALL' and that was what I was missing writing on my own. I have also relearned that MakeABigDealofIT{} is legal as a function, but not sure it should be.

Anyway, if anyone can help me understand the callback and why it fails (logically) because my code does not fail codewise, thanks. if not (well, you dont wanna know)
FH V.6.2.7 Win 10 64 bit

User avatar
ColeValleyGirl
Megastar
Posts: 1685
Joined: 28 Dec 2005 22:02
Family Historian: V6.2
Location: Cirencester, Gloucestershire
Contact:

Re: IUP again

Post by ColeValleyGirl » 04 Jul 2020 07:34

Your code is broken, impossible as that may seem,

What happens when you run analyse on your code in Zerobrane? Which you should do whenever you make changes before you go anywhere near the debug window -- but you probably know that.

Does it tell you that you're referencing an unknown variable 'list' which ought to be 'list_tags'?

Plus your OK button action function is wrongly coded:

Code: Select all

 
    action = getSingleValue(list) 
should be

Code: Select all

    action = function(self) GetSingleValue(list_tags) end
You got the structure right for the Cancel button immediately below it, so you had at some point understood the documentation.

Making those two changes and throwing together a quick testing harness:

Code: Select all

--stuff to require penlight goes here, plus the List handling code from my dialog boilerplate
function sltTAG()

  list_tags = MakeList{values = {"A","B","C","D"}}

  -- Creates frame with dropdown list and sets its title

  local rtx
  local btn_ok = iup.button
  {
    name   = 'OK',
    title  = 'OK', 
    action = function(self) 
		X = GetSingleValue(list_tags) --a breakpoint here will let you verify that you're picking up the correct value
	 end
  }
  local btn_cancel = iup.button
  {
    name   = 'CANCEL',
    title  = 'CANCEL', 
    action = function(self) 
      rtx  = self.name 
      return iup.CLOSE
    end
  }
-- Creates a dialog with the frame and sets its title

-- Creates frame with dropdown list and sets its title
  frame_tags = iup.frame 
  {
    list_tags,
    size  = 'QUARTERxQUARTER'
  }
  local dlg = iup.dialog 
  {
    iup.hbox 
    {
      frame_tags,
      iup.hbox 
      {
        btn_ok,
        btn_cancel
      },
    },

    title = 'Select TAG',
    size  = 'QUARTERxQUARTER'
  }
  return dlg

end -- fn sltTAG

-------------------------------------
--EXECUTE
-------------------------------------
do
  dlgmain = sltTAG()
  dlgmain:showxy(iup.CENTER, iup.CENTER)
  iup.MainLoop()
  dlgmain:destroy()
end
Of course it's doing nothing because your code just gets the selected value from the list and doesn't display it or do anything else with it, but I assume you'll get to that when you've got this problem sorted out.

Also Knowledge Base > IUP GUI Builder Hints And Tips might help you -- it has for example very clear examples of how to create buttons.

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 04 Jul 2020 16:58

part of the issue, when I put code out here, I sometimes forget to put up whats in ZB and put up the last change.
for every little change I make I have to save a copy, or I will forget what was done (working or no)
I always run analyze and then when analyse or compile passes, I format source and then save.
I usually keep the last 6 or so, once I am sure.

I got the cancel button from KB IUP builder and tried to modify the ok button to my understanding.

your code snip helped me get the understanding of how to make the function, excellent, and thank you. I was sure I was not understanding what to do

this is the button:

Code: Select all

 local btn_ok = iup.button
  {
    name   = 'OK',
    title  = 'OK', 
    action = function(self) 
      TAG = GetSingleValue(tags)
      for _, v in ipairs(tbl) do
        if TAG == v then
          rtx  = self.name 
          return iup.CLOSE
        end
      end
    end
  }
  
this is the dialog:

Code: Select all

-- Creates a dialog with the frame and sets its title
  dlg = iup.dialog 
  {
    iup.frame
    {
      iup.vbox 
      {
        tags,

        iup.hbox
        {
          btn_ok,
          btn_cancel
        },     
      },
    },

    title = 'Select TAG',
    size  = 'QUARTERxEIGHTH'
  }

  return dlg
which puts up a pretty small screen really, but the perspective is correct.

I am still fighting thru two problems

when I build the list:
I set visible items to 12 (PICKED IT OUT OF THE AIR)
(i plan on doing a pagination type of thing based on #tbl and divide)
however:
lst.visibleitems = '12'
lst.visibleitems = 12

tried it both ways, the line executes, but when it executes the dialog, the default of 5 is shown.
the only substantial change from your code is I moved the lst.(options) to after the build, because of wanting to "paginate" the drop down so at the end of building the lst before I return lst:
local x = lst.visibleitems

x is '12'

I thought it might be the size = 'QUARTERxEIGHTH' creating an issue for me, so I gave it a 'QUARTERxQUARTER' (not asthetically pleasing, but no change, that isnt it. everything else works in straighforward fashion

the second issue is how to resize and I am trying to read up on that (I expect it can be done)
so that when the dropdown is activated the buttons ok and cancel shift down belove the list are still visible and active.
Untitled.png
Untitled.png (27.58 KiB) Viewed 66 times
here is the entire code. I get an error now when cancel comes back because TAG does not exist, simple fix in the packaging department when I am ready to modularize the code.

Code: Select all

local tbl     = {}
local TAG

function bldTAGS()
  local ptr     = fhNewItemPtr()
  local ptrENT  = fhNewItemPtr()
  local ptrTAG  = fhNewItemPtr()
  local tmp     = {}

  ptr:MoveToFirstRecord('INDI')
  while ptr:IsNotNull() do
    ptrENT:MoveToFirstChildItem(ptr)
    while ptrENT:IsNotNull() do
      ptrTAG:MoveTo(ptrENT)
      local TAG = fhGetTag(ptrTAG)
      if tbl[TAG] then
        tbl[TAG].NBR = tbl[TAG].NBR + 1
      else
        tbl[TAG] = {TAG = TAG, NBR = 1}
      end
      ptrENT:MoveNext()
    end
    ptr:MoveNext()           
  end  

  for k, v in pairs(tbl) do
    table.insert(tmp, v)
  end
  table.sort(tmp, function(a, b) return a.NBR > b.NBR end)

  tbl = {}
  for k, v in pairs(tmp) do
    table.insert(tbl, tmp[k].TAG)
  end

  return tbl
end

function bldList(lst, tbl)
  lst.REMOVEITEM = 'ALL'
  local is_indexed = (rawget(tbl, 1) ~= nil)

  if is_indexed then
    for k, v in ipairs(tbl) do
      lst[tostring(k)] = v
    end 
  else
    local i = 1
    for k, _ in pairs(tbl) do
      lst[tostring(i)] = k
      i = i + 1
    end
  end

end

function crtList(tbl)
-- Create a list and set:
  local lst        = iup.list{}

  -- contents
  bldList(lst, tbl)

  -- bld options
  -- lst.normalizergroup = options.norm
  -- not editable
  lst.editbox      = 'NO'
  -- pre-sorted in this case
  lst.sort         = 'NO'
  -- dropdown 
  lst.dropdown     = 'YES' 
  -- # of visible items 
  lst.visibleitems = 12
  -- expansion
  lst.expand       = 'HORIZONTAL'
  -- multiple selectoin
  lst.multiple     = 'NO' 

  -- bld callbacks
  -- lst.action       =   function(self, text, item, state) end
  return lst
end

function GetSingleValue(list)
  local function choose(cond, value)
    return cond and value
  end

  return choose(list.value ~=0, list[tostring(list.value)])
end      

function sltTAG(tbl)
  tags = crtList(tbl)

  -- Creates frame with dropdown list and sets its title
  local rtx
  local btn_ok = iup.button
  {
    name   = 'OK',
    title  = 'OK', 
    action = function(self) 
      TAG = GetSingleValue(tags)
      for _, v in ipairs(tbl) do
        if TAG == v then
          rtx  = self.name 
          return iup.CLOSE
        end
      end
    end
  }
  local btn_cancel = iup.button
  {
    name   = 'CANCEL',
    title  = 'CANCEL', 
    action = function(self) 
      rtx  = self.name 
      return iup.CLOSE
    end
  }
  
-- Creates a dialog with the frame and sets its title
  dlg = iup.dialog 
  {
    iup.frame
    {
      iup.vbox 
      {
        tags,

        iup.hbox
        {
          btn_ok,
          btn_cancel
        },     
      },
    },

    title = 'Select TAG',
    size  = 'QUARTERxEIGHTH'
  }

  return dlg
end -- fn sltTAG

-- MAIN()
tbl     = bldTAGS()
dlg     = sltTAG(tbl)
-- dspws()

do

  dlg:showxy(iup.CENTER, iup.CENTER)
  iup.MainLoop()
  print('2: ' .. TAG or 'nil')
  dlg:destroy()
  print('3: ' .. TAG or 'nil')
end

--[[
rc, TAG = sltTAG()
if rc == WS_CANCEL then
  return
end
]]
FH V.6.2.7 Win 10 64 bit

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 04 Jul 2020 18:04

solved (the code, not the problem of visibleitems not working) with:

size = '164x' although you really dont need the x, the documentation is wrong on this point.
and
dropdown ='no'
visiblelines = '12'
FH V.6.2.7 Win 10 64 bit

User avatar
tatewise
Megastar
Posts: 18445
Joined: 25 May 2010 11:00
Family Historian: V6.2
Location: Torbay, Devon, UK
Contact:

Re: IUP again

Post by tatewise » 04 Jul 2020 18:15

lst.visible_items = 12 should work, as it must be a number not a string.

There is a small typo in the documentation that omits the underscore, but the examples use visible_items

If you set dropdown = 'no' then it is working in a different mode and visible_items is not used.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry

User avatar
Ron Melby
Megastar
Posts: 585
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: IUP again

Post by Ron Melby » 04 Jul 2020 20:06

that would explain some issues, but did that, and it was icky,
the entire list came up and gone was my frame and gone was my buttons no way to get too them
and that was with the number 12 the iup did not respect that.

so I went back to the way I had working, and I think that for now, I can live with it, did some minor tweak and cleanup and its going into _STD_SLT

(Standard Select) one of my require boilerplates
Untitled.png
Untitled.png (132.12 KiB) Viewed 42 times
FH V.6.2.7 Win 10 64 bit

Post Reply