Cards controls loop?
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
Re: Cards controls loop?
Regarding those trees that fill the forest.
I use the "Find and Replace" gadget constantly. It allows me to identify the one or more objects that contain the string of interest. One can navigate to those objects one by one, and using the SE find tools, locate the string's occurrences one by one.
But that is not always what I need, and I believe the OP wants something rather different as well. He asked for all occurrences of a string everywhere. Not just which objects contain it, but where they are in every place that they are.
That is why I never thought of suggesting "Find and Replace...", rather to go down the path of creating a "look everywhere" procedure that would identify all the string "locations" everywhere. My offering, from HC days, was woefully inadequate, but did suggest the method of navigating through all possible string-containing objects. That old gadget missed groups, of course.
Anyway, that is the right method, and a really good implementation would return something like the OP originally posted, a list of all objects that contain the string, along with all its locations within each script, as well as perhaps a few lines before and after the string for context.
Craig
I use the "Find and Replace" gadget constantly. It allows me to identify the one or more objects that contain the string of interest. One can navigate to those objects one by one, and using the SE find tools, locate the string's occurrences one by one.
But that is not always what I need, and I believe the OP wants something rather different as well. He asked for all occurrences of a string everywhere. Not just which objects contain it, but where they are in every place that they are.
That is why I never thought of suggesting "Find and Replace...", rather to go down the path of creating a "look everywhere" procedure that would identify all the string "locations" everywhere. My offering, from HC days, was woefully inadequate, but did suggest the method of navigating through all possible string-containing objects. That old gadget missed groups, of course.
Anyway, that is the right method, and a really good implementation would return something like the OP originally posted, a list of all objects that contain the string, along with all its locations within each script, as well as perhaps a few lines before and after the string for context.
Craig
Re: Cards controls loop?
With all your ideas and different tests, here is what I finally did. It is not necessarily the fastest solution - and the script can probably be optimized - but it meets my different needs.
For searching for occurrences in the scripts of the controls, the globalMatch() function presented by Stam can be interesting as it allows to search with regex:
https://github.com/stam66/regexPrimerFo ... workaround
In a first try, I used the long IDs of the controls but this is not a good idea in the case where we want to store the sizes and positions of the controls because if the stack is moved, the long IDs will no longer be valid.
Code: Select all
function getStackControlList pStackName
/*
return a tab-cr delimited list of all controls of passed stack and its sub-stacks
one line per control with data separated by tab
1 - control kind ("stack", "group", "card", "button", ...)
2 - control short name
3 - control short ID
4 - owner stack short name
5 - owner main stack short name (same as #4 if the searched stack is a main stack)
6 - owner card short name (or empty if not available)
return empty if passed stack not exists
*/
local controlsList
if (pStackName <> "") then controls_stacks controlsList, pStackName
return controlsList
end getStackControlList
private command controls_stacks @controlsList, mainStackName
if (there is a stack mainStackName) then
---------------------------------- main stack
controls_inStack controlsList, mainStackName
---------------------------------- sub stacks
repeat for each line thisSubStackName in the substacks of stack mainStackName
controls_inStack controlsList, thisSubStackName
end repeat
end if
end controls_stacks
private command controls_inStack @controlsList, stackName
// update controlsList with all controls of passed stack
---------------------------------- passed stack
controls_updateResult controlsList, stackName, "", the long id of stack stackName
---------------------------------- cards of passed stack
local cardLongId, cardName
repeat with c = 1 to (the number of cards in stack stackName)
put the short name of card c of stack stackName into cardName
---------------- cards
put the long id of card c of stack stackName into cardLongId
controls_updateResult controlsList, stackName, cardName, cardLongId
---------------- cards controls (including groups)
repeat with n = 1 to (the number of controls in cardLongId)
controls_updateResult controlsList, stackName, cardName, the long id of control n of cardLongId
end repeat
end repeat
end controls_inStack
on controls_updateResult @controlsList, @stackName, cardName, controlLongId
// update controlsList : one line per control, with data separated by tab
// 1 - kind 2 - name 3 - ID 4 - stack name 5 - mainStack name 6 - card name
get word 1 of controlLongId & tab & the short name of controlLongId & tab & the id of controlLongId & tab & \
stackName & tab & the mainStack of stack stackName & tab
if (it is not in controlsList) then put it & cardName & cr after controlsList
end controls_updateResult
https://github.com/stam66/regexPrimerFo ... workaround
In a first try, I used the long IDs of the controls but this is not a good idea in the case where we want to store the sizes and positions of the controls because if the stack is moved, the long IDs will no longer be valid.
Re: Cards controls loop?
Hi Zax,
You could use the "ruggedID". The IDE has a function that returns the ruggedID
example
Code: Select all
on mouseUp
put revRuggedID (the long id of control 1 of this card)
end mouseUp
It has only the ID and the stack name. That also works the other way around:control id 1006 of stack "testStackZaxScriptSearch"
Code: Select all
put the long id of control id 1006 of stack "testStackZaxScriptSearch"
If you do not want to use the built-in function it is easy to construct a rugged ID on the fly.
Kind regards
Bernd
Re: Cards controls loop?
Interesting! I had noticed the use of ruggedID() in your scripts but I had not looked in detail at what this function did.
Thanks Bernd

I'll do some more testing but it seems to me that sometimes the backgroundIDs returns groups that don't appear in the IDE's Project Browser.
Re: Cards controls loop?
I couldn't find revRuggedID() in my Dictionary.
Bob
Bob
Re: Cards controls loop?
bernd:
Okay, thanks.
Bob
Okay, thanks.
Bob
Re: Cards controls loop?
as far as I can tell, it returns a generic "control id xx of <stack>", instead of a long id. The id is the same, just abstracted to 'control' instead of the specific control type (eg 'button', 'field', etc). Not sure this is any different from simply storing the id?
Re: Cards controls loop?
Hi Stam,stam wrote: ↑Mon Aug 12, 2024 2:58 pmas far as I can tell, it returns a generic "control id xx of <stack>", instead of a long id. The id is the same, just abstracted to 'control' instead of the specific control type (eg 'button', 'field', etc). Not sure this is any different from simply storing the id?
Zax worried about the long ID being dependent on the file name and location.
Rugged ID (control id xxx of stack "yz") does is not dependent on file name and location and is unique and can be transformed into other forms of reference to objects.
LC uses it to reference behaviours for pretty much the reasons described above.
Nothing more, nothing less.
Kind regards
Bernd
Re: Cards controls loop?
I only just noticed this but at first glance it loos like subStacks don't have a separate ID?
Seems to be 1002 for all subStacks, the same as any new stack -- is this right?
revRuggedID returns the name of the stack, so since there is no id to rely on, this definitely seems useful... learned something new again

Re: Cards controls loop?
Very interesting point!
I just reread the Dictionary and, when it says "For all objects, the ID is guaranteed to be unique within a stack", I think that it means "stack" in the strict sense of the term: a substack is a stack. I hadn't paid attention to that and I thought that an ID was unique for a stack and all its substacks.
Reading the Dictionary also allowed me to rediscover "the abbreviated id" which corresponds for example to "field id 1365".
Re: Cards controls loop?
But here is where revRuggedID() is probably better. As the ID is only guaranteed to be unique within a single stack, you cannot key an array to the ID in more than one stack - eg substacks - and maintain unique identifiers.
Let alone if you wanted to make a script that checked a project instead of a stack, which would mean also including library stacks and front/backscripts where these are stacks as well.
Sounds complicated but probably much less than appears.
Let alone if you wanted to make a script that checked a project instead of a stack, which would mean also including library stacks and front/backscripts where these are stacks as well.
Sounds complicated but probably much less than appears.
Re: Cards controls loop?
Right.
Re: Cards controls loop?
Hi all,
Due to popular demand (N=1) I post an improved version of "SearchScripts"
Changes:
all entries are shown by ID (previously I had a mix of IDs and names and card number, especially card number would be invalid of cards are sorted after running "SearchScripts)
controls are sorted by layer.
cards are sorted by position in stack
background groups are reported for the first card where they are placed (previously last occurrence)
A tooltip shows the long name of an entry.
As before click on a line in the display field to go to first occurrence of search term in the script, if more than one occurrence click on the trailing numbers.
Some cleanup.
Kind regards
Bernd
Due to popular demand (N=1) I post an improved version of "SearchScripts"
Changes:
all entries are shown by ID (previously I had a mix of IDs and names and card number, especially card number would be invalid of cards are sorted after running "SearchScripts)
controls are sorted by layer.
cards are sorted by position in stack
background groups are reported for the first card where they are placed (previously last occurrence)
A tooltip shows the long name of an entry.
As before click on a line in the display field to go to first occurrence of search term in the script, if more than one occurrence click on the trailing numbers.
Some cleanup.
Kind regards
Bernd
- Attachments
-
- searchScripts_04_BN.livecode.zip
- (3.38 KiB) Downloaded 293 times
Re: Cards controls loop?
Thanks Bernd, will definitely look at your solution.
I have not yet seen your solution, as was writing my own as an interesting mental exercise
But I've not implemented this as a search, just as a way to create an array with all objects and their scripts.
I moved this from stack level to project level, meaning I look at all stacks, subStacks, stacksInUse, frontScripts and backScripts, excluding IDE stacks and stacks residing in Plugins/Extensions folders. I have no use for this directly at present, but was an interesting exercise. At the very least, it's a way to count the number of lines in my apps!
This script returns an array that is keyed to the revRuggedID() of each object that can contain a script:
the helper command to exclude IDE/Plugin/Extension stacks from lists passed by reference:
The first script passes a stack to a 2nd command by reference, which then processes stacks/cards/objects and adds to the array:
seems to work fine (and in a small test stack, very quickly, but not tested large complex solution yet).
I used a tree control to visualise the results.
I would envisage a search function being filtering this array by the ["script"] key to generate a list - but I'm sure your solution is probably quite a lot faster...
For now this is just a mental exercise for me, but any suggestions to improve would be gratefully received...
Stam
I have not yet seen your solution, as was writing my own as an interesting mental exercise

But I've not implemented this as a search, just as a way to create an array with all objects and their scripts.
I moved this from stack level to project level, meaning I look at all stacks, subStacks, stacksInUse, frontScripts and backScripts, excluding IDE stacks and stacks residing in Plugins/Extensions folders. I have no use for this directly at present, but was an interesting exercise. At the very least, it's a way to count the number of lines in my apps!
This script returns an array that is keyed to the revRuggedID() of each object that can contain a script:
Code: Select all
function analyseStacks
local tStackLongID, tSubStacks, tStackList, tObjectListA
put the stacks into tStackList
_removeIDEstacks tStackList
repeat for each line tStack in tStackList
put the long id of stack tStack into tStackLongID
getObejcts the long id of stack tStack, tObjectListA
// stacksInUse / Libraries
put the stacksInUse into tStackList
_removeIDEstacks tStackList
repeat for each line tStack in tStackList
getObejcts the long id of stack tStack, tObjectListA
end repeat
// substacks
put the substacks of tStackLongID into tSubStacks
repeat for each line tStack in tSubStacks
getObejcts (revRuggedID(the long id of stack tStack of tStackLongID)), tObjectListA
end repeat
// front and backscripts
put the frontScripts into tStackList
put return & the backScripts after tStackList
_removeIDEstacks tStackList
repeat for each line tStack in tStackList
if word 1 of tStack is "stack" then getObjects the long id of stack tStack, tObjectListA
end repeat
end repeat
//return array with all objects that can have scripts and their scripts
return tObjectListA
end analyseStacks
Code: Select all
private command _removeIDEstacks @pStackList -- remove IDE or plugin/extension stacks
filter pStackList without "*/Extensions/*"
filter pStackList without "*/Plugins/*"
filter pStackList without "*/tools/toolset/*"
filter pStackList without "*/tools/ext/*"
filter pStackList without empty
// can add a line to exclude this script if implemented as a library for example
end _removeIDEstacks
Code: Select all
command getObejcts stackRuggedID, @pObjectListA -- build array with objects & scripts of each stack
local tStack, tCard, tControlID, tCardIDs
//stack
put stackRuggedID into tStack
put the long name of stackRuggedID into pObjectListA[tStack]["longOwner"]
put the short name of stackRuggedID into pObjectListA[tStack]["owner"]
put the script of stackRuggedID into pObjectListA[tStack]["script"]
//cards
put the cardIDs of tStack into tCardIDs
repeat for each line tCardID in tCardIDs
put revRuggedID(the long id of card id tCardID of tStack) into tCard
put the long id of tCard into pObjectListA[tCard]["longOwner"]
put the short name of tCard into pObjectListA[tCard]["owner"]
put the script of tCard into pObjectListA[tCard]["script"]
// controls
repeat with y = 1 to the number of controls of tCard
put revRuggedID(the long id of control y of tCard) into tControlID
put the long id of tControlID into pObjectListA[tControlID]["longOwner"]
put the short name of tControlID into pObjectListA[tControlID]["owner"]
put the script of tControlID into pObjectListA[tControlID]["script"]
end repeat
end repeat
end getObejcts
I used a tree control to visualise the results.
I would envisage a search function being filtering this array by the ["script"] key to generate a list - but I'm sure your solution is probably quite a lot faster...
For now this is just a mental exercise for me, but any suggestions to improve would be gratefully received...
Stam