In Mac OS X, the Preferences menu item for each application is in the system controlled application menu i.e. the Mail menu for Mail, the Safari menu for Safari and so on. Revolution accounts for this by assuming that the last 2 items of the Edit menu are a dividing line and Preferences. It deletes these 2 items and passes any reference to the Preferences menu item back to the Edit menu. (A similar thing happens with the Quit menu item from the File menu.)
Monday, 28 April 2008
Disabling the Preferences menu item (Mac only)
Monday, 14 April 2008
Sending messages at a specific time
This will be the final part of my current thread about sending messages. This time, I'm going to look at scheduling messages for a certain time. Say for instance that you want your application to archive a log at 3 am every day, or remind you to stop work at 5 pm, or something like that. You can use the normal message sending routines, but you have to calculate the number of seconds between now and when you want this message to arrive. Here is my script that does all this for you:
-- sendMessageAt pHandlerName, pWhere, pAtTime
--
-- e.g. sendMessageAt "showClock", "fld ID 1026 of cd 1", "11:10"
-- e.g. sendMessageAt "buildList", "cd 1", "14:45"
--
-- send message at a specified time
-- use 24 hour time, so next available will be used.
-- requires setupNextCall handler below
--
on sendMessageAt pHandlerName, pWhere, pAtTime
-- get the current time in dateItems format
put the seconds into timeNow
put timeNow into eventTime
convert eventTime to dateItems
-- split the message time into hours & minutes
set the itemdel to ":"
put round(item 1 of pAtTime) into atHour
put round(item 2 of pAtTime) into atMin
-- see if the time is earlier than the current time & increment the day to put it into tomorrow if so
set the itemdel to comma
if atHour > item 4 of eventTime or (atHour = item 4 of eventTime and atMin <= item 5 of eventTime) then
add 1 to item 3 of eventTime
end if
-- put the selected hour & minute into the dateItems
put atHour into item 4 of eventTime
put atMin into item 5 of eventTime
put 0 into item 6 of eventTime -- adjust to even minute
-- convert back to seconds and calculate how long in seconds until that time
convert eventTime to seconds
put eventTime - timeNow into theDiff
-- use the setupNextCall handler to process this
setUpNextCall pHandlerName, pWhere, theDiff
end sendMessageAt
-- setupNextCall pHandlerName, pWhere, pInSeconds
--
-- e.g. setupNextCall "buildList", "cd 1", 60
-- e.g. setupNextCall "preOpenStack", "me", 5
--
-- send a message in a specified number of seconds
-- clears any pending instances first
--
on setUpNextCall pHandlerName, pWhere, pInSeconds
-- list the pendingMessages and cancel all existing instances of this message
put the pendingmessages into pMess
repeat for each line p in pMess
if item 3 of p contains pHandlerName then cancel item 1 of p
end repeat
-- if the location of the handler cannot be found, just leave
if there is not a pWhere then exit setupNextCall
-- send the handler in the specified number of seconds or milliseconds
if pInSeconds < 1 then
do "send " & quote & pHandlerName & quote & " to " & pWhere & " in " & pInSeconds*1000 & " milliseconds"
else
do "send " & quote & pHandlerName & quote & " to " & pWhere & " in " & pInSeconds & " seconds"
end if
end setUpNextCall
As you can see, this uses two handlers, but you only need to worry about the first one - it calls the second one itself.
sendMessageAt "archiveLog", "me", "03:00"
sendMessageAt "stopWork", the name of stack "Alarms", "07:48"
The last thing is to have a way of monitoring your pendingMessages. Revolution's message box will do this for you if you click the 5th button along:
Until next time,Monday, 7 April 2008
Calculating when to send messages
In my previous post about messages, I used the example of updating a clock display. I had the display updating once per minute, but there are obvious problems with this. If I start the handler at 8:38:59 am, the clock field will show 8:38 and will continue to show 8:38 for the next 60 seconds even though the time actually changed to 8:39 one second later.
There are two ways around this: update the clock every second, or set the update to occur on the minute. Updating every second is easy - just alter the previous script so that it sends the message in 1 second instead of in 60 seconds.
However I prefer the method of working out when the update is needed and only updating then. This seems more efficient. So here is my method for doing this:
on updateClock
-- stop the message in case there are multiples running
cancelMessage "updateClock"
-- update the display
put the time into fld "Clock"
-- store the current time in seconds
put the seconds into tNow
-- work out how long (in seconds) until the next minute
put tNow into tNextUpdate
convert tNextUpdate to dateItems
add 1 to item 5 of tNextUpdate
put 0 into item 6 of tNextUpdate
convert tNextUpdate to seconds
-- calculate the difference in seconds between the current time and the next minute
put tNextUpdate - tNow into tSecsDiff
-- send the update message to happen as the minutes tick over to the next
send "updateClock" to me in tSecsDiff seconds
end updateClock
on cancelMessage pHandlerName
put the pendingmessages into pMess
repeat for each line p in pMess
if item 3 of p contains pHandlerName and \
item 4 of p contains the effective filename of this stack then
cancel item 1 of p
end if
end repeat
end cancelMessage
When the update handler starts, it cancels any other instances of that message that might be in the pending messages list. Then it displays the time as before. The difference is in the next bit where it works out how long it should be until the clock is updated again. This can vary - if the clock was updated at 8:28:59, then it needs to be updated in 1 second. If it was updated at 8:28:01, then there can be 59 seconds before the next update.
This handler stores the current time in seconds format. Then, in a separate variable, it works out the time of the next minute. When a date or time is converted to dateItems, you get a comma-delimited list showing year, month, day, hour, minutes, seconds and day of the week. By adding 1 to item 5 and setting item 6 to zero, this is altered to show the next minute exactly. Then this new time is converted back to seconds so that the number of seconds between the current time and that time can be calculated. This gives the seconds until the clock needs to be updated.
Ooops - mistake in previous post
Sorry people. At the end of the last post, I showed you a handler to cancel messages only from the calling stack. That handler will work in c=some circumstances, but not in all, so I have changed it. The original post now contains the amended handler for anyone who comes to it for the first time, but if any of you have already copied it, here is the new version, which I think will work in all circumstances. If you find a case where it doesn't work, please let me know.on cancelMessage pHandlerName
put the pendingmessages into pMess
repeat for each line p in pMess
if item 3 of p contains pHandlerName and \
item 4 of p contains the effective filename of this stack then
cancel item 1 of p
end if
end repeat
end cancelMessage
Monday, 31 March 2008
Sending messages
The best way to have something happen regularly in Revolution is to use the "send" command. e.g. to have a clock display update once a minute, you could have a script like this:on updateClock
put the short time into fld "Clock"
send "updateClock" to me in 60 seconds
end updateClock
To start it off, you would need to call "updateClock", then it would happen automatically every minute. The best thing is that this doesn't tie up any processing time - it just waits for the 60 seconds, then does it again.
on cancelMessage pHandlerName
put the pendingmessages into pMess
repeat for each line p in pMess
if item 3 of p contains pHandlerName then cancel item 1 of p
end repeat
end cancelMessage
So when closing the stack with the clock display, I would have this line: cancelMessage "updateClock"Another problem can be multiple copies of the same message building up. If for example, you sent "updateClock" in the "openStack" handler and again in the "resumeStack" handler, then it would be running twice, with each occurrence spawning another. To avoid this, I use one of two techniques:on updateClock
cancelMessage "updateClock"
put the short time into fld "Clock"
send "updateClock" to me in 60 seconds
end updateClock
on updateClock
put the short time into fld "Clock"
if the pendingmessages contains "updateClock" is false then
send "updateClock" to me in 60 seconds
end if
end updateClock
32792,1206954370.266598,updateClock,stack "Clock Demo"The first item of each line is the message ID, which you need to quote when cancelling that message. The second item is the time that message will happen in long seconds format. Then we have the name of the message and the name of the object that it will be sent to.
36173,1206954417.881484,updateClock,stack "Other Stack"
on cancelMessage pHandlerName
put the pendingmessages into pMess
repeat for each line p in pMess
if item 3 of p contains pHandlerName and \
item 4 of p contains the effective filename of this stack then
cancel item 1 of p
end if
end repeat
end cancelMessage
Now only the messages directed at the relevant stack will be cancelled.Yes, this blog does have a future
Thanks to the people who replied to my last, rather gloomy post. I had forgotten that people reading via RSS would not show up on my hit counter, so it will always be an underestimation. However it was good to know that there are people out there reading and appreciating. Thanks to those who suggested topics as well.
I would also like to thank Bjoernke for his kind words of encouragment and recommend his blog to you all: http://bjoernke.com/.
Expect another Revolution tip tomorrow.
Until then...
Sarah
Tuesday, 18 March 2008
Does this blog have a future?
OK, I've enjoyed setting up this blog and learning how to customise it as I wish. I can recommend Google's blogger to anyone who needs a quick & easy blog, but then allows a lot of variation if you know a bit of CSS.
However, I had hoped for a bit more interest in the blog. After 4 weeks, it has only had just over 200 visitors and only one person has made a comment.
I'm going to have a go at promoting the blog for the next week or so, but if things don't look up, I will consider myself to have learned something, and gracefully allow it to fade away.
If you have any suggestions, ideas or thoughts, please add a comment to this post.
Sarah
