Looking for an example stack of a address book, etc.

LiveCode is the premier environment for creating multi-platform solutions for all major operating systems - Windows, Mac OS X, Linux, the Web, Server environments and Mobile platforms. Brand new to LiveCode? Welcome!

Moderators: Klaus, FourthWorld, heatherlaine, robinmiller, kevinmiller

chuckm
Posts: 33
Joined: Sun Jun 19, 2016 12:30 am

Re: Looking for an example stack of a address book, etc.

Post by chuckm » Sat Aug 26, 2017 8:54 pm

Hmm, I can see that the data is being stored in the card but somehow I've mucked up getting the card names into the list. In my main stack I'm using the code:

Code: Select all

global gEditMode
global gTmpVals

function loadNameList
   -- clear list
   put empty in field "NameList"
   -- repopulate NameList control
   put the cardnames of this stack into field "NameList"
   -- sort list
   sort lines of field "NameList"
end loadNameList

on preStackOpen
   -- set the initial state of the gEditMode variable to indicate that
   -- initially the application is in read-only mode.
   put false into gEditMode
   
   -- ensure that the edit mode controls are hidden
   hide button "SaveContact"
   hide button "Cancel"
   
   -- ensure that the read-only mode controls are visible
   show button "CloseButton"
   show button "EditContact"
   
   -- load the names list (TBD)
   call "loadNameList()" of this stack
   
end preStackOpen
but I'm getting the error:

Code: Select all

stack "AddressBook": execution error at line 27 (Handler: error in statement), char 1
I isolated the list reload/sort business into a function on the stack level so that I'd only have to fiddle with it in one spot but I'm obviously still missing something. :-(

Hmm, the code below works inline in the handler but not as a function...

Code: Select all

put the cardnames of this stack into field "NameList"
sort lines of field "NameList"
The list is displayed as:

Code: Select all

+-------------------+
| card id 1002      |
| McKnight, Chuck   |
|                   |
|                   |
|                   |
|                   |
|                   |
|                   |
+-------------------+
If I do a put empty into field "NamesList" as the line before the put, it wipes out the contents of the NameList field even though it's called first. I guess it's not needed in that instance since I'm simply refilling the field based on the sorted list of cardnames. Just need to figure out some other name for card 1002 and then suppress that from the list.

Progress?

I would appreciate any thoughts on how to isolate the reload list functionality into a stack-wide function so that I don't have to chase things like that all over the place.

Thanks in advance!

Charles
Last edited by chuckm on Sat Aug 26, 2017 10:38 pm, edited 2 times in total.

bogs
Posts: 3381
Joined: Sat Feb 25, 2017 10:45 pm

Re: Looking for an example stack of a address book, etc.

Post by bogs » Sat Aug 26, 2017 10:23 pm

I made some (very minor) changes, it works as expected.

Code: Select all

    global gEditMode
    global gTmpVals

    on loadNameList // changed to handler...
       -- clear list
       put empty into field "NameList" //changed in to into...
       -- repopulate NameList control
       put the cardnames of this stack into field "NameList"
       -- sort list
       sort lines of field "NameList"
    end loadNameList

    on preStackOpen
       -- set the initial state of the gEditMode variable to indicate that
       -- initially the application is in read-only mode.
       put false into gEditMode
       
       -- ensure that the edit mode controls are hidden
       hide button "Save"
       hide button "Cancel"
       
       -- ensure that the read-only mode controls are visible
       show button "Close"
       show button "Edit"
       
       -- load the names list (TBD)
       loadNameList  // called handler...
       
    end preStackOpen
Image
Image

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4984
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Looking for an example stack of a address book, etc.

Post by jacque » Sat Aug 26, 2017 11:01 pm

LC functions generally return a value and loadNameList is just a series of commands that return nothing. It should work as a function anyway, but there's no need. But I suspect the problem was in using the "call" command, which changes the message hierarchy. "Call" is needed only under some very rare circumstances. LC's message hierarchy ensures that the command will pass through the message path in a specific order, starting with the object whose script is currently running. So all you need to do is issue "loadNameList" and it will be found. I think that's why bogs suggestion works.

The message hierarchy is a critical concept in LC, so if you aren't familiar with how it works you might want to look into it. When you issue a command, it's like pushing a sled off the top of a hill down a well-worn path. It just keeps going until it hits something.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

chuckm
Posts: 33
Joined: Sun Jun 19, 2016 12:30 am

Re: Looking for an example stack of a address book, etc.

Post by chuckm » Sat Aug 26, 2017 11:06 pm

bogs wrote:I made some (very minor) changes, it works as expected.

Code: Select all

    global gEditMode
    global gTmpVals

    on loadNameList // changed to handler...
       -- clear list
       put empty into field "NameList" //changed in to into...
       -- repopulate NameList control
       put the cardnames of this stack into field "NameList"
       -- sort list
       sort lines of field "NameList"
    end loadNameList

    on preStackOpen
       -- set the initial state of the gEditMode variable to indicate that
       -- initially the application is in read-only mode.
       put false into gEditMode
       
       -- ensure that the edit mode controls are hidden
       hide button "Save"
       hide button "Cancel"
       
       -- ensure that the read-only mode controls are visible
       show button "Close"
       show button "Edit"
       
       -- load the names list (TBD)
       loadNameList  // called handler...
       
    end preStackOpen
Image
Thanks! Still slogging away... :-)

chuckm
Posts: 33
Joined: Sun Jun 19, 2016 12:30 am

Re: Looking for an example stack of a address book, etc.

Post by chuckm » Sat Aug 26, 2017 11:09 pm

jacque wrote:LC functions generally return a value and loadNameList is just a series of commands that return nothing. It should work as a function anyway, but there's no need. But I suspect the problem was in using the "call" command, which changes the message hierarchy. "Call" is needed only under some very rare circumstances. LC's message hierarchy ensures that the command will pass through the message path in a specific order, starting with the object whose script is currently running. So all you need to do is issue "loadNameList" and it will be found. I think that's why bogs suggestion works.

The message hierarchy is a critical concept in LC, so if you aren't familiar with how it works you might want to look into it. When you issue a command, it's like pushing a sled off the top of a hill down a well-worn path. It just keeps going until it hits something.
Hi @jacque,

I've been studying the message path (it's up on my wall) and it works like all of the other object oriented things I've done in the past. I think I may be getting tripped up because the other languages I work in have the notion of a "void" function that returns nothing. So let me be sure that my understanding is correct:

1. Functions *must* return a value
2. Handlers do not return a value (and act like a "void" function in other languages

Now to quote a famous Englishman, "once more into the breach, dear friends..." :-)

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4984
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Looking for an example stack of a address book, etc.

Post by jacque » Sat Aug 26, 2017 11:09 pm

If I do a put empty into field "NamesList" as the line before the put, it wipes out the contents of the NameList field even though it's called first. I guess it's not needed in that instance since I'm simply refilling the field based on the sorted list of cardnames. Just need to figure out some other name for card 1002 and then suppress that from the list.
Handlers are executed one line at a time, in order. If the first line of the handler removes the text from the field, that will happen before the rest of the handler finishes. The order of the statements determines what you'll see.

You could use the first card as your first data card. When the user enters the first name/address, the handler can check to see if the string "card id" is in the card name, and if so, "set the name of this card to <whatever>". Or just name it something arbitrary like "main" and filter it out. That will work, but could introduce some navigation issues if the user is paging through the stack from the keyboard.
I would appreciate any thoughts on how to isolate the reload list functionality into a stack-wide function so that I don't have to chase things like that all over the place.
Put the handler in the stack script. It will be available to all cards that way. See "message path" above. :)
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4984
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Looking for an example stack of a address book, etc.

Post by jacque » Sat Aug 26, 2017 11:19 pm

chuckm wrote:So let me be sure that my understanding is correct:

1. Functions *must* return a value
2. Handlers do not return a value (and act like a "void" function in other languages
Functions aren't actually required to return a value, but that's their primary purpose in LC. And command handlers can also return values in "the result", but you need to specifically retrieve the result if you want it. The two types of handlers are very similar except for how you get values from them. If you look at the "return" control structure in the dictionary, you'll see a number of examples showing how it works.

Glad you grok the message path, I wasn't sure where you were at.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

bogs
Posts: 3381
Joined: Sat Feb 25, 2017 10:45 pm

Re: Looking for an example stack of a address book, etc.

Post by bogs » Sat Aug 26, 2017 11:40 pm

chuckm wrote:If I do a put empty into field "NamesList" as the line before the put, it wipes out the contents of the NameList field even though it's called first. I guess it's not needed in that instance since I'm simply refilling the field based on the sorted list of cardnames. Just need to figure out some other name for card 1002 and then suppress that from the list.
Charles
Your guess is correct in this case. Jacque already pointed out the nature of how Lc reads the code, line by line (watch out later on when you start calling multiple handlers, the first few times you might want to step through the thing in the debugger to make sure it is doing what you expect), so walking through your handler from my understanding, it would work like this:

Code: Select all

    on loadNameList // changed to handler...
       -- clear list
       put empty into field "NameList"
//  -> this line does just that, but it is unnecessary in this case because *...
       -- repopulate NameList control 
       put the cardnames of this stack into field "NameList"
// -> * used this way, whatever is there is replaced with the cardnames in this case...
       -- sort list
       sort lines of field "NameList"
    end loadNameList
Now, if you had written put the cardnames of this stack {before or after} field "NameList", then the card names would appear in front of or after the rest of the list.

IF you wanted to sometimes clear the list depending on the event, you would use "put empty" (or the shorter form, put "" ) to clear the list and start over. This isn't really applicable for what you are doing *here*, but you will find it useful to know later on.

Jacque covered everything else I could think to comment on. I think I know your Englishman, I've been down that breach WAY too many times :P
Image

chuckm
Posts: 33
Joined: Sun Jun 19, 2016 12:30 am

Re: Looking for an example stack of a address book, etc.

Post by chuckm » Sun Aug 27, 2017 11:32 pm

Hi All,

Remember me mentioning my tenacity? I appear to have the address book example working correctly (annotated tutorial to be completed over the next week).

I do have a question about best practices. I have four buttons (Close, Edit, Cancel, Save) on the card. Close/Edit and Cancel/Save are somewhat mutually exclusive so I hide the Cancel/Save buttons when the user is not editing a new or existing card and show the buttons when the user is editing (effectively hiding the Close/Edit buttons). I'm currently just doing the hides for each button, but I'm wondering whether or not it would be considered a better practice to group them and just display/hide the group based on the edit mode.

Thanks!

Charles (who is also called Chuck but is rarely called Late For Dinner)

bogs
Posts: 3381
Joined: Sat Feb 25, 2017 10:45 pm

Re: Looking for an example stack of a address book, etc.

Post by bogs » Mon Aug 28, 2017 1:25 am

I seem to remember the recommendation wasn't to hide them, but simply disable them, but I could be wrong.
Image

chuckm
Posts: 33
Joined: Sun Jun 19, 2016 12:30 am

Re: Looking for an example stack of a address book, etc.

Post by chuckm » Mon Aug 28, 2017 2:15 am

bogs wrote:I seem to remember the recommendation wasn't to hide them, but simply disable them, but I could be wrong.
True enough, but hiding them seemed preferable to enabling/disabling them and I felt that it would be cleaner to only present the buttons that could be used at the time. Although the New (+) and Delete (-) buttons aren't disabled during an edit operation, they will trigger a dialog asking if the user wants to save or cancel the current edits before continuing. I'm torn on that one, because my other option is just to disable those buttons until the edit operation is complete. Either way, the user will be required to finish the edit operation before being allowed to continue.

bogs
Posts: 3381
Joined: Sat Feb 25, 2017 10:45 pm

Re: Looking for an example stack of a address book, etc.

Post by bogs » Mon Aug 28, 2017 12:14 pm

Well, if your set and determined to make them go away, then for consistency in the interface you could just have 2 buttons, and change the labels on those, using the label state to set the code in either an if/then or select case (I believe Lc refers to it as 'switch') statement.
WARNING!! - this is off the top of my head, I don't know that I would call it a "best practice", and I certainly didn't go look to see if it was or not :lol:
The switch in labels would be triggered by the code that starts the event, usually, so your talking about maybe 2 additional lines in each event that would read something like (psuedo code)

Code: Select all

on preOpenCard
// default state of the labels on 2 buttons...
    set the label of button x to "edit"; set the label of button y to "cancel"
end preOpenCard

on triggerEvent
// change the state depending on state of the card, editable or not...
    if the state of the card is edit mode then
       set the label of button x to "edit"; set the label of button y to "cancel"
       // run code for these buttons from here
    else
       set the label of button x to "save"; set the label of button y to "close"
       // run code for these buttons from here    
    end if
end triggerEvent
This way, the number of objects is reduced, buttons will appear consistently in one place, the code is located centrally for you, seems like a win win, but I could be wrong.

If you need to look at real code of this type in action, heres a page that has some timers on it using this style of coding. I'd suggest using script locals in place of the globals though, if the code is all centrally located on one page in the script editor.
Image

chuckm
Posts: 33
Joined: Sun Jun 19, 2016 12:30 am

Re: Looking for an example stack of a address book, etc.

Post by chuckm » Mon Aug 28, 2017 5:31 pm

I'm a bit hesitant to overload button handlers like that because it quickly turns into a bloated controller situation which can be quite hellish to debug. Small, modular handlers would seem to be a better approach but I'm new here. My Unix background also keeps popping up with the "keep each thing doing one thing" mantra. :-D

dunbarx
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 5995
Joined: Wed May 06, 2009 2:28 pm
Location: New York, NY

Re: Looking for an example stack of a address book, etc.

Post by dunbarx » Mon Aug 28, 2017 6:12 pm

I also like to compartmentalize tasks. The upside is local control and smaller scripts. The downside is lots of places to look when debugging or embellishing, so I use "Find and Replace..." a lot to locate keywords when doing either.

Still, I like that methodology, only using the card or stack scripts for tasks that must be accessed in common among the various controls on the various cards. In the current stack I am developing for internal use, I have 400 or so lines in the main card script and another 400 in the stack script. But I have 7000 additional lines scattered among the gadgetry on a dozen cards.

If I tried to migrate as much as I could to the stack script, say, I do not think I would eliminate the work required to locate the appropriate handlers and functions. It would be true that no button might have a script, a giant "mouseUp" handler in the stack determining the target and reDirecting to a piece of code somewhere, but if I wanted to change anything, I would still have roughly the same effort to locate the code snippet as I would in locating the button itself.

In the end, it is a matter of style, assuming that one knows the basics of the message hierarchy and uses it to reasonable advantage.

Craig

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4984
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Looking for an example stack of a address book, etc.

Post by jacque » Mon Aug 28, 2017 6:19 pm

bogs wrote:I seem to remember the recommendation wasn't to hide them, but simply disable them, but I could be wrong.
There's no recommendation per se, it all depends on the stack and how you want the UI to work. Every developer will do it differently.

In this case I see no difference between hiding individual buttons or hiding groups of buttons, outside of an extra line of script.

One advantage of hiding a group is that you don't need to lock the screen, since everything in the group will dissappear at once. Hiding individual buttons without locking the screen will show them disappearing in sequence. Since it's trivial to lock the screen, this isn't a great disadvantage.

Disabled buttons are often used when user action is required before the button is relevant. It tells the user what the next action will be, but that it can't be executed yet. Hidden buttons are used when the action isn't relevant at all at the moment. In this case I could see it working either way, though the interface would be cleaner without unusable buttons in view.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

Post Reply

Return to “Getting Started with LiveCode - Experienced Developers”