Appendix G.
Example Programs

  This appendix contains a few complete example programs that illustrate some of the more complex features in Perspective for Java:
  n Event Handling (See ListenAndRotate and FullMetalListen)
  n Tool Tips (See ToolTipDemoOne)

ListenAndRotate
  This example program primarily illustrates the use of the following methods:
  n addPerspectiveListener()
  n perspectiveEvent()
  The addPerspectiveListener() and perspectiveEvent() methods are described in Chapter 8. Also see Chapter 3 for an overview of how events Perspective events are collected and reported to the listener interface.

/*
 *
 * ListenAndRotate.java    03Apr98/jst
 *
 * Copyright (c) 1998 Three D Graphics, Inc. All Rights Reserved.
 *
 * Three D Graphics, Inc.
 * 11340 West Olympic Blvd.
 * Suite 300
 * Los Angeles, CA  90064
 * (310) 553-3313
 *
 * This software is the confidential and proprietary information of
 * Three D Graphics, Inc. ("Confidential Information").  You shall
 * not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered
 * into with Three D Graphics.
 *
 * THREE D GRAPHICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  THREE D
 * GRAPHICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 * ITS DERIVATIVES
 *
 *
 * @author      Joe Terry
 * @version     %I%, %G%
 * @since       JDK1.1
 */
import java.awt.*;
import java.applet.*;
import TDG.Perspective;
import TDG.event.TDGEvent;
public class ListenAndRotate extends Applet
{
    public static final int ACTION_NONE = 0;
    public static final int ACTION_DRAG = 1;
    public int j_Action;
    public Point startPoint, endPoint;
    public void init()
    {
        //{{INIT_CONTROLS
        setLayout(new BorderLayout(0,0));
        setSize(640,480);
        setBackground(new Color(16777215));
        //}}
        // Creation of a Chart
        perspective1 = new TDG.Perspective(this);
        
        // Add the Chart to the Applet
        add(perspective1);
        perspective1.setGraphType(0);  /* set graph type */
        perspective1.setTitleString("Rotate Me Now!");  /* set title string */
        // iff, I'm going to be controlling mouse clicks on the chart then
        // I have to disable the default mouse handling, or else
        // we get unsightly conflicts
        perspective1.setSelectionEnable(0);
        
        // Create an instance of a Class to catch mouse events on the
        // Chart
        SymMouse aSymMouse = new SymMouse();
        perspective1.addMouseListener(aSymMouse);
        perspective1.addMouseMotionListener(aSymMouse);
        
        // Create an instance of a Class to catch High Level Events defined
        // by Three D Graphics for Perspective for Java integration
        SymTDG lSymTDG = new SymTDG();
        perspective1.addPerspectiveListener(lSymTDG);
    }
    java.awt.Panel panel1;
    TDG.Perspective perspective1;
    class SymMouse
        extends java.awt.event.MouseAdapter
        implements java.awt.event.MouseMotionListener
    {
        public void mouseMoved(java.awt.event.MouseEvent event) {
        }
        public void mousePressed(java.awt.event.MouseEvent event) {
        Object object = event.getSource();
        if (object == perspective1)
        perspective1_mousePressed(event);
        }
        public void mouseDragged(java.awt.event.MouseEvent event) {
        Object object = event.getSource();
        if (object == perspective1)
        perspective1_mouseDragged(event);
        }
        public void mouseReleased(java.awt.event.MouseEvent event) {
            Object object = event.getSource();
            if (object == perspective1)
                perspective1_mouseReleased(event);
        }
    }
    void perspective1_mousePressed(java.awt.event.MouseEvent event) {
        j_Action = ACTION_NONE;
        System.out.println("Mouse Event -> " + event);
        startPoint = new Point(event.getX(), event.getY());
    }
    void perspective1_mouseDragged(java.awt.event.MouseEvent event) {
        j_Action = ACTION_DRAG;
        System.out.println("Mouse Event -> " + event);
        Point intermediatePoints = new Point(event.getX(), event.getY());
    }
    void perspective1_mouseReleased(java.awt.event.MouseEvent event) {
        System.out.println("Mouse Event -> " + event);
        endPoint = new Point(event.getX(), event.getY());
        if ( j_Action == ACTION_DRAG ) {
            System.out.println("Drag Happened!");
        rotateChart(startPoint, endPoint);
        }
        else
        System.out.println("No Drag Happened!");
    }
    class SymTDG
        implements TDG.event.TDGListener
    {
        public void perspectiveEvent(TDG.event.TDGEvent event) {
            Object object = event.getSource();
            if (object == perspective1)
                perspective1_perspectiveEvent(event);
        }
    }
// There are just a few High Level TDGEvents currently defined and they are as follows:
/*
    **
    * Perspective selection changed.
    *
    public static final int TDG_SELECTION_CHANGED = TDG_FIRST_EVENT_ID + 1;
    **
    * Apply color change to current selection, if any.
    *
    public static final int TDG_APPLY_COLOR = TDG_FIRST_EVENT_ID + 2;
    **
    * Notify Listeners that Preset has changed.
    *
    public static final int TDG_3DPRESET_CHANGED = TDG_FIRST_EVENT_ID + 3;
   **
     * Notify Listeners that GraphType has changed.
     *
    public static final int TDG_GRAPHTYPE_CHANGED = TDG_FIRST_EVENT_ID + 4;
   **
     * Notify Listeners that CALC has been performed.
     *
    public static final int TDG_CALC_PERFORMED = TDG_FIRST_EVENT_ID + 5;
   **
     * Notify Listeners that Editing State has been toggled.
     *
    public static final int TDG_EDITOR_STATE_TOGGLE = TDG_FIRST_EVENT_ID + 6;
*/
    void perspective1_perspectiveEvent(TDG.event.TDGEvent event) {
        System.out.println("TDGEvent ID " + event.getID() + " is " + event);
        switch( event.getID() ) {
            case TDGEvent.TDG_CALC_PERFORMED:
                System.out.println("Calc Performed!");
            break;
            default:
                // Do nothing... that's okay sometimes.
        }
    }
    void rotateChart(Point startPoint, Point endPoint) {
        int OpCode;
        int DEGREES; // degrees of rotation
        int MaximumDiff = 100;
        int RotationSensitivityBasis = 90;
         // We know there was a drag
        //
        // So we now compute a rotation .... 
        int Xdiff = Math.abs( startPoint.x - endPoint.x );
        int Ydiff = Math.abs( startPoint.y - endPoint.y );
        if ( Xdiff > MaximumDiff )
            Xdiff = MaximumDiff;
        if ( Ydiff > MaximumDiff )
            Ydiff = MaximumDiff;
        if ( Xdiff > Ydiff ) {
            DEGREES = RotationSensitivityBasis * Xdiff / 100;
            if ( startPoint.x > endPoint.x )
                OpCode = 3;
            else
                OpCode = 4;
        } else {
            DEGREES = RotationSensitivityBasis * Ydiff / 100;
            if ( startPoint.y > endPoint.y )
                OpCode = 1;
            else
                OpCode = 2;
        }
        switch( OpCode )
        {
            // Rotation - note these are the only ops that use "relative" methods
            // (modifying the existing rotation matrix, instead of just numeric params).
            //
            case 1:        // X axis Up
                perspective1.rotateCubeX(-DEGREES);
                break;
            case 2:        // X axis Down
                perspective1.rotateCubeX(DEGREES);
                break;
            case 3:        // Y axis Left
                perspective1.rotateCubeY(-DEGREES);
                break;
            case 4:        // Y axis Right
                perspective1.rotateCubeY(DEGREES);
                break;
            case 5:        // Z axis Clockwise
                perspective1.rotateCubeZ(-DEGREES);
                break;
            case 6:        // Z axis Counter-Clockwise
                perspective1.rotateCubeZ(DEGREES);
                break;
        }
        perspective1.updateParamsFromMatrix();
        perspective1.needRecalc();
        
    }
    //{{DECLARE_CONTROLS
    //}}
}

FullMetalListen
  This example program illustrates the use of the following methods:
  n addPerspectiveListener()
  n perspectiveEvent()
  The addPerspectiveListener() and perspectiveEvent() methods are described in Chapter 8. Also see Chapter 3 for an overview of how events Perspective events are collected and reported to the listener interface.

/*
 *
 * FullMetalListen.java    04May98/jst
 *
 * Copyright (c) 1998 Three D Graphics, Inc. All Rights Reserved.
 *
 * Three D Graphics, Inc.
 * 11340 West Olympic Blvd.
 * Suite 300
 * Los Angeles, CA  90064
 * (310) 553-3313
 *
 * This software is the confidential and proprietary information of
 * Three D Graphics, Inc. ("Confidential Information").  You shall
 * not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered
 * into with Three D Graphics.
 *
 * THREE D GRAPHICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  THREE D
 * GRAPHICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 * ITS DERIVATIVES
 *
 *
 * @author      Joe Terry
 * @version     %I%, %G%
 * @since       JDK1.1
 */
import java.awt.*;
import java.applet.*;
import tdg.Perspective;
import tdg.event.TDGEvent;
import tdg.TDGMouseState;
public class FullMetalListen
    extends Applet
    implements tdg.event.TDGListener, java.awt.event.ItemListener
{
    public Point startPoint, endPoint;
    
    public void init()
    {
        //{{INIT_CONTROLS
        setLayout(new FlowLayout(FlowLayout.RIGHT));
        setSize(600,550);
        setBackground(java.awt.Color.white);
        //}}
        aChoice = new Choice();
        aChoice.add("3D Bar Chart");
        aChoice.add("3D Surface Chart");
        aChoice.add("2D Bar Chart");
        aChoice.add("Pie Chart");
         add(aChoice);
         aChoice.addItemListener(this);
         
        // Creation of a Chart
        perspective1 = new tdg.Perspective(this);
        perspective1.setSize(500,350);
        perspective1.setTitleString("Rotate Me Now Better!");  /* set title string */
        // iff, I'm going to be controlling mouse clicks on the chart then
        // I have to disable the default mouse handling, or else
        // we get unsightly conflicts or sightly artifacts. You be the judge!
        perspective1.setSelectionEnable(0);
        // Create an instance of a Class to catch High Level Events defined
        // by Three D Graphics for Perspective for Java integration
        perspective1.addPerspectiveListener(this);
        perspective1.setGraphType(0);  /* set graph type */
        // Add the Chart to the Applet
        add(perspective1);
           messageArea = new TextArea("", 10, 90,  TextArea.SCROLLBARS_BOTH);
         add(messageArea);
    }
    java.awt.Panel panel1;
    tdg.Perspective perspective1;
    java.awt.Choice aChoice;
    java.awt.TextArea messageArea;
    
    public void itemStateChanged(java.awt.event.ItemEvent e) {
        
        Object object = e.getSource();
        
        if (object == aChoice) {
            switch( aChoice.getSelectedIndex() ) {
                case 0: // 3D Bar
                    perspective1.setGraphType(0);
                break;
                case 1: // 3D Surface
                    perspective1.setGraphType(12);
                break;
                case 2: // 2D Side by Side Bar
                    perspective1.setGraphType(17);
                break;
                case 3: // Pie
                    perspective1.setGraphType(55);
                break;
            }
        }
        
    }
    
    public void perspectiveEvent(tdg.event.TDGEvent event) {
    
        Object object = event.getSource();
        
        if (object == perspective1)
            perspective1_perspectiveEvent(event);
    }
    
// There are just a few High Level TDGEvents currently defined and they are as follows:
    
/*
   **
     * Perspective selection changed.
     *
    public static final int TDG_SELECTION_CHANGED = TDG_FIRST_EVENT_ID + 1;
 
   **
     * Apply color change to current selection, if any.
     *
    public static final int TDG_APPLY_COLOR = TDG_FIRST_EVENT_ID + 2;
   **
     * Notify Listeners that Preset has changed.
     *
    public static final int TDG_3DPRESET_CHANGED = TDG_FIRST_EVENT_ID + 3;
   **
     * Notify Listeners that GraphType has changed.
     *
    public static final int TDG_GRAPHTYPE_CHANGED = TDG_FIRST_EVENT_ID + 4;
   **
     * Notify Listeners that CALC has been performed.
     *
    public static final int TDG_CALC_PERFORMED = TDG_FIRST_EVENT_ID + 5;
   **
     * Notify Listeners that Editing State has been toggled.
     *
    public static final int TDG_EDITOR_STATE_TOGGLE = TDG_FIRST_EVENT_ID + 6;
   **
     * Notify Listeners that Mouse Pressed.
     *
    public static final int TDG_MOUSE_PRESSED = TDG_FIRST_EVENT_ID + 7;
   **
     * Notify Listeners that Mouse Dragged.
     *
    public static final int TDG_MOUSE_DRAGGED = TDG_FIRST_EVENT_ID + 8;
   **
     * Notify Listeners that Mouse Released.
     *
    public static final int TDG_MOUSE_RELEASED = TDG_FIRST_EVENT_ID + 9;
*/
    void perspective1_perspectiveEvent(tdg.event.TDGEvent event) {
        
        TDGMouseState Harry = null;
        
        switch( event.getID() ) {
        
            case TDGEvent.TDG_MOUSE_PRESSED:
            
                Harry = (TDGMouseState)event.getDataObject();
                
                startPoint = new Point(Harry.getMouseX(), Harry.getMouseY());
            break;
            case TDGEvent.TDG_MOUSE_DRAGGED:
            // This event occurs during the drag each time the mouse changes location.
            // This would be used in the case of providing selection feedback to the user or 
            // other operations prior to the completion of the drag.
            break;
            case TDGEvent.TDG_MOUSE_RELEASED:
            
                Harry = (TDGMouseState)event.getDataObject();
                
                endPoint = new Point(Harry.getMouseX(), Harry.getMouseY());
                
                if ( Harry.isDrag() && perspective1.getJGraphType().is3DType() ) {
                    
                    String tempString = new String("");
                    
                    tempString = messageArea.getText();
                    if ( tempString.length() > 10000 ) {
                        messageArea.setText("");
                        tempString = "";
                    }
                    if ( tempString.length() > 0 )
                        tempString = "\n";
                    else
                        tempString = "";
                    tempString += "Drag Happened.";
                       messageArea.append(tempString);
                    tempString = "\n";
                    tempString += "====================================================";
                       messageArea.append(tempString);
                    rotateChart(startPoint, endPoint);
                }
                else {
                    
                    String tempString;
                    String newMessage;
                    
                    tempString = messageArea.getText();
                    if ( tempString.length() > 10000 ) {
                        messageArea.setText("");
                        tempString = "";
                    }
                        
                    if ( Harry.isShiftKey() )
                        newMessage = "Shift Key is Down.";
                    else
                        newMessage = "Shift Key is Up.";
                    
                    if ( tempString.length() > 0 )
                        tempString = "\n";
                    else
                        tempString = "";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    if ( Harry.isControlKey() )
                        newMessage = "Control Key is Down.";
                    else
                        newMessage = "Control Key is Up.";
                    
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    newMessage = "Element Object ID is (" + Harry.getElementObjectID() + ")";
                       
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    newMessage = "Element Instance ID is (" + Harry.getElementInstanceID() + ")";
                       
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    newMessage = "Element Series ID is (" + Harry.getElementSeriesID() + ")";
                       
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    newMessage = "Element Group ID is (" + Harry.getElementGroupID() + ")";
                       
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    newMessage = "Element Name is (" + Harry.getElementName() + ")";
                       
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    newMessage = "Element Description is (" + Harry.getElementDesc() + ")";
                       
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    newMessage = "Element Text for Text Items is (" + Harry.getElementText() + ")";
                       
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                    newMessage = "====================================================";
                       
                    tempString = "\n";
                    tempString += newMessage;
                       messageArea.append(tempString);
                }
            break;
            default:
                // Do nothing... that's okay sometimes.
        }
    }
    void rotateChart(Point startPoint, Point endPoint) {
        
        int OpCode;
        int DEGREES; // degrees of rotation
        int MaximumDiff = 100;
        int RotationSensitivityBasis = 90;
        
        // We know there was a drag
        //
        // So we now compute a rotation .... 
        int Xdiff = Math.abs( startPoint.x - endPoint.x );
        int Ydiff = Math.abs( startPoint.y - endPoint.y );
        
        if ( Xdiff > MaximumDiff )
            Xdiff = MaximumDiff;
            
        if ( Ydiff > MaximumDiff )
            Ydiff = MaximumDiff;
        
        if ( Xdiff > Ydiff ) {
            DEGREES = RotationSensitivityBasis * Xdiff / 100;
            
            if ( startPoint.x > endPoint.x )
                OpCode = 3;
            else
                OpCode = 4;
        } else {
            DEGREES = RotationSensitivityBasis * Ydiff / 100;
            
            if ( startPoint.y > endPoint.y )
                OpCode = 1;
            else
                OpCode = 2;
        }
        switch( OpCode )
        {
            // Rotation - note these are the only ops that use "relative" methods
            // (modifying the existing rotation matrix, instead of just numeric params).
            //
            case 1:        // X axis Up
                perspective1.rotateCubeX(-DEGREES);
                break;
            case 2:        // X axis Down
                perspective1.rotateCubeX(DEGREES);
                break;
            case 3:        // Y axis Left
                perspective1.rotateCubeY(-DEGREES);
                break;
            case 4:        // Y axis Right
                perspective1.rotateCubeY(DEGREES);
                break;
            case 5:        // Z axis Clockwise
                perspective1.rotateCubeZ(-DEGREES);
                break;
            case 6:        // Z axis Counter-Clockwise
                perspective1.rotateCubeZ(DEGREES);
                break;
        }
        perspective1.updateParamsFromMatrix();
        perspective1.needRecalc();
        
    }
    //{{DECLARE_CONTROLS
    //}}
}

ToolTipDemoOne
  This example program illustrates the use of the following methods:
  n setDeveloperToolTip()
  n setUserToolTip()
  These methods are described in Chapter 8.

/*
 *
 * ToolTipDemoOne.java    06May98/jst
 *
 * Copyright (c) 1998 Three D Graphics, Inc. All Rights Reserved.
 *
 * Three D Graphics, Inc.
 * 11340 West Olympic Blvd.
 * Suite 300
 * Los Angeles, CA  90064
 * (310) 553-3313
 *
 * This software is the confidential and proprietary information of
 * Three D Graphics, Inc. ("Confidential Information").  You shall
 * not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered
 * into with Three D Graphics.
 *
 * THREE D GRAPHICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  THREE D
 * GRAPHICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 * ITS DERIVATIVES
 *
 *
 * @author      Joe Terry
 * @version     %I%, %G%
 * @since       JDK1.1
 */
import java.awt.*;
import java.applet.*;
import tdg.Perspective;
import tdg.event.TDGEvent;
import tdg.TDGMouseState;
public class ToolTipDemoOne
    extends Applet
    implements java.awt.event.ItemListener, java.awt.event.ActionListener
{
    public Point startPoint, endPoint;
    
    public void init()
    {
        setLayout(new FlowLayout(FlowLayout.RIGHT));
        setSize(600,480);
        setBackground(java.awt.Color.white);
        
         ToolTipModeCheckbox = new Checkbox("Tool Tip Mode (false = user)");
        ToolTipModeCheckbox.setState(false);
         ToolTipModeCheckbox.addItemListener(this);
         add(ToolTipModeCheckbox);
        CustomToolTip = new TextField(50); // 50 columns minimum
         CustomToolTip.addActionListener(this);
        add(CustomToolTip);
         
         SetCustomToolTip = new Button("Set Custom Tool Tip");
         SetCustomToolTip.addActionListener(this);
         add(SetCustomToolTip);
        
        // Creation of a Chart
        perspective1 = new tdg.Perspective(this);
        perspective1.setSize(580,380);
        perspective1.setTitleString("Tell Me More About Myself!");  /* set title string */
        // Disabling selection is slightly more Aesthetically pleasing
        perspective1.setSelectionEnable(0);
        perspective1.setGraphType(0);  /* set graph type */
        perspective1.setToolTipDisplay(true);
        perspective1.setToolTipMode(false);  // User Mode
        // Add the Chart to the Applet
        add(perspective1);
    
        GraphTypeChoice = new Choice();
        GraphTypeChoice.add("3D Bar Chart");
        GraphTypeChoice.add("3D Surface Chart");
        GraphTypeChoice.add("2D Bar Chart");
        GraphTypeChoice.add("Pie Chart");
         add(GraphTypeChoice);
         GraphTypeChoice.addItemListener(this);
   }
    java.awt.Panel panel1;
    tdg.Perspective perspective1;
    java.awt.Choice GraphTypeChoice;
    java.awt.Checkbox ToolTipModeCheckbox;
    java.awt.TextField CustomToolTip;
    java.awt.Button SetCustomToolTip;
    
    public void actionPerformed(java.awt.event.ActionEvent e) {
        
        Object object = e.getSource();
        
        if (object == SetCustomToolTip) {
            if ( ToolTipModeCheckbox.getState() ) {
                perspective1.setDeveloperToolTip(CustomToolTip.getText());
            } else {
                perspective1.setUserToolTip(CustomToolTip.getText());
            }
        }
    }
    public void itemStateChanged(java.awt.event.ItemEvent e) {
        Object object = e.getSource();
        if (object == GraphTypeChoice) {
            switch( GraphTypeChoice.getSelectedIndex() ) {
                case 0: // 3D Bar
                    perspective1.setGraphType(0);
                break;
                case 1: // 3D Surface
                    perspective1.setGraphType(12);
                break;
                case 2: // 2D Side by Side Bar
                    perspective1.setGraphType(17);
                break;
                case 3: // Pie
                    perspective1.setGraphType(55);
                break;
            }
        }
        if (object == ToolTipModeCheckbox) {
            perspective1.setToolTipMode(ToolTipModeCheckbox.getState());
        }
    }
}