Page 1 of 2

Shared script

Posted: Sun Feb 11, 2007 3:33 pm
by quailcreek
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

Posted: Sun Feb 11, 2007 3:44 pm
by Mark
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

Posted: Sun Feb 11, 2007 4:00 pm
by quailcreek
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

socketError

Posted: Sun Feb 11, 2007 4:23 pm
by quailcreek
Can't seem to get it running.

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

Tom

Posted: Sun Feb 11, 2007 4:34 pm
by Mark
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

Re: Shared script

Posted: Sun Feb 11, 2007 5:35 pm
by FourthWorld
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

Posted: Sun Feb 11, 2007 6:11 pm
by quailcreek
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

Posted: Sun Feb 11, 2007 10:53 pm
by FourthWorld
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

simplifying

Posted: Mon Feb 12, 2007 9:32 am
by marielle
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).

A fourth solution to libraries of functions

Posted: Mon Feb 12, 2007 9:50 am
by marielle
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.

A bit more complex. An events listener/bindings solution

Posted: Mon Feb 12, 2007 10:00 am
by marielle
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 :-).

Posted: Mon Feb 12, 2007 4:22 pm
by quailcreek
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

Re: A fourth solution to libraries of functions

Posted: Mon Feb 12, 2007 10:51 pm
by FourthWorld
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.

Re: A fourth solution to libraries of functions

Posted: Mon Feb 12, 2007 11:07 pm
by marielle
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?

Re: A fourth solution to libraries of functions

Posted: Mon Feb 12, 2007 11:13 pm
by marielle
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 ;-).