| By Hoyt Nelson | Article Rating: |
|
| April 1, 2001 12:00 AM EST | Reads: |
7,207 |
In my previous article (PBDJ, Vol. 8, issue 2), I demonstrated the Object Name feature of the debug popup menu. The popup menu is a developer's tool invoked by holding down a magic key as you right-click a window or control. The initial and most useful debug menu item is Object Name, which you can use to identify any object in your PowerBuilder application as you run the application. Selecting Object Name as you right-click a DataWindow produces output like that shown in Figure 1.
Each line in the message box represents a level in the object hierarchy, with the upper item contained within the item immediately below. To the left is the name of the object as shown in the Library Painter, i.e., its development-time name. The item in brackets is the object's containing PBL. To the right is the object's ClassName(): its runtime name.
The first debug article left some subtopics unexplained. One is the technique for identifying which PBL contains a DataObject. For non-DataObjects, the ClassDefinition.LibraryName suffices, but you have to jump through some hoops to get the equivalent information for a DataObject. I postponed clarification of how f_get_parent_objects() works. I also promised to describe the f_set_default_pbl() function, which is short and simple, and makes Object Name one click easier to use. This article clarifies all of these items. By the end you'll have all you need to create your own debug menu with Object Name!
Why should you care? It is valuable to be able to click your application and immediately know the name of the DataObject and the PBL that contains it. This may seem like more trouble than it's worth. If you're having a hard time tracking down an object, this could be a big help. And remember, you can always just download the associated code from www.SYS-CON.com!
Stashing Objects
Before the ClassDefinition attribute arrived with PB6, I needed to be able to find out which PBL contained a given object, for such purposes as exporting an object's source to facilitate a search-and-replace. A series of functions provided the means, and they're still useful for DataObjects. The technique is to import all the application's objects into a DataObject, import that DataObject into a PBL, and quickly reference the object list as needed.
The following code stashes the object list. The indented functions are called by the preceding function, e.g., f_get_library_list_ as_array() is called by f_stash_library_ object_list().
f_stash_library_object_list()Listing 1 presents f_stash_library_object_ list().
f_get_utility_dw()
f_get_library_list_as_array()
f_load_dw_with_pbl_objects_by_type()
f_get_application_pbl_and_name()
f_library_import()
1. Get a working DataWindow and assign it to the DataObject dw_pbl_directory.
The working DataWindow is one way to work around the problem discussed in
my article "Writing Functions for All DataWindow-ish Types" (PBDJ, Vol. 8, issue 1). What you'd like in your script is a DataStore, but you're seemingly limited by functions that work with DataWindows. You could follow the "DataWindow-ish" prescription for adapting your functions to all DataWindow-ish types. Or, you could use a utility DW, and treat it as you would a DataStore.
f_stash_library_object_list() takes the second approach.
The utility DW is an ordinary DW that resides on some global window that is certain to be open, such as the main desktop window of your application. Make the DW invisible in its constructor and return it with a function call. My f_get_utility_dw() (see Listing 2; all listings are available at www.PowerBuilderJournal.com) provides for the missing main desktop window if we're running the testbed. Refer to the previous debug article (PBDJ, Vol. 8, issue 2) for information about the testbed.
The DataObject dw_pbl_directory has the typical columns required for importing the results of a Library Directory() call: object name, modified date, and Library Painter comment. It also has two additional columns: PBL name and object type.
2. Get the set of PBLs that comprise
the application.
The function f_get_library_list_as_array() examines the PB.INI file to identify the set of PBLs that comprise an application. See Listing 3 for all the details. You'll find f_find_pb_ini2() mentioned; replace that with your PB.INI file's location, hard-coded. f_get_library_list_as_array() also calls f_parse_item_string(), which parses a string and places its contents into an array.
3. Import all the objects in the application into the working DW.
This is accomplished by f_load_dw_with_pbl_objects_by_type() (see Listing 4). This function is artful in that it executes a separate LibraryDirectory() for each type
of PB object: DataObjects, Windows, UserObjects, etc. Before it imports the resultant string into the accumulating DataWindow, it performs a substitution that embeds the PBL name and the object type into the LibraryDirectory() result string. This causes the PBL and type to be imported into the DataWindow along with the rest of the LibraryDirectory() information.
The suffix below corresponds to the letter that PowerBuilder appends to exported objects to indicate the type: "d", "w", and "u" for DataObjects, windows, and UserObjects.
ls_directory = f_substr( ls_directory,At this point I have a working DW with a PBL populated with the usual Library- Directory() information (object name, modification date, and Library Painter comment), along with each object's containing PBL and a single-letter indicator of the object's type.
"~n", "~t" + the_pbls[ j ] + "~t" + &
ls_suffix + "~r~n" )
Next, I need to stash the object list, which means that I need to import the object list into the application, retaining the data I just imported!
4. Get the syntax of the now-populated list of application objects.
These are available as DataWindow attributes you can describe as follows:
ls_dwo_syntax = &The "DataWindow.Syntax.Data" is the part that returns the syntax for the object names and related elements that I imported into the DataObject in the step above "Import all the objects in the application into the working DW."
ldw_work.describe( "DataWindow.Syntax" )
+ &
ldw_work.describe(
"DataWindow.Syntax.Data" )
5. Get the name of the application object and the name of its PBL.
See Listing 5. The function f_get_application_pbl_and_name() looks up the application object name and the PBL in the PB.INI file. Again, you'll have to hard-code the location of your PB.INI file.
6. Import the syntax.
The application object name is used to define the name of the DataObject to be imported. This allows a given PBL to contain multiple stash DataObjects: one for each application object in that PBL.
ls_dwo_name = "dw_" + ls_app_name +Listing 6 shows how f_library_import() works. This function applies a very superstitious, possibly unviable, theory of mine; opening an invisible window before the LibraryImport() makes the import more reliable. Hey, it doesn't hurt! Just create a window and make it invisible.
"_objects"
if f_library_import( ls_app_pbl,
ls_dwo_name, &
ls_dwo_syntax, ls_comment ) then exit
So what have we accomplished? We now have, as a permanent DataWindow Object in the application, something named dw_
This is how Object Name gets the PBL that contains the DataObject. The PBL name and the object's type are out of sight, off to the right.
Using the Stashed List of Objects
f_get_parent_objects2()
f_set_default_pbl()
The DefLib was set to "e:\p2k\pontfunc.pbl" when the Figure 3 dialog was opened.
The function f_set_default_pbl() simply sets that attribute (see Listing 9). As a result, when you use Object Name to identify the name and containing PBL of an object in your application, the DefLib attribute is set so your next Select <Object Type> operation has the containing PBL pre-selected for you. It saves you from navigating the list of PBLs at the bottom. (Is that cool? Or am I just off-the-chart lazy?!)
Summary
You have all you need to create your own Object Name debug menu item. Or, just visit
www.SYS-CON.com to download the source! Check it out!
The function hierarchy for getting an object out of the stash is simpler.
f_get_library_object_from_stash()
I have a favorite function, which
returns the utility DataWindow used by f_get_library_object_from_stash() to look up an object using the Find() command. See Listing 7. This function executes quickly.
f_get_utility_dw()
Ignore the "2" - it merely indicates that this is a variant of the original. The source is shown in Listing 8. This function loops up the control hierarchy until it reaches the containing window. Because the debug menu is always invoked from a visual object, you can depend on eventually arriving at the parent window. En route, f_get_parent_objects2() builds the string that describes the object hierarchy, including the ClassDefinition.name attribute that is the development-time name of the object.
This simple function makes Object Name a little easier to use. If you look in your PB.INI file (pre-PB8, I am informed), you'll see something like the following:
[Application]
The function f_set_default_pbl() sets the DefLib entry. This is where PB stashes the information that the last PBL you operated on was pontfunc.pbl. If you open a PBL in the Library Painter, for example, DefLib is set to the name of that PBL. The next time you open the Select <Object Type> dialog, as in the Select DataWindow dialog in Figure 3, the PBL identified by the DefLib will be pre-selected.
DefLib=e: \p2k\ pontfunc.pbl
AppLib=e: \p2k\ pontappl.pbl
AppName=pont
This article presents a somewhat round- about method for identifying the PBL that contains a DataObject and the code for retrieving that information at runtime. The immediate application is in the Object Name script shown in Part 1 of this series (PBDJ, Vol. 8, issue 2), where the PBL containing the DataObject of interest is identified. I also addressed the promised subtopics that didn't fit into the previous articles, including the functions for recursion up the tree of containing objects and for setting the default library.
Published April 1, 2001 Reads 7,207
Copyright © 2001 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Hoyt Nelson
Hoyt Nelson is an independent contractor, a 10-year PowerBuilder veteran, and father to the amazing Nelson, Kent, Emma, and Molly (Hi, kids!).
- Why SOA Needs Cloud Computing - Part 1
- Cloud Expo and The End of Tech Recession
- The Transition to Cloud Computing: What Does It Mean For You?
- A Rules Engine Built in PowerBuilder
- Sybase Named “Silver Sponsor” of iPhone Developer Summit
- How PowerBuilder Got Its Groove Back
- The Cloud Has Cross-Border Ambitions
- Ulitzer Names The World's 30 Most Influential Virtualization Bloggers
- Ulitzer Named "New Media" Partner of Greatly Anticipated iStrategy Event in Berlin
- Risks and Enterprise Mobility?
- Steps for Success in Enterprise Mobility?
- Are Mobile Luddites Resisting Mobility?
- The Difference Between Web Hosting and Cloud Computing
- Sybase CTO to Speak at 4th International Cloud Computing Expo
- Why SOA Needs Cloud Computing - Part 1
- Cloud Expo and The End of Tech Recession
- The Transition to Cloud Computing: What Does It Mean For You?
- Five Reasons to Choose a Private Cloud
- Seeding The Cloud: The Future of Data Management
- The Threat Behind the Firewall
- Economy Drives Adoption of Virtual Lab Technology
- Tips for Efficient PaaS Application Design
- A Rules Engine Built in PowerBuilder
- Sybase Named “Silver Sponsor” of iPhone Developer Summit
- Where Are RIA Technologies Headed in 2008?
- PowerBuilder History - How Did It Evolve?
- The Top 250 Players in the Cloud Computing Ecosystem
- Custom Common Dialogs Using SetWindowsHookEx
- DDDW Tips and Tricks
- OLE - Extending the Capabilities of PowerBuilder
- DataWindow.NET How To: Data Entry Form
- Book Excerpt: Sybase Adaptive Server Anywhere
- Sybase ASE 12.5 Performance and Tuning
- Working with SOA & Web Services in PowerBuilder
- Office 2003 Toolbar: A New Look For Your Old PowerBuilder App
- Dynamically Creating DataWindow Objects
































