Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
-
Simon Knight
- Posts: 845
- Joined: Wed Nov 04, 2009 11:41 am
- Location: Gunthorpe, North Lincs, UK
Post
by Simon Knight » Sun Feb 19, 2017 4:43 pm
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
Code: Select all
put the long id of button 5 into tTemp or put the long id of field 5 into tTemp
I have read about the Value command but I am uncertain how to use it in the following example.
Code: Select all
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
Any thoughts?
Simon
best wishes
Skids
-
dunbarx
- VIP Livecode Opensource Backer
- Posts: 9578
- Joined: Wed May 06, 2009 2:28 pm
- Location: New York, NY
Post
by dunbarx » Sun Feb 19, 2017 5:39 pm
Hi.
I guess I understand what you want to do.
Does this help at all, perhaps in a button script somewhere:
Code: Select all
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:
Code: Select all
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
Craig Newman
-
Simon Knight
- Posts: 845
- Joined: Wed Nov 04, 2009 11:41 am
- Location: Gunthorpe, North Lincs, UK
Post
by Simon Knight » Sun Feb 19, 2017 5:52 pm
Hi Craig,
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
Code: Select all
repeat with Counter = 1 to the number of pType of this card
to work with ptype being a variable? So that livecode sees
Code: Select all
repeat with Counter = 1 to the number of buttons of this card
or
Code: Select all
repeat with Counter = 1 to the number of fields of this card
depending on what is passed into the function in pType.
best wishes
Skids
-
dave.kilroy
- VIP Livecode Opensource Backer
- Posts: 858
- Joined: Wed Jun 24, 2009 1:17 pm
- Location: Plymouth, UK
-
Contact:
Post
by dave.kilroy » Sun Feb 19, 2017 6:34 pm
Hi Simon, the following code functions and may give you enough to get you to where you want to go...
Code: Select all
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
"...this is not the code you are looking for..."
-
dunbarx
- VIP Livecode Opensource Backer
- Posts: 9578
- Joined: Wed May 06, 2009 2:28 pm
- Location: New York, NY
Post
by dunbarx » Sun Feb 19, 2017 7:08 pm
Simon.
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:
Code: Select all
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?
Craig
-
[-hh]
- VIP Livecode Opensource Backer
- Posts: 2262
- Joined: Thu Feb 28, 2013 11:52 pm
- Location: Göttingen, DE
Post
by [-hh] » Sun Feb 19, 2017 11:57 pm
Here a slightly different solution:
You could try to "generalize" your work _within_ the loop, leaving the enumerating of the loop "concrete".
Code: Select all
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
shiftLock happens
-
Simon Knight
- Posts: 845
- Joined: Wed Nov 04, 2009 11:41 am
- Location: Gunthorpe, North Lincs, UK
Post
by Simon Knight » Mon Feb 20, 2017 8:14 am
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:
Code: Select all
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.....
Code: Select all
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
Thanks
Simon K
best wishes
Skids
-
dunbarx
- VIP Livecode Opensource Backer
- Posts: 9578
- Joined: Wed May 06, 2009 2:28 pm
- Location: New York, NY
Post
by dunbarx » Tue Feb 21, 2017 6:53 pm
Simon.
You have "done" it correctly.
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.
Oy. So many quotes.
Craig
-
Simon Knight
- Posts: 845
- Joined: Wed Nov 04, 2009 11:41 am
- Location: Gunthorpe, North Lincs, UK
Post
by Simon Knight » Wed Feb 22, 2017 8:03 am
I am still not sure why you still say that the variable cannot be, er "variable",
Because I was wrong! excuses excuses...... late at night mind set........ need coffee etc etc
Thanks again for all the help,
best wishes
Simon K
best wishes
Skids
-
Simon Knight
- Posts: 845
- Joined: Wed Nov 04, 2009 11:41 am
- Location: Gunthorpe, North Lincs, UK
Post
by Simon Knight » Wed Feb 22, 2017 8:33 am
Here is the function I ended up with :
Code: Select all
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
Thanks yet again
best wishes
Skids
-
Thierry
- VIP Livecode Opensource Backer
- Posts: 875
- Joined: Wed Nov 22, 2006 3:42 pm
Post
by Thierry » Wed Feb 22, 2017 11:20 am
Hi Simon,
Here is a variation of your latest script.
Take or Drop whatever you want.
Regards,
Thierry
Code: Select all
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.
!
-
Simon Knight
- Posts: 845
- Joined: Wed Nov 04, 2009 11:41 am
- Location: Gunthorpe, North Lincs, UK
Post
by Simon Knight » Thu Feb 23, 2017 10:03 am
Hi Thierry,
Thank you for your refactored version of my script. In it you have used constructs that I did not know were allowed e.g.
Code: Select all
put (pGroupName is empty) into ignoreInGroup
and your use of the filter command to reduce the list size is very elegant. My only concern is the use of the single line if statements :
Code: Select all
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.
I have learned a lot - thanks,
best wishes
Simon K
best wishes
Skids
-
Thierry
- VIP Livecode Opensource Backer
- Posts: 875
- Joined: Wed Nov 22, 2006 3:42 pm
Post
by Thierry » Thu Feb 23, 2017 10:21 am
Simon Knight wrote:Hi Thierry,
I have learned a lot - thanks,
best wishes
Hi Simon,
You're welcome.
Reading other's code from time to time
is a good exercise to open our mind....
and after that, we do what we like
If you feel the "end if" is missing, than add it and here you go....
Good luck with your project,
Thierry
!
SUNNY-TDZ.COM doesn't belong to me since 2021.
To contact me, use the Private messages. Merci.
!
-
Klaus
- Posts: 13806
- Joined: Sat Apr 08, 2006 8:41 am
- Location: Germany
-
Contact:
Post
by Klaus » Thu Feb 23, 2017 3:37 pm
Hi Simon,
short note:
Do not use IT (get xyz...) unless really neccessary!
IT wil change when you least exspect IT!
Best
Klaus
-
Thierry
- VIP Livecode Opensource Backer
- Posts: 875
- Joined: Wed Nov 22, 2006 3:42 pm
Post
by Thierry » Thu Feb 23, 2017 5:10 pm
Klaus wrote:
short note:
Do not use IT (get xyz...) unless really neccessary!
IT wil change when you least exspect IT!
another short note:
Learn when IT will change and how to use IT and then you're free...
I'm using IT quite a lot since many years on numerous professional projects
without any trouble and I love IT
Best,
Thierry
!
SUNNY-TDZ.COM doesn't belong to me since 2021.
To contact me, use the Private messages. Merci.
!