.CurrentRecord runs twice

In a new, empty database and only a procedure named .CurrentRecord and nothing but Message “X” in it, every time the active record is changed or a new record is added, the procedure s run twice.

I tried your steps and it does get called twice when a new record is added. I only get it once when using the up or down arrows or when clicking on a row. Looking at the source code, this seems quite possible.

I’m going to enter this into BitBucket with a priority of “trivial”. I’m not sure it is worth my spending any time on this. A .CurrentRecord procedure should contain only a tiny amount of code that runs in nearly zero time. If it contains enough code that running it twice is a problem, it probably contains too much code. Personally I can’t remember when I’ve even ever used .CurrentRecord in the last couple of decades, I really dislike the feature. If there’s some case where this is a realistic problem I haven’t thought of, please let me know. On the other hand, it may be very fast to fix so I will probably spend at least a few minutes to determine that, and if so, fix it.

I have “fixed” this issue by documenting that .CurrentRecord may be triggered more than once when certain operations are performed. I spent about 90 minutes trying to fix the problem, but only succeeded in determining that there is no simple fix, and that if a fix is possible at all, it is likely to take days of work. So this behavior is not going to change. I also revised the documentation to even more strongly discourage use of the .CurrentRecord feature.

FWIW, the documentation already stated that the .CurrentRecord procedure should never display an alert. I’m surprised this worked at all. However, it turns out that the message statement was not the problem, the problem is rooted deep in Apple’s mechanism’s for displaying tables (like the data sheet).

I’ve run into another scenario in which .CurrentRecord runs in a loop. I have a video of it.

You wrote that you can’t imagine a scenario for using it, but I use it constantly. In this case, as a record is activated, I use related array( to grab info from another database. Then I run other array processes to break it down to display as text in a form. Date of Last Payment, Max Payment, YTD Payments, Last Year’s Payments… all initially acquired in a single array of dates and amounts. It’s extremely fast and I can click from record to record with no noticeable delay.

But when I stop on a record the text blinks over and over due to the loop in .CurrentRecord.

The alternative is to use four complex related arrays in the form. I did that and it was taking about 4-5 seconds to draw. Considerably slower and actually unusable since it’s starting with the same relatedarray( each time then running it through similar breakdowns.

How would you suggest that I avoid using .CurrentRecord while also avoiding the speed hit of multiple embedded formulas? Form events don’t seem to be the way.

FWIW: Pan X has a feature that sets a maximum time limit for running procedures to avoid endless loops. Have a look in Panorama X Preferences > Advanced.

The problem is that .CurrentRecord shouldn’t loop at all, but the recommendation is not to use it. So the challenge is in how to reload variables when a different record is accessed.

Putting a message into .CurrentRecord is noted in the documentation as possibly causing a loop, but I added one only after I saw the variables blinking in the form - and zlog simply wouldn’t post anything.

Without it, variables are left with values from the last record that load them.

I remain at a loss for how to reload variables when the active record is changed.

I’ve tried intercepting every process I can think of that changes records, but there’s always another. Find, Search, Delete, Add New…

I am reluctant to make a suggestion when you likely know a lot more than I do. But if you display the data in a text list, you can trigger a procedure when you select a different row that will make the variable assignments you want.

You just found a bug.

For now (and possibly permanently), you can use the zlogalways statement. Or you can use the zlogcoverage statement.

This is waaaaaaay more processing than what .CurrentRecord was designed for. You are really tempting me to simply remove this feature, it is too subject to what I would think of as abuse.

I think this is a much better idea than using the .CurrentRecord procedure. Though you might find that may also trigger more than once (I don’t know, but it wouldn’t shock me. Internally the data sheet, text lists and matrix objects all use the same Apple class called NSTableView. I’ve found that NSTableView tends to send out extra notifications of state changes. Since I don’t have access to NSTableView’s internal state, there’s no way I can differentiate extra notifications. The notifications are what Panorama uses to trigger automatic procedures.)


I do have one possible idea for you. At the beginning of your .CurrentRecord code, you could use info(“serverrecordid”) to see if the record has actually changed. If it hasn’t changed, you could simply return without doing anything.


I also want to make sure you are aware that .CurrentRecord only runs in response to user input. It does NOT run if a procedure changes the current record. So the code

downrecord

will not cause .CurrentRecord to run. You would need to explictly trigger it in this situation, like this:

downrecord
call .CurrentRecord

The reason is because you may move the record multiple times in a procedure, and you don’t want Panorama to call .CurrentRecord each time.

The list does seem to run twice - sometimes. I’ve had a hard time telling. Regardless, the situation here is a form with lots of customer info that (for instance) the user will look at, then move on to the next and the next. They’re likely to use the arrow keys but could click on a record in the data sheet while the form is open. Adding a list and expecting them to use that to go from record to record and nothing else is similar to where I’m at now in trying to find every method they have for changing records and creating my own equivalent of .CurrentRecord.

I’ll give that a try. I had gone to using relatedid( but that ran repeatedly too.

And therein lies the probable issue. Later last night I found that the blinking I observed was brought on by movement of the mouse.

Are you saying moving the mouse without clicking on it? Panorama does not ever process the mouse location except when it is clicked. Perhaps there is some Apple code that is doing that, but that seems unlikely to me since generally the application (in this case Panorama) receives the mouse down event, then passes it along to whatever user interface element that needs it. Panorama only handles and passes along mouse down and key down events – it completely ignores mouse movements when the mouse isn’t down. The only exception is tooltips, but that is handled by Apple code, no Panorama code is invoked to display a tooltip.

I don’t suppose you have some third party system extension of some sort that might be causing weird behavior?? Probably not, but at this point, I think I have to ask.

Here is something to try out if you want. Taking a clue from Jim with the info(“serverrecordid”) scheme and the fact that the .CurrentRecord actually uses a timer to function, I tried a slightly different approach that eliminates the auto-function of the .CurrentRecord procedure altogether.

First change the name of your .CurrentRecord procedure to .currentRecord (lower case C). This will keep it from automatically being triggered and still keep it out of the Action menu. Now in your .Initialize procedure (or any procedure just to test it) put the following timer code:

starttimer "CurrentRecord", "code",{define fgRecordCheck, info(“serverrecordid”)
If fgRecordCheck ≠ info(“serverrecordid”)
	fgRecordCheck = info(“serverrecordid”)
	call .currentRecord
Endif}

This will create an always running timer that checks every second to see if the current record has changed and then run your .currentRecord procedure if it has changed. In my simple tests it seems to work reliably but would need further testing in more robust situations.

Hope maybe it is of some use.

P.S I tried reducing the interval from the default of 1 second to .5 seconds and it was even more responsive.

Very clever Gary. Using a timer to check the id would very probably do the trick.