11.4 Use Case: Creating User Interface Scripts with Java and JFC/Swing

Use JavaScript to create sophisticated Java user interfaces in JFC/Swing. There is a caveat: declarations are always untyped, so do not declare variables. For example:

  • Do not do this:

    Packages.javax.swing.JButton button = new Packages.javax.swing.JButton( "OK" )
    
  • Instead, do this:

    var button = new Packages.javax.swing.JButton( "OK" )
    

    Listeners added to GUI components use a slightly different syntax.

There are no GUI designers for JFC/Swing as embedded within JavaScript. However, some GUI designers, such as NetBeans*, work well with JavaScript.

In fact, JavaScript is so adept at creating JFC/Swing user interfaces that Operations Center creates many user interfaces in JavaScript, because it allows dynamically generated code for management-system-specific tasks.

To minimize confusion, Operations Center has attempted to make its JavaScript appear unlike Java, using single-quote (') strings, and no semicolons in JavaScript statements. However, there is nothing wrong with making your code look exactly like Java. For example:

new java.awt.Frame( "A Frame Window" );

This code compiles in Java and works in JavaScript, with no modifications.

11.4.1 Syntax for Bean-Listener Patterns

Those familiar with JFC/Swing have probably seen or used inner-class declarations for setting up a listener to a component. JavaScript supports a similar declarative syntax for creating listeners to JFC/Swing and AWT components.

An example in Java:

final frame = new java.awt.Frame( "A Frame Window" );
frame.addWindowListener
(
   new java.awt.event.WindowAdapter()
   {
      public void windowClosing( java.awt.event.WindowEvent evt )
      {
         frame.setVisible( false );
      }
   }
);

The same example in JavaScript:

var frame = new java.awt.Frame( "A Frame Window" );
frame.addWindowListener
(
   new java.awt.event.WindowAdapter()
   {
      windowClosing: function( evt )
      {
         frame.setVisible( false );
      }
   }
)

Note the similarity with Java: there is still a declaration of an inner class, derived from java.awt.event.WindowAdapter(). However, the declaration uses inline notation of a property of the JavaScript object, namely the windowClosing property, which is itself a function taking one argument.

You can manufacture similar listeners for any JFC/Swing or AWT component that allows for listener registration. However, options are not limited to these interfaces. It is possible to create inner class declarations for almost anything that can be done in Java.

11.4.2 Utilizing NetBeans

NetBeans is an open source project found at http://www.netbeans.org, where it can be freely downloaded.

An attractive feature of NetBeans is creating user interfaces with the GUI design tool. Copy or paste these interfaces into a JavaScript script with little or no modifications. As long as the interactivity portion of the user interface design is left out of the NetBeans form, it is possible to create user interfaces for use in NOC Script.

As an example:

  1. Consider the following form declaration, taken directly from a user interface create in NetBeans. This user interface is the Change Password dialog in Operations Center:

    /*
     * ChangePasswordDialog.java
     *
     * Created on September 6, 2000, 12:01 PM
     */
    
    package proto;
    
    /**
     *
     * @author  kwester
     * @version 
     */
    public class ChangePasswordDialog extends javax.swing.JDialog {
    
        /** Creates new form ChangePasswordDialog */
        public ChangePasswordDialog(java.awt.Frame parent,boolean modal) {
            super (parent, modal);
            initComponents ();
            pack ();
        }
    
        /** This method is called from within the constructor to
         * initialize the form.
         * WARNING: Do NOT modify this code. The content of this method is
    
    
         * always regenerated by the FormEditor.
         */
       private void initComponents()//GEN-BEGIN:initComponents
       {
          java.awt.GridBagConstraints gridBagConstraints;
    
          clientPanel = new javax.swing.JPanel();
          buttonPanel = new javax.swing.JPanel();
          OKButton = new javax.swing.JButton();
          CancelButton = new javax.swing.JButton();
          specifyLabel = new javax.swing.JLabel();
          oldPasswordLabel = new javax.swing.JLabel();
          oldPasswordField = new javax.swing.JPasswordField();
          newPasswordLabel = new javax.swing.JLabel();
          newPasswordField = new javax.swing.JPasswordField();
          newPasswordAgainLabel = new javax.swing.JLabel();
          newPasswordAgainField = new javax.swing.JPasswordField();
    
          clientPanel.setLayout(new java.awt.GridBagLayout());
    
          buttonPanel.setLayout(new java.awt.GridLayout(1, 2, 4, 4));
    
          OKButton.setText("OK");
          buttonPanel.add(OKButton);
    
          CancelButton.setText("Cancel");
          buttonPanel.add(CancelButton);
    
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 7;
          gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
          gridBagConstraints.ipadx = 30;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
          gridBagConstraints.weightx = 1.0;
          gridBagConstraints.insets = new java.awt.Insets(24, 0, 8, 8);
          clientPanel.add(buttonPanel, gridBagConstraints);
    
          specifyLabel.setText("Enter new password:");
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 0;
          gridBagConstraints.gridwidth = 4;
          gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
          gridBagConstraints.insets = new java.awt.Insets(8, 8, 24, 8);
          clientPanel.add(specifyLabel, gridBagConstraints);
    
          oldPasswordLabel.setText("Old password:");
          oldPasswordLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 1;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
          gridBagConstraints.insets = new java.awt.Insets(4, 24, 0, 8);
          clientPanel.add(oldPasswordLabel, gridBagConstraints);
    
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 1;
          gridBagConstraints.gridy = 1;
          gridBagConstraints.gridwidth = 2;
          gridBagConstraints.gridheight = 2;
          gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
          gridBagConstraints.ipadx = 80;
          gridBagConstraints.ipady = 4;
    
          gridBagConstraints.weightx = 1.0;      gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 24);
          clientPanel.add(oldPasswordField, gridBagConstraints);
    
          newPasswordLabel.setText("New password:");
          newPasswordLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 3;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
          gridBagConstraints.insets = new java.awt.Insets(4, 24, 0, 8);
          clientPanel.add(newPasswordLabel, gridBagConstraints);
    
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 1;
          gridBagConstraints.gridy = 3;
          gridBagConstraints.gridwidth = 2;
          gridBagConstraints.gridheight = 2;
          gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
          gridBagConstraints.ipadx = 80;
          gridBagConstraints.ipady = 4;
          gridBagConstraints.weightx = 1.0;
          gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 24);
          clientPanel.add(newPasswordField, gridBagConstraints);
    
          newPasswordAgainLabel.setText("New password (again):");
          newPasswordAgainLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 5;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
          gridBagConstraints.insets = new java.awt.Insets(4, 24, 0, 8);
          clientPanel.add(newPasswordAgainLabel, gridBagConstraints);
    
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 1;
          gridBagConstraints.gridy = 5;
          gridBagConstraints.gridwidth = 2;
          gridBagConstraints.gridheight = 2;
          gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
          gridBagConstraints.ipadx = 80;
          gridBagConstraints.ipady = 4;
          gridBagConstraints.weightx = 1.0;
          gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 24);
          clientPanel.add(newPasswordAgainField, gridBagConstraints);
    
          getContentPane().add(clientPanel, java.awt.BorderLayout.CENTER);
    
       }//GEN-END:initComponents
    
        /** Closes the dialog */
        /**
        * @param args the command line arguments
        */
        public static void main (String args[]) {
            new ChangePasswordDialog (new javax.swing.JFrame (), true).show ();
        }
    
    
       // Variables declaration - do not modify//GEN-BEGIN:variables
       private javax.swing.JPanel buttonPanel;
       private javax.swing.JButton OKButton;
       private javax.swing.JLabel newPasswordLabel;
       private javax.swing.JLabel specifyLabel;
       private javax.swing.JPasswordField newPasswordField;
       private javax.swing.JLabel newPasswordAgainLabel;
       private javax.swing.JButton CancelButton;
       private javax.swing.JPasswordField newPasswordAgainField;
       private javax.swing.JPanel clientPanel;
       private javax.swing.JLabel oldPasswordLabel;
       private javax.swing.JPasswordField oldPasswordField;
       // End of variables declaration//GEN-END:variables
    
    }
    
  2. Copy or paste the section of code highlighted in bold into a NOC Script script with only no modifications. This enables taking a script, which results in assembling the clientPanel variable in the script, and adding it to the content pane of a JDialog:

    // Create an owner frame.
    frame = new javax.swing.JFrame( 'Hidden' )
    
    // Create a dialog that holds the clientPanel.
    dialog = new javax.swing.JDialog( frame, 'Change Password', true )
    dialog.getContentPane().add( clientPanel )
    dialog.pack()
    formula.util.center( dialog )
    
  3. Place the following line at the top of the script, to declare the javax variable:

    javax = Packages.javax
    
  4. After creating the dialog, create a few listeners to components of the dialog, to ensure interaction with the user:

    // Add a window listener to automatically close.
    dialog.addWindowListener
    (
       new java.awt.event.WindowAdapter()
      {
        windowClosing: function( evt )
        {
          dialog.setVisible( false )
        }
      }
    )
    
    // Add an OK listener.
    OKButton.addActionListener
    (
       new java.awt.event.ActionListener()
      {
        actionPerformed: function( evt )
        {
          info( 'You pressed OK' )
        }
      }
    )
    
    // Add a Cancel listener.
    CancelButton.addActionListener
    (
       new java.awt.event.ActionListener()
      {
        actionPerformed: function( evt )
        {
          alert( 'You pressed Cancel' )
        }
      }
    )
    
  5. The resulting script:

    // Forward declaration of "javax", since it isn't a predefined package name for JS
    javax = Packages.javax
    
    // BEGIN PASTE FROM NETBEANS
    
          clientPanel = new javax.swing.JPanel();
          buttonPanel = new javax.swing.JPanel();
          OKButton = new javax.swing.JButton();
          CancelButton = new javax.swing.JButton();
          specifyLabel = new javax.swing.JLabel();
          oldPasswordLabel = new javax.swing.JLabel();
          oldPasswordField = new javax.swing.JPasswordField();
          newPasswordLabel = new javax.swing.JLabel();
          newPasswordField = new javax.swing.JPasswordField();
          newPasswordAgainLabel = new javax.swing.JLabel();
          newPasswordAgainField = new javax.swing.JPasswordField();
    
          clientPanel.setLayout(new java.awt.GridBagLayout());
    
          buttonPanel.setLayout(new java.awt.GridLayout(1, 2, 4, 4));
    
          OKButton.setText("OK");
          buttonPanel.add(OKButton);
    
          CancelButton.setText("Cancel");
          buttonPanel.add(CancelButton);
    
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 7;
          gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
          gridBagConstraints.ipadx = 30;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
          gridBagConstraints.weightx = 1.0;
          gridBagConstraints.insets = new java.awt.Insets(24, 0, 8, 8);
          clientPanel.add(buttonPanel, gridBagConstraints);
    
          specifyLabel.setText("Enter new password:");
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 0;
          gridBagConstraints.gridwidth = 4;
          gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
          gridBagConstraints.insets = new java.awt.Insets(8, 8, 24, 8);
          clientPanel.add(specifyLabel, gridBagConstraints);
    
          oldPasswordLabel.setText("Old password:");
         
    oldPasswordLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 1;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
          gridBagConstraints.insets = new java.awt.Insets(4, 24, 0, 8);
          clientPanel.add(oldPasswordLabel, gridBagConstraints);
    
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 1;
          gridBagConstraints.gridy = 1;
          gridBagConstraints.gridwidth = 2;
          gridBagConstraints.gridheight = 2;
          gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
          gridBagConstraints.ipadx = 80;
          gridBagConstraints.ipady = 4;
          gridBagConstraints.weightx = 1.0;
          gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 24);
          clientPanel.add(oldPasswordField, gridBagConstraints);
    
          newPasswordLabel.setText("New password:");
          newPasswordLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 3;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
          gridBagConstraints.insets = new java.awt.Insets(4, 24, 0, 8);
          clientPanel.add(newPasswordLabel, gridBagConstraints);
    
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 1;
          gridBagConstraints.gridy = 3;
          gridBagConstraints.gridwidth = 2;
          gridBagConstraints.gridheight = 2;
          gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
          gridBagConstraints.ipadx = 80;
          gridBagConstraints.ipady = 4;
          gridBagConstraints.weightx = 1.0;
          gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 24);
          clientPanel.add(newPasswordField, gridBagConstraints);
    
          newPasswordAgainLabel.setText("New password (again):");
         
    newPasswordAgainLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 0;
          gridBagConstraints.gridy = 5;
          gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
          gridBagConstraints.insets = new java.awt.Insets(4, 24, 0, 8);
          clientPanel.add(newPasswordAgainLabel, gridBagConstraints);
    
          gridBagConstraints = new java.awt.GridBagConstraints();
          gridBagConstraints.gridx = 1;
          gridBagConstraints.gridy = 5;
          gridBagConstraints.gridwidth = 2;
          gridBagConstraints.gridheight = 2;
          gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
          gridBagConstraints.ipadx = 80;
          gridBagConstraints.ipady = 4;
          gridBagConstraints.weightx = 1.0;
          gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 24);
          clientPanel.add(newPasswordAgainField, gridBagConstraints);
    
    // END PASTE FROM NETBEANS
    
    // Create an owner frame.
    frame = new javax.swing.JFrame( 'Hidden' )
    
    // Create a dialog that holds the clientPanel.
    dialog = new javax.swing.JDialog( frame, 'Change Password', true )
    dialog.getContentPane().add( clientPanel )
    dialog.pack()
    formula.util.center( dialog )
    
    // Add a window listener to automatically close.
    dialog.addWindowListener
    (
       new java.awt.event.WindowAdapter()
      {
        windowClosing: function( evt )
        {
          dialog.setVisible( false )
        }
      }
    )
    
    // Add an OK listener.
    OKButton.addActionListener
    (
       new java.awt.event.ActionListener()
      {
        actionPerformed: function( evt )
        {
          info( 'You pressed OK' )
        }
      }
    )
    
    // Add a Cancel listener.
    CancelButton.addActionListener
    (
       new java.awt.event.ActionListener()
      {
        actionPerformed: function( evt )
        {
          alert( 'You pressed Cancel' )
        }
      }
    )
    
    // Show the dialog
    dialog.setVisible( true )