On TextChanged not firing when field changed by script

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

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9823
Joined: Sat Apr 08, 2006 7:05 am
Location: Los Angeles
Contact:

Re: On TextChanged not firing when field changed by script

Post by FourthWorld » Sat Apr 17, 2021 5:17 pm

dunbarx wrote:
Sat Apr 17, 2021 3:52 pm
As a matter of opinion (mine) I also think that the textChanged message should be more universal. It should fire if the, er, text has changed, period.
I share your desire for the convenience in this one retrofit case, but I also appreciate the team's interest in keeping the message queue lean.

Setting up and managing a message queue is not a small thing, and each message carries a tradeoff in performance.

In my next reply we'll take a fresh look at current with-the-grain options to see that it may not be needed or even desirable to slow down all text display operations just for this case...
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

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

Re: On TextChanged not firing when field changed by script

Post by jacque » Sat Apr 17, 2021 5:24 pm

dunbarx wrote:
Sat Apr 17, 2021 3:52 pm
As a matter of opinion (mine) I also think that the textChanged message should be more universal. It should fire if the, er, text has changed, period.
I can foresee all kinds of issues if that were the case. A different message would be okay but changing the existing one would break a lot of stacks.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9823
Joined: Sat Apr 08, 2006 7:05 am
Location: Los Angeles
Contact:

Re: On TextChanged not firing when field changed by script

Post by FourthWorld » Sat Apr 17, 2021 5:59 pm

Returning to the core need expressed here:
stam wrote:
Fri Apr 16, 2021 4:07 pm
I have a setup where a complex set of graphics that creates a summary parameter - i was hoping to use that as a trigger to update a database every time a value is changed, which will in turn change the summary parameter. i.e., instead of having to add the updating command to every graphic...
There are at least two built-in ready-to-use ways to have multiple controls modify one field with extra stuff beyond setting the text itself:
- Handle it in any script of relevant scope
- Handle it with a setProp handler

Neither requires replicating the additional handling. The db binding (or anything else you want to do) is every bit as centralized as if you'd written a textChanged message, but without the overall performance degradation of a new message that would impeded all operations involving text display.

Let's briefly look at each:

Handle it in any script of relevant scope
In each control the script is about as lean as it could possibly be, a one-word command with one argument:

Code: Select all

on mouseUp
   SetMainTextWithBinding "Some text to add to the field."
end mouseUp
In a card, stack, or library script we define the handler:

Code: Select all

on SetMainTextWithBinding pText
    put pText after field "Main"
    -- DB update stuff goes here
end SetMainTextWithBinding

Handle it with a setProp handler
Here each control set a virtual property of the field as the trigger for the multistep operation:

Code: Select all

on mouseUp
   set the uBoundText of fld "Main" to "Some text to add to the field."
end mouseUp
...where the field, card, stack, or a library can define how to handle that virtual property:

Code: Select all

setProp uBoundText pText
   put pText after the text of the target
   -- DB update stuff goes here
 end uBoundText
Which is "best" is partly a matter of taste, and partly a matter of the workflow you develop with: virtual property handler (getProp/setProp) are handy but affected by lockMessages, where custom handlers are not. If you have total control over everything in play you can have confidence that no other script will have messages locked at the moment the setProp is triggered.

Personally I use the less glamorous option is just putting a handler in a relevant script, keeping things simple enough and I never need to ask myself whether messages will be locked when it's invoked.

The important thing here is that the code in each control used to trigger the text change is dirt-simple, possibly a bit briefer than whatever was in place to set the text before. And the full scope of the handling -- both displaying the text change and dealing with the DB stuff -- is fully centralized in one place for robust and easy maintenance, just as it would be if it were handled in a textChanged message (but without the performance hit of having the engine take on yet another message).

The challenge in this specific case isn't so much finding a comfortable solution for multiple triggers of a single set of custom handling instructions.

The challenge is a challenge at all only because it's retrofit, a solution not anticipated in the code as originally written.

With just about any non-trivial program there will be times we'll want to revise things based on what we've learned since we first started crafting our app. While it would be wonderful to have simple mechanisms we can drop in place so we don't need to change code to reflect changing needs, refactoring/retrofitting is indeed rarely simple and often tedious.

Accommodating change is work, in any human activity, including coding.

While exploring options for one-size-fits-all solutions like reliance on an idle handler or other such things may be useful for learning and sometimes even prove a great solution for the task at hand, I would caution against the temptation to bypass normal with-the-grain message handling unless it's absolutely necessary, after all with-the-grain options have been explored and somehow proven untenable for the unique case at hand. There be dragons. Every gray hair on my head was hard-earned from spending hours in the meadow hunting for magic ponies that never appeared, when all I needed to do was sit down, roll up my sleeves, and revise a few lines of code.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 9823
Joined: Sat Apr 08, 2006 7:05 am
Location: Los Angeles
Contact:

Re: On TextChanged not firing when field changed by script

Post by FourthWorld » Sat Apr 17, 2021 6:09 pm

After writing that a third with-the-grain solution comes to mind (really just a better variant of the first option above), if the details of your layout will accommodate it:

Put the buttons in a group, and have no code in any of them at all.

Instead, put the text unique to each triggering control into a custom property within it, with the group script being:

Code: Select all

on mouseUp
    SetMainTextWithBinding the uFieldText of the target
 end mouseUp
Now you not only have the custom handling for the database stuff centralized as before, but you also eliminate the code that triggers it which is currently replicated across 30 scripts.

One-stop shopping for both ends of the transaction, making for easier maintenance and extensibility going forward, and at the low cost of about five minutes of work.
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn

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

Re: On TextChanged not firing when field changed by script

Post by bogs » Sat Apr 17, 2021 6:56 pm

stam wrote:
Sat Apr 17, 2021 12:37 pm
I suppose it wouldn't be too difficult to write a script that periodically checks for changes in the field. I.e. store previous value in script variable, compare with current variable and if a change then run the script that updates the database, then call itself again in xx time.
Actually, I used something very similar in the text editor tutorial, maybe that would be of some use to you for your situation. The relevant part starts around Scripting the main text field - 04:16, and indeed I put the entire text field into a local, then check the difference between the number of chars in the local vs. the field to determine whether to prompt for a save.

I think it is a tad more efficient than polling the idle timer, but probably doesn't make any real difference.
Image

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

Re: On TextChanged not firing when field changed by script

Post by jacque » Sat Apr 17, 2021 7:06 pm

One more option: go ahead and change all 30 graphic controls. When I need to retroactively do something like that, I change the script of the first (lowest layered) control and then put something like this in the multi-line message box:

Code: Select all

repeat with x = 2 to the number of graphics
  set the script of grc x to the script of grc 1
end repeat
This does change all the graphics, so if you only want a subset then you'll need to add a condition such as "if the short name of grc x contains 'blah" then..."
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

bwmilby
Posts: 438
Joined: Wed Jun 07, 2017 5:37 am
Location: Henrico, VA
Contact:

Re: On TextChanged not firing when field changed by script

Post by bwmilby » Sun Apr 18, 2021 2:28 am

One thing that I think is being lost is that if "textChanged" was sent when the field was updated by script, then you could get yourself into a really bad recursion loop. One of the uses of the message is to clean up a field after user interaction which very well may end up making another change to the field.

We currently have that issue with the NavBar Widget and the TreeView Widget. "hiliteChanged" on both is sent when script or user updates the highlighted item. Since those widgets originated with that behavior, we know about it and can code around it if needed. Making that type of change to "textChanged" would be a breaking change that could impact a large number of existing stacks.
Brian Milby

Script Tracker https://github.com/bwmilby/scriptTracker

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

Re: On TextChanged not firing when field changed by script

Post by dunbarx » Sun Apr 18, 2021 4:27 am

I now see that wishful thinking, without considering the consequences, that is, changing the constraints of the textChanged message, could be harmful.

But it then is left that there is no message sent when the text of a field is changed under script control. As has been said, one can do that from the source, and so such a message need not be a necessity.

Anyway, one cannot be too careful.

Craig

stam
Posts: 2680
Joined: Sun Jun 04, 2006 9:39 pm
Location: London, UK

Re: On TextChanged not firing when field changed by script

Post by stam » Sun Apr 18, 2021 11:30 am

Thanks for the really interesting answers everyone - hugely varied approaches, have given me a lot to think about.

I can see that textChanged should not be altered - maybe in the future a new message called textModified or some such could fill this gap. If more people agree that's a useful addition can maybe submit as a new feature request.

Regarding centralising a handler to manage the actions - i do that already, but it's complex set up (it's not just graphics that modify the value) and I'd need to modify a number of scripts. Not the end of the world, but it is extra work with potential to break stuff.

The setProp approach is much better actually.
The summary value that gets put in the field in question is stored in a custom property of the group that contains all the graphics so i would just need to add a setProp hander to the group. I really should've thought of this sooner (thank you Richard!).
I've been bitten by infinite recursion with setProp on more than 1 occasion, so i use it extra sparingly, but it might be a good fit for this situation...

Thank you all for the fantastic ideas!
Stam

Post Reply

Return to “Getting Started with LiveCode - Experienced Developers”