Subclassing information is held at the object level in a set of eleven string
properties, and these can be manipulated directly, that is, with getStringProperty()
and setStringProperty()
, or using the specific accessor methods,
setParentModule()
, setParentModuleType(), setParentModuleStorage()
,
and so on. Note that if you change any of these properties you must call reattach()
which refreshes the object's subclassing references.
The eleven properties consist of three single properties and four sets of pairs. These properties must be set in a specific order specified below:
PARENT_NAME_PTID
PARENT_FILENAME_PTID
PARENT_FILEPATH_PTID
PARENT_MODULE_PTID
PARENT_SOURCELEVEL1OBJECT_NAME_PTID
PARENT_SOURCELEVEL2OBJECT_NAME_PTID
PARENT_MODULESTORAGE_PTID
PARENT_MODULETYPE_PTID
PARENT_TYPE_PTID
PARENT_SOURCELEVEL1OBJECT_TYPE_PTID
PARENT_SOURCELEVEL2OBJECT_TYPE_PTID
The first three properties above identify the source module, and where that
module is stored (file system or database). If the PARENT_FILENAME_PTID
returns a null string then the subclass source is in the same module as the
target object.
The other properties are pairs representing the Forms object name and type for each level of the entire object tree for a given source object. Source objects may exist up to four levels deep and these properties allow us to precisely locate them. The lowest level property with a value set is the source object itself.
Consider the image in Figure 2, showing the Form Builder navigator. A block
is directly owned by a module so only has a two-level tree. So if BLOCK1 is
the source object, then the property PARENT_MODULE_PTID
would be
"MODULE1" and the property PARENT_NAME_PTID
would be
"BLOCK1".
An item is three levels deep so ITEM1 would additionally have PARENT_SL1OBJ_NAME_PTID
set to "ITEM1". PARENT_MODULE_PTID
and PARENT_NAME_PTID
(the owning block) set.
A radio button is four levels deep, so to use RADIO_BUTTON1 as the source object for another object in the same module, you'd have to set the following properties (in this order) on the target object:
JdapiTypes.PARENT_NAME_PTID
to "BLOCK1"
JdapiTypes.PARENT_MODULE_PTID
to "MODULE1"
JdapiTypes.PARENT_SOURCELEVEL1OBJECT_NAME_PTID
to "ITEM2"
JdapiTypes.PARENT_SOURCELEVEL2OBJECT_NAME_PTID
to "RADIO_BUTTON1"
JdapiTypes.PARENT_MODULESTORAGE_PTID
to JdapiTypes.PAMO_FILESYSTEM_CTID
JdapiTypes.PARENT_MODULETYPE_PTID
to JdapiTypes.FORM_MODULE_OTID
JdapiTypes.PARENT_TYPE_PTID
to JdapiTypes.BLOCK_OTID
JdapiTypes.PARENT_SOURCELEVEL1OBJECT_TYPE_PTID
to JdapiTypes.ITEM_OTID
JdapiTypes.PARENT_SOURCELEVEL2OBJECT2OBJ_TYPE_PTID
to JdapiTypes.RADIO_BUTTON_OTID
So, the PARENT_NAME_PTID
and PARENT_TYPE_PTID
properties
always represent a child of the module, e.g. block, canvas etc. The PARENT_SOURCELEVEL1OBJECT_NAME_PTID
and PARENT_SOURCELEVEL1OBJECT_TYPE_PTID
(Source
Level 1 Object) properties
always represent the next level, i.e. a child of a child of the module, like
items, graphics etc. The final two properties represent the lowest level which
includes radio buttons and triggers on items.
import oracle.forms.jdapi.*; /** * Example to illustrate how 'parent' properties can be used to subclass * Forms objects after construction. */
public class SubclassExample { public static void main(String[] args) {// create a module from scratch
FormModule fmd = new FormModule("MODULE_ONE"); Block blockA = new Block(fmd, "EMP"); Item itemA = new Item(blockA, "ID"); Item itemB = new Item(blockA, "NAME"); Item itemC = new Item(blockA, "LOCATION"); fmd.save("D:/work/Module_One.fmb"); fmd.destroy();// Create another form and block subclassed from the first one
// This time using the low-level subclassing properties
fmd = new FormModule("MODULE_TWO"); blockA = new Block(fmd, "EMP2");// Set subclassing for the block
blockA.setParentName("EMP"); blockA.setParentFilename("Module_One.fmb"); blockA.setParentFilepath("D:\\work"); blockA.setParentModule("MODULE_ONE"); blockA.setParentModuleStorage(JdapiTypes.PAMO_FILESYSTEM_CTID); blockA.setParentModuleType(JdapiTypes.FORM_MODULE_OTID); blockA.setParentType(JdapiTypes.BLOCK_OTID);// That's as deep as we need to go for a block
// MUST call reattach for subclassing to 'happen'
blockA.reattach();// Create a canvas and place our inherited items on it
Canvas cnv = new Canvas(fmd, "DISPLAY"); JdapiIterator items = blockA.getItems(); while(items.hasNext()) { Item item = (Item)items.next(): item.setCanvas(cnv);// NB Layout setting (x,y pos etc) omitted
} fmd.save("D:/work/Module_Two.fmb"); fmd.destroy(); Jdapi.shutdown(); } }
Comments: This is the code from the example in Creating, Manipulating, and Destroying Forms Objects rewritten to illustrate the use of the low-level parent properties for subclassing instead if the higher-level (and more convenient) approaches described previously. We've used the specific accessor methods purely for more readable code.
The advantage of the low-level subclassing methods is primarily in programmatically inspecting Forms object subclassing information, since it's quite complicated to actually perform subclassing by this method. However, using this method, the parent object does not actually have to be loaded in the Jdapi session, so you could use this approach, for example, if you knew the details of the parent objects but didn't have access to them at design time.
As stated previously, the source module (MODULE_ONE
) must be saved
before subclassing.
Note that all Forms object names must be in uppercase. The Forms Builder enforces this but the API does not. However, using mixed case names will not work. (This refers only to the name string property of the Forms object and not the identifier for the Java class instance, or module file names on the file system).