Understanding and Using the CallAdjustObjectSize and CallEvaluateContents Properties
Dynamic behavior in a ReportListener class takes place in the EvaluateContents event for Report Expression layout controls, and in the AdjustObjectSize event for shape and image controls. In RTM and SP1, the Report Engine looks for code in the Xbase class hierarchy for the object serving as ReportListener to evaluate whether it triggers these events, which pose a significant performance penalty and perform no native service in the product. In SP2, these two new properties allow an Xbase class to indicate whether it needs each of the two events to be triggered, whether there is code in the class tree for each event or not.
In addition to evaluation of these properties during the report initialization, the Report Engine obeys changes to the values of these two properties after the start of the report. It is possible to change the values of CallAdjustObjectSize and CallEvaluateContents in the BeforeBand event, meaning for all layout controls in a single band. This allows for significant optimization, even for reports that require some dynamic behavior.
For example, reports with layout rectangles in page headers, detail bands, and page footers might have one rectangle in a group header band serving as a placeholder for a summary graph. rendered summary graph. Only the group header band needs the AdjustObjectSize to be calle . Similarly, a report expression in a page header band might have font alterations for some types of presentations, but all the other bands might have a very large number of report expressions not requiring any EvaluateContents adjustments. In these cases, Xbase code can adjust the CallAdjustObjectSize and CallEvaluateContents properties on a band level, at will.
|The FXMemberDataScript TMM docoid provides a simple example of using dynamic, band-specific code to adjust CallAdjustObjectSize and CallEvaluateContents. In the example, the relevant code is attached to a report in developer script, using the Run-time extensions feature, rather than directly attached to a reportlistener. This approach makes especially good sense, because the evaluations needed to optimize EvaluateContents and AdjustObjectSize behavior are FRX-specific rather than general.|
It is not feasible for user code to attempt to fine-tune performance by turning these properties on and off for individual objects rather than between bands. Especially with AdjustObjectSize, it is difficult to predict in what order, or even how many times, these events occur with respect to other layout controls of the same type within a given band, and these event calls occur, as a group, at the beginning of band processing.
For compatibility with RTM and SP1, the default value for these properties (0) runs the method if there is any code in the Xbase class hierarchies. The sample code in both SP2 CHM topics shows how to turn the event-triggering off at the beginning of the report run, by explicitly changing the value to 1, in response to a user option or other setting. However, it is better practice to explicitly set the value to 2 (always call the method) when you need the behavior, as well as setting it off when you do not. This practice ensures that multiple objects participating in a report run have a chance to indicate whether any one of them needs the event. It also ensures that the event is called even in cases where the event itself has no Xbase code but an external object has used BINDEVENTS to attach code.
|It is good practice for objects to adjust these values only up, never down, as each object participating in a report run determines its requirements for the report or the report band, so that once any object has indicated a need for the event by setting the value to 2 its "vote" is the deciding one.|
The following code is the PROTECTED adjustDynamicCalls method
of the FXMemberDataScript
class. Notice that
the class does not adjust the values of CallAdjustObjectSize or CallEvaluateContents
if the value of either property is already 2 (#DEFINEd as LISTENER_CALLDYNAMICMETHOD_ALWAYS):
* change m.toListener.CallEvaluateContents and * m.toListener.CallAdjustObjectSize if necessary SET DATASESSION TO (m.toListener.FRXDataSession) IF INLIST(m.toListener.callEvaluateContents,; LISTENER_CALLDYNAMICMETHOD_CHECK_CODE,; LISTENER_CALLDYNAMICMETHOD_NEVER) SELECT FRX GO TOP SCAN FOR ObjType = FRX_OBJTYP_FIELD AND Platform = FRX_PLATFORM_WINDOWS IF THIS.useMemberData(RECNO()) SELECT (THIS.scriptAlias) IF ATC("EvaluateContents",ExecWhen) > 0 OR ; ATC("EvaluateContents",Execute) > 0 OR ; (NOT EMPTY(UserScript)) * UserScript for a Field-type item * has to be EvaluateContents m.toListener.callEvaluateContents = LISTENER_CALLDYNAMICMETHOD_ALWAYS EXIT ENDIF ENDIF SELECT FRX ENDSCAN ENDIF IF INLIST(m.toListener.callAdjustObjectSize,; LISTENER_CALLDYNAMICMETHOD_CHECK_CODE,; LISTENER_CALLDYNAMICMETHOD_NEVER) SELECT FRX GO TOP SCAN FOR Platform = FRX_PLATFORM_WINDOWS AND ;
INLIST(ObjType,FRX_OBJTYP_LINE,FRX_OBJTYP_RECTANGLE,FRX_OBJTYP_PICTURE) IF THIS.useMemberData(RECNO()) SELECT (THIS.scriptAlias) IF ATC("AdjustObjectSize",ExecWhen) > 0 OR ; ATC("AdjustObjectSize",Execute) > 0 OR ; (NOT EMPTY(UserScript)) * UserScript for a Shape-Picture-type item * has to be AdjustObjectSize m.toListener.callAdjustObjectSize = LISTENER_CALLDYNAMICMETHOD_ALWAYS EXIT ENDIF ENDIF SELECT FRX ENDSCAN ENDIF