Combining Visual Development Environments

Our author mixes and matches the best features from Rogue Wave's JFactory and Symantec's Cafe to create his JavaTax applet, web-based software for tax preparation.


December 01, 1996
URL:http://www.drdobbs.com/jvm/combining-visual-development-environment/184410080

Java Sourcebook 96: Combining Visual Elements

Combining Visual Development Environments

JFactory and Cafe mix it up

Wm. Ellis Oglesby

Rogue Wave's JFactory and Symantec's Cafe are visual tools for Java-based development. Fundamentally, Cafe 1.20 is a fast compiler with a graphical debugger, a class browser, an editor that highlights Java syntax, a screen painter, and a code generator. It is an open environment, so you can add menu items to the Tools popup to spawn stand-alone applications such as Netscape Navigator or a calculator. Cafe organizes these tools in a tabbed desktop, allowing you to set up one desktop configuration for editing, another for debugging, and another for browsing. A tab control allows swapping between desktops, and you can easily add new tabs for new configurations.

JFactory 1.1, on the other hand, is primarily an application designer and code generator. It includes JWidgets--a collection of packages that augments the JDK with toolbars, image buttons, animation, and a table object. In addition to the WYSIWYG screen-painting facilities, JFactory includes an option that allows programmers to run prototypes--not just individual screens but entire interfaces--before compiling. JFactory is also an open environment. After code generation, it can spawn a command-line compiler, debugger, and applet viewer. It also allows you to add tools like Navigator to its menu structure.

Theoretically, JFactory and Cafe are complete solutions to visual Java development, but they have different strengths. In developing the JavaTax project I present here (available electronically), I used the best features of each. In the process, I learned the hazards and rewards of mixing and matching third-party tools.

JavaTax

Tax-preparation software is ideally suited for a web-based applet. Online tax-return filing is yesterday's news, so online preparation must be the next logical step. Taxpayers generally only file once a year, so it makes sense to rent the software for one-time use. HTML is the perfect medium to navigate the tomes of IRS regulations and requirements, but return preparation requires calculation. Users could print a copy for their records and e-mail the other to Uncle Sam. Finally, the emergence of electronic signatures and online banking could provide the technological infrastructure and safeguards needed to make online tax preparation a reality.

JavaTax takes users step-by-step through the U.S. Form 1040 via a series of "wizard" dialogs, accepting tax data and automatically calculating subtotals and totals. When the 1040 requires data from other forms or schedules, such as my personal favorite, Schedule C--Profit or Loss from Business, JavaTax offers a button that pops up the appropriate form. When complete, the schedule data is automatically transferred to the 1040. Users can navigate back and forth through the screens, massaging the numbers until they reach an acceptable bottom line. Finally, a print option simulates printing the tax return and a submit button pops up an animation of a shrinking dollar sign that simulates sending the data back to the server. A commercial version of JavaTax would require implementing these features, but that is beyond the scope of this article.

Making Tools Work Together

In theory, Cafe and JFactory fit together well. Prototype the front end with JFactory. When that's done, generate the code and load it into a Cafe project. Use Cafe's integrated editor, class browser, compiler, and debugger to add data structures and calculation functions. Voila! A finished application.

Unfortunately, I don't write applications like that, and I'm not sure anyone else does, either. Even late in the development cycle, I find myself in the Designer, resizing text fields or correcting spelling mistakes in dialog captions. This blurs the line between prototyping and developing, making tool integration more error prone.

When integrating tools for projects such as JavaTax, the first task is to set up the desktop. After adding JFactory to Cafe's menu bar, I create a new workspace tab for designing. It contains only two Cafe tools: the class browser and the project manager. Fortunately, Cafe does not frame its tools within the application window (MDI style). The "empty" space on the display is available for JFactory components, such as Project Manager, Object Manager, and Designer. Figure 1 shows this arrangement in action.

JFactory's Project Manager (Figure 2) organizes all interface objects in a hierarchy. Applications contain windows and dialogs. Windows contain menus, toolbars, and controls. Menus contain menu items. Toolbars contain tool items and controls, and so on. Creating a new project adds one window (an applet frame) to the project manager. Users can add new objects by right-clicking on object containers.

Every interface object has a set of properties (such as location or color) and a set of events to which it can respond (gotFocus, lostFocus, clicked, and the like). These are listed in JFactory's Object Manager (Figure 3). A programmer can modify these properties at any time.

Double-clicking on a window or dialog in the project manager opens that object in JFactory's visual designer--a floating canvas with a tool palette for drag-and-drop construction of windows and dialogs. It has all the sizing, spacing, and alignment features expected in a WYSIWYG screen painter. In addition to the standard Java components (text areas, choices, buttons, and so on), JFactory's tool palette supports JWidgets, and JavaTax takes advantage of these highly graphical features.

Building the Applet Interface

Since the JDK 1.03 does not support menubars in applet frames, JavaTax (Figure 4) is driven by a toolbar with three tool buttons: one to fill out the return, one to print it, and one to submit it. Dragging, dropping, and aligning these components in the designer is a 60-second task. In the Object Manager, I specify how the components respond to mouse clicks. Choices include calling an external object, linking to source code, and popping up windows and dialogs.

The tax return itself, as everyone knows, is an interminable series of lines, each consisting of a line number, some explanatory text, and a blank to enter the data. Form 1040 groups these lines into sections for Income, Tax Credits, Payments, and other categories. JavaTax reproduces this form with a series of wizard-like dialogs. Labels hold the line numbers and explanatory text, and text fields provide a mechanism for data entry.

Graphical buttons on the bottom of the dialog allow users to cancel the task or navigate through the form. In total, JavaTax uses eight graphical buttons: five dialog buttons (Okay, Cancel, Prev, Next, and Finish) and three toolbar buttons (Process, Submit, and Print). The bitmap associated with each of these must contain images for six possible button states: off, off disabled, off depressed, on depressed, on, and on disabled. Because JavaTax uses single-state buttons, only three slots are actually used. Creating these six-slot images is one of the most time-consuming steps in the entire project.

Although the content of the wizard pages is varied, the layout is essentially the same. Instead of creating each dialog individually, I design a generic page with ten labels, ten text fields, and three buttons; and I store it in JFactory's Object Gallery. This is a holding tank for reusable applications, windows, dialogs, and menus. A large firm might use this feature to maintain company-standard screens like logon dialogs and About boxes--situations where multiple applications use the same compound objects--but it's also an easy way to store templates. Now, when I create a new dialog, I can choose from JFactory's prepackaged dialogs (blank, About, and standard), or select my own wizard. From the template, I create nine wizard pages and modify their properties in the Object Manager. Though some dialogs require other components, such as group boxes, radio buttons, and button links to other forms, the Object Gallery cuts the interface development time in half.

When the interface is complete, I can test it to make sure it behaves as expected. Although I have not yet compiled it, it looks just like it's running in the applet viewer. It proves I'm on the right track before I begin adding back-end code.

Generating, Compiling, and Running

After achieving the desired interface, JFactory generates the corresponding Java source code. You have the option of generating a .java file for each object or one large file. Like any other application generator, the code is longer than what an experienced programmer would write, but it is well commented and easy to follow. Most importantly, it works. I could only find one situation that makes JFactory generate compiler-choking code--defining the applet frame to be an empty dialog--but this doesn't seem like a practical problem.

JFactory provides the option of compiling the files with javac and starting the applet viewer. For what it's worth, it works just fine, but I haven't used command-line tools since Reaganomics. Instead, I simply click on Cafe's Browse workspace tab. JFactory disappears, obscured by Cafe's project manager, class browser, and hierarchy editor.

Adding Custom Code

There are three tasks to accomplish programatically in Cafe:

Cafe's Project Manager organizes the files that comprise an application. Since JFactory does not automatically generate the project, you must create a new one, add the generated source files, and point Cafe to Rogue Wave's JWidget package. Once the project is correctly defined, the application compiles and executes without any problem. If I have bugs down the road, I can't blame them on the tools (I can blame them on the JDK).

Using the Class Browser

I prefer to do all my work in Cafe's browser. Like the editor, it highlights Java syntax. The top-left panel lists the applet classes either alphabetically or in their creation order. The top right shows the methods and data members of the selected class, and the bottom half displays the corresponding source code. Because Cafe's parser is independent of the compiler, it is not necessary to recompile to update the browser. This tool gives a good class-oriented overview of the application.

The only problem with using Cafe and JFactory together is trying to add member data and methods via the browser in such a way that JFactory doesn't overwrite them when it regenerates the code.

JFactory preserves user code by placing protect blocks at locations throughout the source. When it regenerates the application, it simply copies the contents of these blocks into the updated file. It is a flawless system, as long as the programmer doesn't make changes outside of these safe zones. Protect blocks occur often, so this shouldn't be an inconvenience. For example, Hello World has 14 of them.

Example 1 is an excerpt from the main applet class definition as generated by JFactory. The protect blocks are marked by the comments zpb_begin and zpb_end.

Of course, Cafe isn't aware of these protect blocks, and it has its own ideas about where to place code. When I use the browser to add member data or methods, they appear at the top of the class, and user classes are declared at the bottom of the file unless a new source file is specified. If the code remains in these places, JFactory erases it when it regenerates the application.

Simple workarounds include using the editor to define new members within protect blocks and flesh them out in the browser, or cutting and pasting into protect blocks. Either way, Cafe's browser finds them just fine.

Data Storage

JavaTax uses a custom data class, taxData, to store and calculate its data. This keeps all the information in a central location, and simplifies calculations involving data from multiple dialogs.

I created the new class with Cafe's Hierarchy Editor (Figure 5). It's basically an interactive class diagram that can manipulate an application's inheritance structure. By default, the Hierarchy Editor places new base classes in their own file. Because JFactory is not aware of this file, it is completely safe to regenerate code. In addition to a default constructor, the taxData class contains variables to hold the application's data and a calculate() function that computes all subtotals and totals at once. This ensures the data is always current. When the application is initialized, I instantiate the taxData class by adding a line to the appropriate protect block, as in Example 2.

Each dialog class has a protect block for "user variables" where I've added the entry taxData myTaxData=taxapp.pTaxData, which allows each dialog to manipulate the tax-data object directly.

Managing the Text Fields

Java handles data entry into its fields, but you are responsible for writing that information to and from the application's variables. JavaTax does this on a dialog-by-dialog basis. Each one has a saveData() function that takes the strings in its text fields, converts them to integers, and stores them in the data object. updateEdits() does the reverse. Example 3 shows

how these two methods are implemented.

Calling the Functions

I call myTaxData.calculate() and updateEdits() in the dialog's constructor after the components are created and before the window is shown. This ensures all data is displayed correctly.

The dialogs must save their data when the user navigates from one page to another. JFactory already generated the action method that processes the Prev and Next buttons; I just add a call to saveData() to that method.

So far, JavaTax displays each dialog correctly and saves the data when the user is done. However, I also want it to update the calculated fields as the user enters data. I accomplish this by trapping the Enter key.

JFactory generates a handleEvent() function for each window, and I extend it to check for key presses. If the user presses the Enter key while in a text field, I save the data, calculate and update the subtotals in the dialog, and place focus in the next component. Example 4 shows the necessary changes.

The reference to ((Component)(e.target)).nextFocus(); in Example 4 works because JFactory allows you to rearrange the component's creation order. (It's called "tab order," although the JDK 1.03 for Win32 doesn't support tabbing.) By ordering the text fields consecutively, I ensure that nextFocus() puts focus into the next text field and not, for example, in a button.

Debugging

After writing user code with Cafe's source editor and the class browser, I can compile and execute the applet from within the Cafe environment.

And it doesn't work.

Cafe's graphical debugger is extremely useful. The 1.20 version doesn't even require TCP/IP. After setting breakpoints, I can step "over" methods, stopping on the next executed line, or step "into" them, which takes me line by line into the method's source code. Cafe also has a data/object window that displays the contents of class members and variables.

The debugger has a few other features I haven't used, but they'd probably be helpful in other situations. The first is a Thread View window that allows you to freeze and thaw individual threads while others continue to run. The second is a remote debugger for working with applets running on another machine. This could help find pesky problems that don't manifest themselves in a stand-alone environment.

Conclusion

After a few rounds of debugging, JavaTax is up and running. As with many software tasks, the program logic is relatively simple, yet the applet required over 3500 lines of code. Writing it from scratch would be tough, but using the right combination of tools makes it a manageable task.

Cafe and JFactory are both remarkably robust for 1.x releases, but they have their share of bugs. However, my primary reservations about the Java language spring not from the available tools but from performance problems in the run-time environment. JavaTax runs fine in the applet viewer, but it brings Netscape 3.0b4 to its knees. Nonetheless, I'm confident that these issues will resolve themselves and that Java will soon mature into formidable presence in the commercial development arena.

Figure 2: JFactory's Project Manager.

Figure 1: JFactory and Cafe in a combined workspace.

Figure 3: JFactory's Object Manager.

Figure 4: The JavaTax applet.

Figure 5: Cafe's Hierarchy Editor.

Example 1: Main applet class generated by JFactory.




public
class taxapp extends Applet {
    private static Applet applet;
    // Initial size in logical units
    Dimension initialSize = new Dimension(158, 64);
    // zpb_begin MainUserVars
    // zpb_end
    public
    void init() {
        applet = this;
        // zpb_begin AppletInit
        // zpb_end
        setBackground(Color.lightGray);
        setFont(new Font("Helvetica", Font.PLAIN, 12));
        LogFontLayout lfLayout = new LogFontLayout(this);
        setLayout(lfLayout);
 . . .
    // zpb_begin MainAppletUserMethods
    // zpb_end
}
// zpb_begin UserClasses
// zpb_end






Example 2: Instantiating a taxData object.




public
void init() {
    applet = this;
    // zpb_begin AppletInit
    pTaxData = new taxData();
    // zpb_end






Example 3: Methods added to a typical dialog.


// zpb_begin Inc2DialogUserMethods
void saveData(){
    myTaxData.rental = 
(Integer.valueOf(pRentalEdit.getText())).intValue();
    myTaxData.farm = 
(Integer.valueOf(pFarmEdit.getText())).intValue();
    myTaxData.unemployment = 
(Integer.valueOf(pUnemploymentEdit.getText())).intValue();
    myTaxData.SSBenefits = 
(Integer.valueOf(pSocialSecurityEdit.getText())).intValue();
    myTaxData.otherIncome = 
(Integer.valueOf(pOtherIncomeEdit.getText())).intValue();
}
void updateEdits(){
    pRentalEdit.setText(String.valueOf(myTaxData.rental));
    pFarmEdit.setText(String.valueOf(myTaxData.farm));
    pUnemploymentEdit.setText(String.valueOf(myTaxData.unemployment));
    pSocialSecurityEdit.setText(String.valueOf(myTaxData.SSBenefits));
    pOtherIncomeEdit.setText(String.valueOf(myTaxData.otherIncome));
    pTotalIncomeEdit.setText(String.valueOf(myTaxData.totalIncome));
}
// zpb_end



Example 4: Checking for the Enter key.




public boolean handleEvent(Event e) {
 ...
  // zpb_begin Inc2DialogHandleEvent
  if (e.target instanceof TextField
     && e.id == Event.KEY_PRESS
     && e.key == 10){
     saveData();
     myTaxData.calculate();
     pTotalIncomeEdit.setText
         (String.valueOf(myTaxData.totalIncome));
     ((Component)(e.target)).nextFocus();
  }
  // zpb_end
...

For More Information

Symantec Corp.

10201 Torre Avenue

Cupertino, CA 95014-2132

408-253-9600

http://www.symantec.com

Rogue Wave Software

260 SW Madison Avenue

Corvallis, OR 97333

800-487-3217

http://www.roguewave.com

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.