Shared script

Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

quailcreek
Posts: 746
Joined: Sun Feb 04, 2007 11:01 pm

Shared script

Post by quailcreek » Sun Feb 11, 2007 3:33 pm

Hello Again,
Does RR support a shared script concept? What I mean is if I have a script that I want to have in 50 or so places in my stack, is there a way to link it to all of them without copying it to each object? This way I would only need to update the script once.

Thanks
Tom

Mark
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 5150
Joined: Thu Feb 23, 2006 9:24 pm
Contact:

Post by Mark » Sun Feb 11, 2007 3:44 pm

Sure. Search the docs for the frontScript and backScript properties and the start using command.

Btw, we are having an almost-live discussion here. We could have a real-live/life discussion on ChatRev. http://chatrev.bjoernke.com and http://economy-x-talk.com/chatrev.html

Best,

Mark
Last edited by Mark on Fri Dec 14, 2007 7:50 pm, edited 1 time in total.
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

quailcreek
Posts: 746
Joined: Sun Feb 04, 2007 11:01 pm

Post by quailcreek » Sun Feb 11, 2007 4:00 pm

Seems like http://economy-x-talk.com/chatrev.html is the obvious choice. Let me get the download installed and we can talk some more.

Thanks again for the help.
Tom

quailcreek
Posts: 746
Joined: Sun Feb 04, 2007 11:01 pm

socketError

Post by quailcreek » Sun Feb 11, 2007 4:23 pm

Can't seem to get it running.

disconnected
socket is not open
error: socketError Error 10060 on socket

Tom

Mark
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 5150
Joined: Thu Feb 23, 2006 9:24 pm
Contact:

Post by Mark » Sun Feb 11, 2007 4:34 pm

Hi Tom,

First, make sure that your firewall allows outgoing traffic through pot 8008. If you are using the client which you downloaded from the Economy-x-Talk homepage, select the URL from the (lower) IP URL combo box or enter 81.221.127.96 into the (upper) IP combo box. Enter 8008 into the Port field and enter a Name and Password. If you try to connect now, you should get a message that asks you to register. If you click Register, you will see a registration window. Fill out the fields and click Register. Now you can log in. You may have to log in twice, because of a bug in this client (I know it needs updating but there is no time to do so).

Best,

mark
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10054
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Re: Shared script

Post by FourthWorld » Sun Feb 11, 2007 5:35 pm

quailcreek wrote:Hello Again,
Does RR support a shared script concept? What I mean is if I have a script that I want to have in 50 or so places in my stack, is there a way to link it to all of them without copying it to each object?
Yes. Revolution supports three mechanisms for extending the message path: libraries, frontScripts, and backScripts:

http://www.fourthworld.com/embassy/arti ... _path.html

quailcreek
Posts: 746
Joined: Sun Feb 04, 2007 11:01 pm

Post by quailcreek » Sun Feb 11, 2007 6:11 pm

Thanks. I read through the information but I'm stil trying to get a harness around the mechanics.

If I have let's say a button with a script that contains a mouseUp, mouseDown and a turnTheMouse all around script. Can this be used with the frontScript method? Also, how do I tell Rev which obects I want to receive the collection of commands?

Tom

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10054
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Post by FourthWorld » Sun Feb 11, 2007 10:53 pm

quailcreek wrote:Thanks. I read through the information but I'm stil trying to get a harness around the mechanics.

If I have let's say a button with a script that contains a mouseUp, mouseDown and a turnTheMouse all around script. Can this be used with the frontScript method? Also, how do I tell Rev which obects I want to receive the collection of commands?
There are a great many ways to do this. One way would be to define a custom property of the objects you want to share these behaviors, then have a frontScript that does something like this:

on mouseDown
if the uType of the target = "MyClass" then
DoMyClassMouseDown
else pass mouseDown
end mouseDown

marielle
Livecode Opensource Backer
Livecode Opensource Backer

simplifying

Post by marielle » Mon Feb 12, 2007 9:32 am

Let's start simple.

In terms of having a script that is shared, you have to dissociate two things. One is the stage of "detecting events that happen on the interface". Another one is the stage of "doing something".

So the simplest solution is

At object level:

Code: Select all

on mouseup
    dosomethingWhenAButtonOfThisTypeIsPressed
end mouseup
At card or stack level (depending of how universal you want it to be:

Code: Select all

on dosomethingWhenAButtonOfThisTypeIsPressed
   ... processing ....
end dosomethingWhenAButtonOfThisTypeIsPressed
No need for a frontscript, backscript, or anything (there is a limit to the number of frontscript and backscript that you can have in a compiled application).
Last edited by marielle on Mon Feb 12, 2007 7:10 pm, edited 2 times in total.

marielle
Livecode Opensource Backer
Livecode Opensource Backer

A fourth solution to libraries of functions

Post by marielle » Mon Feb 12, 2007 9:50 am

A problem I have with frontscripts and backscripts is that they encourage you to pack huge quantitites of script in a single file. Quite bad for legibility and maintenance. Even worst for encouraging good coding practices (strict independence of functions, etc.).

So, what I do, is store my scripts into separate libraries. These libraries never get into the front or back. These libraries are stored within interface objects. I typically use groups that I keep on a card called "libraries", which is on a stack called "resources" (which contains libraries, templates, tables, settings).

Then what you can do is use some syntax like

Code: Select all

put the long id of group "library_dosomething" of card "libraries" of stack "resources" into tLibRef
send dosomethingWhenAButtonOfThisTypeIsPressed to tLibRef
You will tell me, what about when I need to pass data? How do I do that. You simply use custom properties to store data temporarily. You then store them at library level.

Code: Select all

put the long id of group "library_dosomething" of card "libraries" of stack "resources" into tLibRef
set the input_data of tLibRef to tData
send dosomethingWhenAButtonOfThisTypeIsPressed to tLibRef
put the output_data of tLibRef into tResult
answer tResult
Nothing hanging in the front or backscript that could mix up with your code. The code in each (relatively small-sized) library is strictly independent from the code in other libraries. No limit to the number of libraries you can have. Ah yes, it is very easy to design a test suite that is specific to each library you write.

There are examples of libraries written and used this way at:
revolution.widged.com/libraries/

Check the "testsuite" to see how these calls are being made.
Last edited by marielle on Mon Feb 12, 2007 7:11 pm, edited 1 time in total.

marielle
Livecode Opensource Backer
Livecode Opensource Backer

A bit more complex. An events listener/bindings solution

Post by marielle » Mon Feb 12, 2007 10:00 am

All solutions presented so far imply that you need to make the initial call at object level. This can sometimes be calling for troubles in case you make any change in naming conventions or script organization later on.

What I find quite useful is the use of a "binding" function. This will simply forward all messages to a given library. My real function is more complex that this. Let's keep things more simple. I have for instance a small library that is specialized in gesture recognition. It can analyse movements with the mouse in terms of "right", "left", "up", "down".

What I will have on my user interface, is a zone (typically a graphic), which is to try and analyse mouse movements into gestures when any mouse movement occurs in that area.

I simply create a custom property called "bindings" for this graphic. To this custom property "bindings", I give as value "api_gesture" (in my version of the script, for the simplified version I give, you would need to provide as value the long id of the group or object in which that script is held). That's all!.

Okay, I of course need a bit scripting to manage this binding.

At card or stack level (could be back script), I have

Code: Select all

on mousedown
  get message.process("mousedown", the long id of the target)
end mousedown
---
on mouseup
  get message.process("mouseup", the long id of the target)
end mouseup
---
on mousemove
  get message.process("mousemove", the long id of the target)
end mousemove
---
function message.process pMessage, pTarget
  set the lockmessages to true -- not clear whether I need this.
  if the bindings of pTarget is not empty then
    try 
      put the bindings of pTarget into tApiRef
      set the listener of tApiRef to pMessage
      send "bindings" to tApiRef
    end try
  end if
  set the lockmessages to false
end message.process
Then within my gesture detection library, I will have:

Code: Select all

on bindings
  put the listener of me into tListener
  switch tListener
  case "mousedown"
    gesture.mousedown
    break
  case "mouseup"
    gesture.mouseup
    break
  case "mousemove"
    gesture.mousemove
    break
  end switch
end binding
That's it, job done :-).
Last edited by marielle on Mon Feb 12, 2007 7:08 pm, edited 1 time in total.

quailcreek
Posts: 746
Joined: Sun Feb 04, 2007 11:01 pm

Post by quailcreek » Mon Feb 12, 2007 4:22 pm

Thank you for the excellent explanation, Marielle. You've given me a lot to think about. It looks like I need to become very familiar with the use of Libraries.

Tom

FourthWorld
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 10054
Joined: Sat Apr 08, 2006 7:05 am
Contact:

Re: A fourth solution to libraries of functions

Post by FourthWorld » Mon Feb 12, 2007 10:51 pm

marielle wrote:A problem I have with frontscripts and backscripts is that they encourage you to pack huge quantitites of script in a single file. Quite bad for legibility and maintenance. Even worst for encouraging good coding practices (strict independence of functions, etc.).
Not necessarily. In an imperfect world, everything involves tradeoffs. :) Some find it convenient to keep code centralized rather than hunt across multiple objects for a handler definition. Any hunting needed in the message path can be easily automated (and is with devolution and Galaxy), but scripts outside the message path would require a custom solution.

Also, one difficulty in using "send" to route messages to scripts outside of the message path is that it's quite slower than the natural message path. For occasional use the performance penalty of "send" isn't much, but I tend toward solutions that go with the grain of the message path whenever possible, saving any extra clock cycles for features.

Backscripts are rarely truly needed, but with "start using" one can have up to 50 libraries in the back of the message path, which should be plenty for most purposes. I tend to group related functionality into separate libraries (printing, fileI/O, menu commands, etc.), and even in the largest commercial app I've shipped I've never used more than a dozen, with plenty to spare for anything I might want to add in the future.

As for FrontScripts, they offer a unique value that isn't possible elsewhere: they catch messages before even the target gets them. This allows one to write just one universal message trap to route messages without replicating code in objects. True, they do require a property setting, but so would parentScripts or any OOP class definition, which seem the closest match to what Tom is asking for.

Using a frontScript as the message trap is similar to what you've recommended at the card level, but wouldn't need to be copied into each card, making it easier to modify just the one frontScript at any time to alter the behaviors. One can even turn off these specialized behaviors but just removing the frontScript from the message path, or alter the behaviors by just inserting a different one.

marielle
Livecode Opensource Backer
Livecode Opensource Backer

Re: A fourth solution to libraries of functions

Post by marielle » Mon Feb 12, 2007 11:07 pm

FourthWorld wrote:Also, one difficulty in using "send" to route messages to scripts outside of the message path is that it's quite slower than the natural message path. For occasional use the performance penalty of "send" isn't much, but I tend toward solutions that go with the grain of the message path whenever possible, saving any extra clock cycles for features.
I didn't benchmark this. I never had any reason for concern.

Feedback from Dar suggested the cost was really minimal. Do you have any data on this yourself?

marielle
Livecode Opensource Backer
Livecode Opensource Backer

Re: A fourth solution to libraries of functions

Post by marielle » Mon Feb 12, 2007 11:13 pm

FourthWorld wrote:even in the largest commercial app I've shipped I've never used more than a dozen, with plenty to spare for anything I might want to add in the future.
I have 88 libraries for now ;-). Granted, I don't need all of these in all projects. However in the quite small project I am working on now, I have 32 libraries.

Most of them are in fact widget management libraries. That's a solution by which the library defines the behavior of a class of objects. On the interface, I can have as many instances of the class as I want. I have a very simple mechanism to store the relevant data at instance level and to read and write them from the class level.

I am very fond of this solution. My user may have to wait a tick more (one sixtieth of a second). But I get to code applications in half the time I would with a front/back script solution.

Then my code gets refined again and again with time, getting more robust, more reliable. I am sure my clients and users alike prefer a delay they don't even notice and increased functionalities and reliability.

If time is really critical, then I can always revert to a back/front script solution. However, because I would have waited the very last minute to move the script to the front and would have used completely independent libraries during the development process, I would have better code.

No need for tradeoffs. You can get all the advantages of a method without loosing any advantage of the other ;-).
Last edited by marielle on Mon Feb 12, 2007 11:29 pm, edited 3 times in total.

Post Reply