How to use one list to populate many identical, but independent, menus?

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

Post Reply
scott93933
Posts: 3
Joined: Sat May 29, 2021 7:56 pm

How to use one list to populate many identical, but independent, menus?

Post by scott93933 » Mon Aug 16, 2021 12:58 am

Apologies, as I'm sure this info is probably already out there, but several Google searches and LC forum searches and LC tutorial searches have landed me in topics that are related to what I'm looking for, but unfortunately not close enough.

Here's what I've done so far:
I've created a scrolling list field and have added a field below it for adding items to the scrolling list field, as well as a button to trigger the script. The script compares the proposed new item the user has input with the contents of the existing scrolling list field and then adds the new item to the list only if it's unique. Then the list gets sorted (alphabetized) and the field for adding the new item is cleared, so another new item can be added to the list. So this is a simple interface for managing a list.

Here's my challenge:
I want to create pull-down menus on various cards that will be populated with the contents of the aforementioned scrolling list field. Each pull-down menu has to be independent so that on one card, a user can select the fifth item in the menu and on another card they can select the first item in the menu, as an example. If the contents of the scrolling list field change, all pull-down menus that are based on the scrolling list field need to change automatically.

Any help will be greatly appreciated!
Cheers,
Scott

kdjanz
Posts: 300
Joined: Fri Dec 09, 2011 12:12 pm
Location: Fort Saskatchewan, AB Canada

Re: How to use one list to populate many identical, but independent, menus?

Post by kdjanz » Mon Aug 16, 2021 5:12 am

I think the first thing you need to separate in your mind is the DATA vs the DISPLAY of the data. Where does your list really live ie. where is the master copy that is always correct?

Simple Solution :
If it is in the field, then all the other locations that use the data must refer back to that master field.

Global Solution:
As another solution, the list could live in a global variable which is then accessible from every card or location that needs to use it. So when a new item is added to the list on the edit card, it updates and sorts the global variable. Only when the global variable is up to date (the master location), does the script then go on to update the field to display it to the user. All the other cards and locations just use the global variable in whatever way they need to and then they update the global variable as well. Since variables lose their values between runs of the program, you will need to store your list somewhere and then reinstate the global as part of your startup routine for the program. You could use a custom property on the first card of the stack, or you could ensure your list field is updated to match the global and then save the stack before quitting.

External Solution:
Another solution to saving the current state of the global would be to write the global variable to disk in the user's Documents folder. On startup, your program can look for the file in the special location and then read it into the global variable. This would be especially important in the security restricted mobile environment, because the main stack on mobile is not allowed to change and therefore you can't save the main stack. It is signed and sealed and can't change - so all information that does change has to be saved externally. You can write this external file as a simple return delimited text file that is easy to read right back into a field, or you could write it as an encrypted binary file if it contains personal or protected information. You have lots of choices depending on your needs.

But the critical starting point is to separate the idea of the data from the users of the data. The data should only exist in one place, and all the manipulations that form it into menu views or list views or sort it or calculate with it find it in that one place at the beginning of the script and then they return it and update to that one place at the end of the script. That one place is always up to date and is always the single source of truth throughout your program.

Hope that helps

Kelly

AxWald
Posts: 578
Joined: Thu Mar 06, 2014 2:57 pm

Re: How to use one list to populate many identical, but independent, menus?

Post by AxWald » Mon Aug 16, 2021 8:57 am

Hi,

adding to what Kelly said, maybe an example:
  1. The content of your menu needs some more information, so let it be:

    Code: Select all

       [MenuTitle]tab[MenuCommand]tab[MenuSelector]CR
       ...
    where MenuCommand is what is send when the menu is choosen, and MenuSelector is a space-delimited list of chars that determine on what cards this line shall be shown.
    Your "menuField" has its TabStop set at the right edge so only the MenuTitle is visible.
    .
  2. At StartUp time you read your menu from [somewhere], and:

    Code: Select all

       set the cMenu of this stack to myMenuData
    This way it's available from everywhere.
    .
  3. At OpenCard the card sets up its menu:

    Code: Select all

       set the cData of fld "menuField" of me to the cMenu of this stack
    Which triggers a setProp handler in the menuField that filters the lines of the menu:
    Each card has its "the cMenuSelector" - if this is contained in MenuSelectors than this line matches.
    Then it populates itself :

    Code: Select all

       setProp cData theData
          set itemdel to tab
          put the cMenuSelector of this cd into mySelector
          repeat for each line L in theData
             if mySelector is among the words of item 3 of L then put L & CR after myMenu
          end repeat
          put char 1 to -2 of myMenu into me
          pass cData
       end cdata
    .
  4. Finally, when a selection in the field is made, it responds in a mouseUp handler:

    Code: Select all

       set itemdel to tab
       dispatch item 2 of line (the hilitedLine of me) of me to this cd
    For sure, a handler should be ready to receive the MenuCommand we dispatched.
This way it works with quite few code. The code of the menu field just asks for residing in hidden button somewhere & be used as behavior ;-)

Have fun!
All code published by me here was created with Community Editions of LC (thus is GPLv3).
If you use it in closed source projects, or for the Apple AppStore, or with XCode
you'll violate some license terms - read your relevant EULAs & Licenses!

Post Reply

Return to “Getting Started with LiveCode - Complete Beginners”