AN1009 - Scope and Name Searching

From Serious Documentation
Jump to: navigation, search

When you use a named object's name in a reference (e.g. "myPageFrame.oh" or "image7.ow") in a script or a layout rule, how does SHIPTide "find" that object? If there are two objects or more with the same name in your GUI, and you reference that name, which one does it pick to refer to?

This app note discusses how SHIPTide does "name searching" and the various developer options to control and manage unexpected behavior.

This video portion of this app note is currently in production; thanks for your patience.

Name Search Rules

When an object name is explicitly referenced in a script or layout rule, there is a predictable and explicit search pattern SHIPTide uses to "find" that referenced object name.

The search always starts at the "referring object" -- i.e. the script or layout rule making the reference, and proceeds as follows:

  • The parent object's name is checked for a match
  • If the parent name does not match, then direct siblings to the referring object (i.e. direct children under the parent) are checked for a name match
  • Especially note that children under siblings are not searched: those names are private/local to the siblings
  • If no direct sibling matches, the search recurses upwards to the parent's parent and repeated
  • This recursive search upwards stops at the top of the "area" that the refer-er lives in (e.g. layout, resources, etc.)
  • Depending if the global project Name Search Options are enabled, SHIPTide may now traverse top-down the platform, then resources, then cargo, then layout areas looking for the first occurrence of that name
  • If the name is still not found, SHIPTide shows a reference error

Anonymous Typed Object Search Rules

When, instead of an explicit object name, you use an anonymous object type (for example "frame" or "box"), the search rules are more restrictive to avoid serious confusion in your references. They are similar to the named search rules, but siblings are not included in the search:

  • The parent object's type is checked for a match
  • If the parent type does not match, the search recurses upwards to the parent's parent and repeated
  • This recursive search upwards stops at the top of the "area" that the refer-er lives in (e.g. layout, resources, etc.)
  • If the object type is not found in the direct parent[.parent]* chain, SHIPTide shows a reference error

Note there is no global search applied for object type references.

Qualified vs. Unqualified Names

Name references can be "qualified" or "unqualified". If you use an object name alone, such as "varA", this is an unqualified reference. You are not "qualifying" its location. On the other hand, if you say "parent.varA", this is a qualified reference: varA must be a child directly under the parent. Similarly if you use "layout.d0.homePage", since "layout" is a reserved name of the layout area, the name is a "fully qualified name" since it is starting at the top and insisting that varA be a child of something named "d0" which must be a child of "layout". This is much like file names in DOS/Windows, where you can specify a fully qualified name such as "C:/folderA/folderB/fileA.png", or, if you're in that folderB, you can just say "fileA.png" as an unqualified name and the folder is assumed.

For example, study this sample GUI area where the unqualified names "varA" and "varB" are referenced:

Unqualified Name Searches

varA and varB are "unqualified" names, since there is no prefix in front of them. Step 1/1X shows how the parent then direct siblings are tested and did not match. Note also that under "varFoo" even though the objects "varA" and "varB" exist those are private/local to the varFoo sibling and are not found/searched. You can explicitly reference them through "qualified" references (see below) but unqualified searches do not dive into sibling.

Step 2/2X shows the upwards first recursion of the search pattern, as does step 3/3X. At step 4, we hit the "Layout" top level node where recursion stops.

At that point, global search rules take over (assuming they're enabled, see #Name Search Options below) and in this example the Layout global search is enabled so the very first top-down version of the varA and varB names are matched.

In this example, this is probably not what you wanted. You probably wanted the varFoo more-local varA and varB objects.

To be paranoid -- perhaps wisely -- and ensure you're always getting the one you expect, you may want to turn off the global search feature so that only strict reference scoping is allowed. That way you never get an object you don't expect matching your reference.

But that doesn't change the question of how to get the varA and varB objects you wanted in the first place... the ones under "FrameA.varFoo". The solution is to qualify the reference names:

Qualified Name Searches

In this case, the layout rule in BoxA does not use the unqualifed "varA" and "varB" names, but rather qualifies them with "frame.varFoo.". This is a combo anonymous and qualified name. The "frame" keyword says "use the search pattern to find the first object of type frame". It does that in step 1 in the diagram. Then, once it has matched "frame" to the FrameA, it must find a direct child to the frame named "varFoo" which it does. Then it must find varA and varB directly under that.

If you referenced "PageA.varA" as a qualified name in BoxA, the search algorithm would do the local/upwards recursion, and find PageA, then dig into that and find varA there.

Scope-Prefixed Searches (v5.1.125+)

Introduced in SHIP v5.1.125, Scope-Prefixed Searches add one more useful twist on name searching.

When the reference is prefixed by an object name/type followed by a double colon, for example "page::<reference>", the prefix (in this case the anonymous type "page") is searched according to the standard search rules.

Global searches are never performed on anonymous (object type, e.g. "box') prefixes, only the standard upwards parent recurse pattern as there are so many (for example) "frame" objects it would be impossible to be predictable from a GUI designer's perspective. There is one exception to the global search concept with the scope-prefix system: the key global root objects (see Global Root Names) can all be referenced in scope-prefixes by name or type irrespective of the developer options/global search settings. Since the names and types of these objects are unique, there is no ambiguity in these references. This means even with global searching disabled, you can always use the object names or types of these key root names, such as “resources” (the type) or “Resources” (the name).

Once the prefix is found, the rest of the reference is searched in a "local global" fashion from that node/object downward. This is a deep tree search, finding the first match for the first element of the <reference>. For example, "page::foo.bar" will look upwards only for the nearest "page" type parent (according to the standard anonymous search rules). Once that page object is found, this page is the "scope" for the deep search for the first occurrence of something named "foo". When it finds foo, it expects "bar" to be a direct child.

Here is another example:

Scoping Rules - Scope Prefixed

Qualified Names and the Search "Anchor"

When you refer to an qualified name, for example "PageA.varA", in a script or layout rule, the first item in the "dot" notation list (in this case "PageA") is the "anchor" object. The search is run on this name according to the algorithm above irrespective of what comes after the anchor name. For example, if "frame" is the anchor name -- in this case an anonymous object type typically looking for the nearest parent frame -- then the nearest parent frame type object becomes the anchor.

Once the anchor is found, the remainder of the qualified name must be matched strictly in the parent-child-grandchild type relationship. There is no more searching done on the second, third, and subsequent names. .

Name Search Options

Under the "Tools->Options->Developer Settings" area in SHIPTide you can modify the global search behavior to enable/prevent global name searching.

These options are turned on by default to preserve legacy behavior in projects, however we strongly recommend you consider at least turning off the "Include Layout" search so that scripts and layout rules must refer to other layout objects more explicitly and you don't end up referring by accident to an object with the same name somewhere remote and unexpected in your GUI Layout.

Name Search Options

Global Root Names

In your name search constructions, you can always use the reserved area type and/or their respective names which are always unique in the system and always refer absolutely to their respective areas. This is irrespective of the global search options selected. To be clear, even if all global searching is disabled, you can always, for example, reference "resources" (the type) or "Resources" (the name) of the unique system root object holding the resources area, even if this reference is from the a layout area object.

Here is a list of the global names/types of the top (aka root) objects:

Node Type Node Name Description
resources Resources Holds all reusable items, such as images, fonts, audio clips, etc.
layout Layout Holds the layout description of your GUI
platform Platform The accessible hardware aspects of your platform described in the GUI Reference Manual (GRM) for your module

Notes

Known Issues/Errata

  • none

Related Content

  • AN0321 - Node Names and References covers discusses how to name objects and reference object from scripts, listeners, and layout rules. It covers direct references by name, anonymous reference by node type (e.g. page.visible), and anonymous relative references (e.g. parent.iw).