ParentExec Attribute
Data Type: FrameExec
4GL Access: RW
The ParentExec attribute specifies the FrameExec that contains the event scripts (On MouseEnter, On Click, and so on) for the field. This attribute must be set in applications that implement multi-document interface (MDI) or portlet-based user interfaces. In an MDI, one or more fields on one frame (the “guest”) are moved and displayed on another frame (the “host”). This can be used to deliver more advanced user interfaces where related functionality is displayed in separate portlets in a single window, effectively flattening the application. The MDI helps to reduce desktop clutter with many windows open at one time while still allowing each function to be programmed independently. This architecture also supports docking and undocking these portlets into their own windows.
The ParentExec attribute is used to ensure that, after fields from a guest are moved to a host frame, any user interaction events (click, entry, exit, setvalue, and so forth) which will now occur on the host are queued to the guest frame where the event logic is actually located. The default value of this attribute is NULL, which indicates that the field is being displayed on the frame where it was originally located. Fields on a guest frame can be moved to a host frame by setting a field's ParentField attribute to a composite field on the host frame. However, before moving a field to a host frame, its ParentExec attribute should be set to the CurFrame value of the guest frame.
As an example, assume that you have implemented a utility frame that uses a date picker. Typically, the date picker is called when the user enters into an entry field with a date data type or clicks on a date picker button next to the field. The date picker appears in a popup window, the user selects a date by clicking the button representing the desired date, and the window closes, returning the selected date to the calling frame. Now assume that in a particular application, you would prefer to embed the date picker directly on a frame because selecting a date is an integral way of controlling the frame. You could use portlet support to do this.
First, you would create a composite field on the host frame that is a place holder for the portlet. In this example, you would create a subform, size it appropriately, and name it “CalendarPortlet.” The initialize block in the host frame would look like the following:
Initialize () =
Declare
CalendarExec = FRAMEEXEC WITH DEFAULT NULL;
EndDeclare
{
CalendarExec = OPENFRAME DatePickerFrame
(Portlet = FIELD(CalendarPortlet));
}
Note that you are passing a reference to the Calendar field to the DatePickerFame. You are also holding a pointer to the DatePicker frame as returned by the OPENFRAME statement to support interframe communications.
Next, you would alter your date picker to enable it to be displayed on a host if a container is passed. Assuming the top composite field on the DatePickerFrame is a composite field called “Calendar,” the code would look like the following:
Initialize
(
Portlet = COMPOSITEFIELD WITH DEFAULT NULL;
) =
{
IF (Portlet IS NOT NULL) THEN
FIELD(Calendar).ParentExec = CurFrame;
FIELD(Calendar).ParentField = Portlet;
CurFrame.WindowVisibility = WV_INVISIBLE;
ENDIF;
}
Note that if the the DatePickerFrame is to be displayed in the portlet, you first set the ParentExec attribute of the topmost field moved, set its ParentField to be the portlet field, and then make the rest of the window invisible. The guest frame will continue to run and receive events, but the window border will not be displayed. Note that only fields on the guest frame can be moved. Moving toolbars, menubars, and statusbars is not supported. Also note that it may be necessary to implement some interframe communications to let one frame know what has happened in the other. In our example, when the DatePickerFrame is used as a popup, the date value selected by the user is returned to the calling frame when the date is selected and the frame closes. When used as a portlet, the host frame must be notified using a user event.
Assuming the Calendar field on the DatePickerFrame has a matrix field called “DaysOfMonth” containing buttons for individual days of the month with each button's ClientText attribute holding the actual date represented by the button, that code would look like the following:
On ChildClick Calendar.DaysOfMonth =
{
IF (Portlet IS NOT NULL) THEN
CurFrame.ParentFrame.SendUserEvent(
EventName='DatePicked',
EventVarchar=CurFrame.TriggerField.ClientText);
ELSE
RETURN CurFrame.TriggerField.ClientText;
ENDIF;
}