I have a project that uses two near identical functions that I would like to merge into a single function. The two functions examine either the buttons or the fields on a card. The challenge is to merge the two functions into one and use a parameter to switch between fields and buttons. I don't want to use an if statement as this does not reduce the complexity in any way instead I wish to use the passed in value as part of a statement. In the non working code below the switch variable passed into the function is pType and I would like livecode to evaluate my lines as, for example
Function LoopObjects pType
# pType is a string either "Field" or "Button"
repeat with Counter = 1 to the number of pType of pLongIDCardOrGroup
put cr & (the long name of pType counter) after tTemp
end repeat
return avalue
end LoopObjects
on mouseUp
repeat with y = 1 to the number of controls
if the long name of control y contains "button" then add 1 to b
else if the long name of control y contains "field" then add 1 to f
end repeat
answer b && f
end mouseUp
Now if you see how this works, that is, how it examines everything and distinguishes fields and buttons among all possible controls, you might insert your own gadgetry, something like:
on mouseUp
repeat with y = 1 to the number of controls
if the long name of control y contains "button" then doButtonStuff
else if the long name of control y contains "field" then doFieldStuff
end repeat
end mouseUp
I'm sorry but it is not quite what I was after. My actual functions are quite complex and one is the twin of the other except that one refers to buttons and the other to fields. So my aim was to merge the two functions into one and get rid of a load of code. So for example is it possible to get the line
on mouseUp
put word 1 of the long name of control 1 into tType
put LoopObjects(tType)
end mouseUp
Function LoopObjects pType
repeat with Counter = 1 to the number of controls in the current card
if word 1 of the long name of control Counter = pType then put cr & the long name of control counter after tTemp
end repeat
return tTemp
end LoopObjects
What you are asking for cannot simply be that the type of control is placed in a variable, as Dave suggested, as opposed to being explicitly derived in a loop. This hardly simplifies or compacts anything at all.
Is it just a slight bit of compaction that you are looking for? Try this in a button, on a card that contains both fields and buttons and some other controls:
on mouseUp
repeat with y = 1 to the number of controls
if the long name of control y contains "button" or the long name of control y contains "field"\
then doStuff (the long name of control y)
end repeat
end mouseUp
on doStuff tControlType
if tControlType contains "button" then
set the backColor of tControlType to any item of "red,yellow,green,blue,orange"
else
do "put random(9999) into" && tControlType
end if
end doStuff
Do you know why you have to use a "do" construction to make this work?
function dojob obj -- param obj is the long id of a field or button
put (the long name of obj) & cr after tTemp
put (the backcolor of obj) & cr after tTemp
...
return tTemp
end dojob
function loopObjects pType
if pType is "field" then
repeat with i = 1 to the number of fields of pLongIDCardOrGroup
put dojob(the long id of field i of pLongIDCardOrGroup) after tReturn
end repeat
else
repeat with i = 1 to the number of buttons of pLongIDCardOrGroup
put dojob(the long id of button i of pLongIDCardOrGroup) after tReturn
end repeat
end if
return tReturn
end loopObjects
Hi, thanks for all your replies and the confirmation that it is not possible to use a variable in the way I hoped. I have included a copy of one of my functions which I accept needs refactoring with some of the ideas given above; specifically extracting the type of control, button or field from the long name of the control.
Craig, you ask if I understand why the "Do" is needed ? My answer is maybe! I believe that the do statement means treat all that follows as an expression that needs evaluating before it is then executed:
put "field " & quote & "debug" & quote into tControl
-- put random(9999) into tControl -- no error raised if only line but causes error to be raised on next line
do "put random(9999) into" && tControl -- this works
Have I understood ?
An example of the rather complex dedicated function which I shall rewrite later today.....
Function GetButtonScripts pLongIDCardOrGroup, pStackName, pCardName, pGroupName
# Function that extracts the scripts from the buttons on the stack/card/group passed in.
put empty into tText
if pStackName is empty then
return False
else
Put "***! Stack:" & pStackName into tHeader
end if
if pCardName is empty then
return False
else
Put ":Card:" & pCardName after tHeader
end if
# Either dealing with buttons on a card or within a group (on a card)
if pGroupName is empty then
# process the buttons on the card ignore those in groups
put the number of buttons of pLongIDCardOrGroup into tItemCount
repeat with btnCounter = 1 to the number of buttons of pLongIDCardOrGroup
put the long name of button (btncounter) of pLongIDCardOrGroup into tTemp
if the long id of button btncounter of pLongIDCardOrGroup contains "group" then
-- ignore
else
put tHeader & ":Button:" & (the short name of button btncounter of pLongIDCardOrGroup) into tButtonHeader
put (the script of button btncounter of pLongIDCardOrGroup) into tButtonScript
# Only save an entry if the button has a script
if tButtonScript is not empty then put tButtonHeader & cr & tButtonScript & cr after tText
end if
end repeat
else
# process the button in the group, ignore those on the card
Put ":Group:" & pGroupName after tHeader
repeat with btnCounter = 1 to the number of buttons of pLongIDCardOrGroup
if the long id of button btncounter of pLongIDCardOrGroup contains "group" then
put tHeader & ":Button:" & (the short name of button btncounter of pLongIDCardOrGroup) into tButtonHeader
put (the script of button btncounter of pLongIDCardOrGroup) into tButtonScript
# Only save an entry if the button has a script
if tButtonScript is not empty then put tButtonHeader & cr & tButtonScript & cr after tText
end if
end repeat
end if
return tText
end GetButtonScripts
But among the several example approaches offered, I am still not sure why you still say that the variable cannot be, er "variable", in that it can reference, albeit with a little kluging, any control class, and hold that specific class within itself while you make it do actual work for you.
The "do" construction is what allows that, to evaluate twice, so that the "implicate" control reference is extracted "from within" the actual "working" line of code.
Function GetControlScripts pLongIDCardOrGroup, pStackName, pCardName, pGroupName
# Function that extracts the scripts from the buttons on the stack/card/group passed in.
put empty into tText
if pStackName is empty then
return False
else
Put "***! Stack:" & pStackName into tHeader
end if
if pCardName is empty then
return False
else
Put ":Card:" & pCardName after tHeader
end if
# Either dealing with buttons on a card or within a group (on a card), pGroupName is used as the switch var
if pGroupName is empty then
# processing the controls on the card - ignore any with group in their long name/id
repeat with Counter = 1 to the number of controls of pLongIDCardOrGroup
put the long id of control counter of pLongIDCardOrGroup into tLongID
if tLongID contains "group" then
next repeat
end if
# tLongID refers to a control on the card and not in a group
If tLongID contains "field" Or tLongID contains "button" then
put ":" & the first word of tLongID & ":" into tType -- field or button
put tType & (the short name of control counter of pLongIDCardOrGroup) into tHeaderSuffix
put (the script of control counter of pLongIDCardOrGroup) into tScript
# Only save an entry if the control has a script
if tScript is not empty then put tHeader & tHeaderSuffix & cr & tScript & cr after tText -- one line if
end if
end repeat
else
# process the button in the group, ignore those on the card
Put ":Group:" & pGroupName after tHeader
repeat with Counter = 1 to the number of controls of pLongIDCardOrGroup
put the long id of control counter of pLongIDCardOrGroup into tLongID
If tLongID contains "field" Or tLongID contains "button" then
put ":" & the first word of tLongID & ":" into tType -- field or button
if tLongID contains "group" then
put tType & (the short name of control counter of pLongIDCardOrGroup) into tHeaderSuffix
put (the script of control counter of pLongIDCardOrGroup) into tScript
# Only save an entry if the button has a script
if tScript is not empty then put tHeader & tHeaderSuffix & cr & tScript & cr after tText -- one line if
end if -- contains group
end if -- contains either field or button
end repeat -- loop through all the controls on the card
end if -- Check if working with controls on the card or the group
return tText
end GetControlScripts
Function controlScripts pLongIDCardOrGroup, pStackName, pCardName, pGroupName
# extracts scripts from buttons on the stack/card/group passed in.
local tHeader, tText
local ignoreInGroup, listOfControls, theScript
if pStackName is empty then return false
if pCardName is empty then return false
put (pGroupName is empty) into ignoreInGroup
put "***! Stack:" & pStackName & ":Card:" & pCardName into tHeader
# get list of all control
repeat with Nc = 1 to the number of controls of pLongIDCardOrGroup
put the long id of control Nc of pLongIDCardOrGroup &cr after listOfControls
end repeat
# keep only buttons and fields
filter listOfControls with regex pattern "^(button|field)"
# keep controls in OR not in a group
if ignoreInGroup then filter listOfControls without "*group*"
else filter listOfControls with "*of group*"
repeat for each line aControl in listOfControls
put the script of aControl into theScript
if theScript is empty then next repeat
if ignoreInGroup then get tHeader & ":"
else get tHeader & ":Group:" & pGroupName & ":"
put IT & word 1 of aControl & ":" & the short name of aControl &cr after tText
put theScript & cr after tText
end repeat
return tText
end controlScripts
! SUNNY-TDZ.COM doesn't belong to me since 2021.
To contact me, use the Private messages. Merci.
!
if theScript is empty then next repeat
if ignoreInGroup then get tHeader & ":"
else get tHeader & ":Group:" & pGroupName & ":"
again I was not aware that the else statement could be used in this way also I am so use to expecting an if to be finished with an end if that your lines seem strange and alien.