setting default behavior of buttons

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: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

Post Reply
yeldarb
Posts: 43
Joined: Thu Dec 14, 2017 5:39 pm

setting default behavior of buttons

Post by yeldarb » Thu Jan 04, 2018 9:24 pm

I'd prefer to handle the behavior of all buttons in one spot, with mouseOver, mouseLeave, etc. I've got a button named "master" in a group, and I'm trying to have all the buttons get the same behavior wtih a stack script:

Code: Select all

on openCard
   repeat with i = 1 to the num of controls in this card into ctrlCount
      if word 1 of the name of control i of this card is "button" then
         put the long id of btn "master" of grp "background" into masterBtn
         set the behavior of control i of this card to masterBtn
      end if
   end repeat
end openCard
But I get the error:
stack "personalityQuiz": execution error at line 108 (parentScript: loop in hierarchy), char 1

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

Re: setting default behavior of buttons

Post by dunbarx » Thu Jan 04, 2018 9:36 pm

Hi.

What is line 108?

And just for discussion, the line:

Code: Select all

 repeat with i = 1 to the num of controls in this card into ctrlCount
The "...into ctrlCount" seems to throw no error, but is not part of the language. What was your intention?

Craig Newman

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

Re: setting default behavior of buttons

Post by bogs » Thu Jan 04, 2018 9:39 pm

well, you could do something like this instead (no master anything required)

Code: Select all

on mouseEnter
   if the abbreviated name of the target contains "button" then set the backgroundcolor of the target to "yellow"
end mouseEnter
If you get into more complicated areas where you need the mouseEnter later, you can stick it pretty much anywhere, this one was in the mainStack code where all messages wind up eventually. Just remember if you have a button specific mouseEnter to add "pass mouseEnter" after your specific code.

*Edit - I should have pointed out this works for all the mouse events your talking about, and of course that if you wanted to do more than one thing, you should use the if / end if format, not the single line format, so like

Code: Select all

if the abbreviated name of the target contains "button" then
   set the backgroundcolor of the target to "yellow"
   add 2 to timesHit
   answer "It worked!"
end if
 
Image

Klaus
Posts: 13806
Joined: Sat Apr 08, 2006 8:41 am
Location: Germany
Contact:

Re: setting default behavior of buttons

Post by Klaus » Thu Jan 04, 2018 9:57 pm

Hi yeldarb,

try this:

Code: Select all

on openCard
  ## No need to do this inside of the loop!
   put the long id of btn "master" of grp "background" into masterBtn
   
   ## We can directly loop through all buttons!
   repeat with i = 1 to the num of buttons

     ## We can't and don't want to overwrite the MASTER button himself!
      if the short name of btn i = "master" then
         next repeat
      end if
      set the behavior of btn i to masterBtn
   end repeat
end openCard
Best

Klaus

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

Re: setting default behavior of buttons

Post by bogs » Thu Jan 04, 2018 10:03 pm

Ok, now I am curious, what exactly would be the advantage of doing something like that, looping over all the controls, using a master control, to just putting it all in one event? Is it just to cut down on having to code the other possible events?
Image

yeldarb
Posts: 43
Joined: Thu Dec 14, 2017 5:39 pm

Re: setting default behavior of buttons

Post by yeldarb » Thu Jan 04, 2018 10:07 pm

bogs wrote:
Thu Jan 04, 2018 10:03 pm
Ok, now I am curious, what exactly would be the advantage of doing something like that, looping over all the controls, using a master control, to just putting it all in one event? Is it just to cut down on having to code the other possible events?
Yes, it allows me to tweak the behavior of all buttons from one spot. And the problem (doh!) was that I didn't filter out the "master" button, so I was essentially assigning the behavior of button "master" to its own behavior.

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

Re: setting default behavior of buttons

Post by bogs » Thu Jan 04, 2018 10:32 pm

I see. For me, I think it would have to be doing more than a few things to be able to cover that, since you have to add the event handlers anyway, if you see what I mean. If it got that complicated, I'd probably relegate it to a function and call that.

I'm not saying the above is right, or correct, just my take on it.
Image

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

Re: setting default behavior of buttons

Post by jacque » Fri Jan 05, 2018 8:23 pm

Behaviors are incredibly useful and the preferred way to manage identical scripts across many controls. They operate a little like classes in other languages, or you can think of them as backscripts private to each control. The control itself needs no script at all, it will use the handlers in the behavior script.

Edit to add examples: I've got a large project that uses behaviors for almost everything. There is a library script, for example, that handles all aspects of creating, managing, and removing mobile scrollers. The project consists of dozens of stacks. Whenever we need a mobile scroller, we set the behavior of the field to the library script and it just works. No scripts are required in the field itself except for any actions that may be unique to that field. If the field is simply read-only its script is blank.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

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

Re: setting default behavior of buttons

Post by bogs » Fri Jan 05, 2018 10:27 pm

jacque wrote:
Fri Jan 05, 2018 8:23 pm
The project consists of dozens of stacks.
As I said, I could see it in this type of complex situation, you have a lot of stacks, probably other main stacks as well, and want to relegate the behavior to one location to change things.

In a project that isn't very complex, say with one mainstack, even with dozens of substacks, I'd think it would be just as easy to relegate it to handlers in the mainstack if it is one or two lines, or to a function if it is something pretty complex and pass the event or call the function from where it is needed.

I guess I just haven't hit a situation yet where I've needed something like this, and I am still after all in the 'toddler' stages of using this language. When I get up to the walking and running stages I might need to revisit this thinking.

Above all (for any readers that come later), I will point out again that my thinking is not necessarily right, or correct, just my take on it. I'd certainly defer to everyone else's opinion on it if for no other reason than you have all been through it for many more years than I have :)
Image

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

Re: setting default behavior of buttons

Post by jacque » Fri Jan 05, 2018 11:17 pm

Your method was the only method up until behaviors were introduced. It is still valid but its main limitation is the need to edit every object when a change is made, as well as needing to track what object called the handler in some cases. Even if you call out to a central handler, it may be necessary later to add or remove parameters or change it some other way.

Behaviors aren't just necessary for large or complex projects. Imagine a game card with a grid of buttons. If each one has the same assigned behavior you will never need to edit any of them. Only the behavior needs to be changed. In the behavior script, "me" refers to the object that is currently using the behavior, and each instance of the behavior's execution retains separate variable values. That means you can load a script local variable that will contain a different value for every object that uses the behavior. The behavior acts as though a copy of the whole script is isolated in each button.

I think when you begin to explore behaviors you'll see the advantages. It was a major leap forward in LC scripting. Try this:

Create a button with this script:

Code: Select all

local sFlag

on mouseUp
  if sFlag = "" then put any line of the colornames into sFlag
  put sFlag
end mouseUp
Now create two or three other buttons with no scripts. Set those to use the behavior in the first button (you can do that in the advanced pane of the property inspector.) When you click on any of the three non-scripted buttons you should see a different color name in the message box that is retained for the session.

Now imagine a much longer script with many handlers and functions. The whole script can be applied to any number of controls and will act independently for each of them, just as though you'd copied the script into every object.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

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

Re: setting default behavior of buttons

Post by bogs » Sat Jan 06, 2018 1:52 am

jacque wrote:
Fri Jan 05, 2018 11:17 pm
It is still valid but its main limitation is the need to edit every object when a change is made, as well as needing to track what object called the handler in some cases.
Thank you, that was very insightful, but I guess what I am not getting is the parts of what you said that I marked in bold.

The code I posted, in this case for mouseEnter, changes the background color of every button on the stack as you enter that button, because it is in the mainStack's script, not the button's script.

It uses the target to figure out what is being entered. Granted, it is a very simple thing to change the color, but if I put 30 more things in there, they would still be in that one location and would still affect any button you entered.

Anything button specific would go into a buttons script or a general handler, where case or if / then would handle the differences, again, the handler being in the mainStacks script. No button's individual script would need editing at that point for the generic things that would be in this script and specifics would be in a handler.

I did understand the example you put, and I understand it is a big step forward for certain things, but for the OP's posted question (other than that he already has a button to tie behaviors too), I guess I don't get the extra need.

But I appreciate all the extra input, it all gives me more insight :D
Image

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

Re: setting default behavior of buttons

Post by jacque » Sat Jan 06, 2018 4:18 am

Thank you, that was very insightful, but I guess what I am not getting is the parts of what you said that I marked in bold.

The code I posted, in this case for mouseEnter, changes the background color of every button on the stack as you enter that button, because it is in the mainStack's script, not the button's script.
In your example, suppose you don't want every button to change color, only some of them. So now you have two conditions to check for -- that the target is a button, and that the target fits a set of criteria, perhaps by comparing the name of the target to a constant holding a list. So now you have to look at the target, keep a list, get the name, compare it to the list, and remember to update the list if you add or delete buttons later. Eventually you may have other conditions to be met and you'll have to account for those as well. This kind of script can get long and snarly after a while.

With a behavior, you simply set the behavior and that's all. Buttons without the behavior don't use the script, and buttons with it act as you want. There is no need to keep a list or check the target, or remember to update anything. The behavior script acts as though it is the script of the button. Deleting the button doesn't require changes anywhere else. Adding a button is as simple as cloning one of the others or adding the behavior to a new button. None of the buttons need their own script.

Now suppose you have a color-changing button on different mainstacks. You will need to include your original script in both stacks, so now you have to remember to update two copies and keep two lists. Since behaviors can be loaded as libraries, you only need to open the library in preOpenStack or preOpenCard and any button in the stack that uses the behavior will be a color-changing button.

Edit: BTW, behaviors are not confined to buttons. Any control can have a behavior, as can cards and stacks.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

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

Re: setting default behavior of buttons

Post by bogs » Sat Jan 06, 2018 10:20 pm

Above all else before I begin, I really want to make sure it is understood that I am not recommending this in all instances, instead I am talking about relatively simple things, being relatively simple myself I tend to be drawn in that direction most :D

While I've seen scripts that are "long and snarly" as you put it, I think one of two things when I come across them most times -
  1. it required more complexity than I am suggesting using this method for, and using behaviors would be more appropriate probably in that circumstance, or
  2. the person writing it got tunnel vision of sorts and didn't take the time to break it down to more relevant handlers and functions.
In your example, suppose you don't want every button to change color, only some of them. So now you have two conditions to check for -- that the target is a button, and that the target fits a set of criteria, perhaps by comparing the name of the target to a constant holding a list. So now you have to look at the target, keep a list, get the name, compare it to the list, and remember to update the list if you add or delete buttons later.
When I started using Lc I was doing something like that. No lists, mind you, but using repeat to loop through controls and filter what I wanted or didn't based on name values.

Having come a tiny bit further, I now put the empty handler in the button (card, stack, field, etc) to avoid the event in the mainstack, or alternately, call or send or dispatch the handler or function I wanted for that special snowflake button from which ever stack I decided it was optimal to put the handlers/functions in.

If you have a multi-stack program, certainly using a library would likely be the place to put those handlers or functions I think, if for no other reason than to keep them centralized to one location for editing later that isn't going to have any other kind of code in it.
... In fact, I am so enamored of libraries I pretty much can say I use those a LOT, if for nothing else than keeping generic code around and easily accessible.

Using call, send, dispatch, etc has eliminated (so far) the need to copy/ paste scripts across stacks/cards/etc. for the stuff I do or have done, but again all my projects so far are very simple things.

I have no problem with using behaviors, although I'm sure it sounds like I do, reading my answers. If I had something that required some kind of complicated inheritance, or as you put it earlier, the equivalent of a class object, I'd certainly start digging right in.

I guess deciding when it is the most appropriate tool is going to be the challenge for me, certainly if any handlers I write for some object start to hit that 'long and snarly' mark, I'd be looking at it as it would have passed the 'relatively simple' mark.

Thank you again for all the insights though, I really appreciate the explanations and amount of thought put into them, you always give me lots to think about :)
Image

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

Re: setting default behavior of buttons

Post by jacque » Sun Jan 07, 2018 12:10 am

You're doing it the hard way, but it's valid and it works. Note though that call, send, and dispatch have some overhead that could be avoided.

I won't try to convince you any more. :)
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

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

Re: setting default behavior of buttons

Post by bogs » Sun Jan 07, 2018 2:49 am

jacque wrote:
Sun Jan 07, 2018 12:10 am
You're doing it the hard way...
I can't honestly say I've never heard that before, but thank you for being gentle with me :)
Image

Post Reply

Return to “Getting Started with LiveCode - Experienced Developers”