We add the applet to the frame on left hand side with the following way:
<applet name="Control" code="CylinderExam.class"
mayscript
width="150" height="200">
</applet>
Let's look at the CylinderExam.java file. First we need to include some Java AWT classes to prepare the user interface.
//** Necessary JAVA Classes import java.awt.*; import java.applet.*; import java.util.*;You need to import the following classes into your java file to use External Authoring Interface (EAI).
//** Apperantly we need External Authoring Interface classes import vrml.external.Node; import vrml.external.Browser; import vrml.external.field.*; import vrml.external.exception.*;We need LiveConnect technology to get the handle of the Browser object. With the recent release of EAI we can use Browser.getBrowser() to get the VRML Browser's handle. Then we do not need LiveConnect technology and it will work without any problem on the Internet Explorer(IE) also.
//** We need LiveConnect Support import netscape.javascript.JSObject;We extend the object from Applet as usual. We do not need to say that this object implements EventOutObserver since we did not use the callback mechanism of the EAI for this application.
public class CylinderExam extends Applet {
private boolean DEBUG = false; private Browser browser = null; private Node rootNode = null; private EventInMFNode addChildren = null; private EventInMFNode removeChildren = null; private Label radius, height, bottom; private Label top, side, DragLabel; private TextField radiusTF; private TextField heightTF; private Choice bottomC; private Choice topC; private Choice sideC; private float Cheight = 1f; private float Cradius = 1f; private boolean Cbottom = true; private boolean Ctop = true; private boolean Cside = true; private Node myNode[] = null; private Node myTransform[] = null; private boolean Dragging = true; private Choice DragMode ;Let's define the user interface of the applet.
/** * User Interface */ public void init() { radius = new Label("radius"); radiusTF = new TextField(4); height = new Label("height"); heightTF = new TextField(4); bottom = new Label("bottom"); bottomC = new Choice(); bottomC.addItem("true"); bottomC.addItem("false"); top = new Label("top"); topC = new Choice(); topC.addItem("true"); topC.addItem("false"); side = new Label("side"); sideC = new Choice(); sideC.addItem("true"); sideC.addItem("false"); DragLabel = new Label("Dragging"); DragMode = new Choice(); DragMode.addItem("Move"); DragMode.addItem("Rotate"); setLayout(new GridLayout(0,2)); Panel Labels = new Panel(); Labels.setLayout(new GridLayout(7,0)); infoPanel p1 = new infoPanel(InfoWindow,"radius.html",this); p1.add(radius); Labels.add(p1); infoPanel p2 = new infoPanel(InfoWindow,"height.html",this); p2.add(height); Labels.add(p2); infoPanel p3 = new infoPanel(InfoWindow,"bottom.html",this); p3.add(bottom); Labels.add(p3); infoPanel p4 = new infoPanel(InfoWindow,"top.html",this); p4.add(top); Labels.add(p4); infoPanel p5 = new infoPanel(InfoWindow,"side.html",this); p5.add(side); Labels.add(p5); infoPanel p6 = new infoPanel(InfoWindow,"Info.html",this); p6.add(DragLabel); Labels.add(p6); infoPanel p7 = new infoPanel(InfoWindow,"Info.html",this); Labels.add(p7); Panel entries = new Panel(); entries.setLayout(new GridLayout(7,0)); Panel p11 = new Panel(); p11.add(radiusTF); entries.add(p11); Panel p12 = new Panel(); p12.add(heightTF); entries.add(p12); Panel p13 = new Panel(); p13.add(bottomC); entries.add(p13); Panel p14 = new Panel(); p14.add(topC); entries.add(p14); Panel p15 = new Panel(); p15.add(sideC); entries.add(p15); Panel p16 = new Panel(); p16.add(DragMode); entries.add(p16); Button submit = new Button("Submit"); Panel p17 = new Panel(); p17.add(submit); entries.add(p17); add(Labels); add(entries); System.out.println(" End of Init() "); }// end of init()start() method is where we have to get the handle of Browser, events and nodes that we are interested in the scene. If you want Browser notifies this applet for the occurence of the particular event, you need to use the advise() method to make sure that this event also calls the callback() of this applet.
public void start() {The following code part gets the browser object.
// ** Let's first get the handle of VRML 2.0 Browser // ** We need to use LiveConnect Technology here JSObject win = JSObject.getWindow(this); JSObject parent = (JSObject) win.getMember("parent"); JSObject brWin = (JSObject) parent.getMember("browser"); JSObject doc = (JSObject) brWin.getMember("document"); JSObject embeds = (JSObject) doc.getMember("embeds"); // ** Now it is time to get the handle of browser browser = (Browser) embeds.getSlot(0); if(DEBUG==true) System.out.println("after browser handle ");We can get the handle of CYLINDER node with getNode() method.
try { if(DEBUG==true) System.out.println("before rootNode handle "); rootNode = browser.getNode("CYLINDER"); if(DEBUG==true) System.out.println("after rootNode handle "); } catch (InvalidNodeException e) { System.out.println("Invalid Node Exception"); }We can get the handle of the addChildren and removeChildren eventIns.
// Get EventIns of the rootNode addChildren = (EventInMFNode) rootNode.getEventIn("addChildren"); removeChildren = (EventInMFNode) rootNode.getEventIn("removeChildren"); if(DEBUG == true ) System.out.println(" events are registered !! "); String vrmlString = " Group { children [ DEF myCone Transform { children ["+ " Shape { appearance Appearance { material Material {} }"+ " geometry Cylinder { radius "+Cradius+" height "+Cheight+ " bottom "+(Cbottom==true?"TRUE":"FALSE")+ " top "+(Ctop==true?"TRUE":"FALSE")+ " side "+(Cside==true?"TRUE":"FALSE")+" } }] }"+ " DEF Sensor PlaneSensor { } ] "+ " ROUTE Sensor.translation_changed TO myCone.set_translation}";Create the VRML node dynamically and tell the browser to add this.
myNode = browser.createVrmlFromString(vrmlString); addChildren.setValue(myNode); if(DEBUG==true) System.out.println("New Node is added to the scene"); }// end of start()action() is where we need to handle the user action. After user sets the necessary values from the applet's interface, she has to submit these values. Whenever we get the submit event, we create the necessary node(createVrmlFromString()) by using current values and replace(addChildren and removeChildren) this new node with the previous one.
public boolean action(Event event, Object what) { if (event.target instanceof Button) { Button b = (Button) event.target; if (b.getLabel() == "Submit") { String heightStr = heightTF.getText(); String radiusStr = radiusTF.getText(); if(heightStr.length()>0) Cheight = Float.valueOf(heightStr).floatValue(); else Cheight = 1f; if(radiusStr.length()>0) Cradius = Float.valueOf(radiusStr).floatValue(); else Cradius = 1f; Cbottom = (bottomC.getSelectedIndex()==0?true:false); Ctop = (topC.getSelectedIndex()==0?true:false); Cside = (sideC.getSelectedIndex()==0?true:false); Dragging = (DragMode.getSelectedIndex()==0?true:false); if(DEBUG==true) System.out.println(" height is "+Cheight+" radius "+Cradius+" bottom is "+Cbottom+ " top is "+Ctop+" side is "+Cside+" Moving is "+Dragging);Delete the previous node from the scene with removeChildren.
removeChildren.setValue(myNode); String vrmlString = " Group { children [ DEF myCone Transform { children ["+ " Shape { appearance Appearance { material Material {} }"+ " geometry Cylinder { radius "+Cradius+" height "+Cheight+ " bottom "+(Cbottom==true?"TRUE":"FALSE")+ " top "+(Ctop==true?"TRUE":"FALSE")+ " side "+(Cside==true?"TRUE":"FALSE")+" } } ] }"+ (Dragging==true? " DEF Sensor PlaneSensor { } ] ROUTE Sensor.translation_changed TO myCone.set_translation }": " DEF Sensor SphereSensor { } ] ROUTE Sensor.rotation_changed TO myCone.set_rotation } ");Define the new node with createVrmlFromString().
myNode = browser.createVrmlFromString(vrmlString);Add this node to the scene with addChildren().
addChildren.setValue(myNode); if(DEBUG==true) { System.out.println("New Node is added to the scene"); System.out.println(" event is SUBMIT "); }// end of if }// end of if }// end of if return true; }// end of action() }// end of class CylinderExamThis object handles the information for each field in the node. For each field, there is a HTML page and this object shows this page in the lower right hand frame(Info frame) by using showDocument() method of AppletContext object.
/** * */ class infoPanel extends Panel { private String myurl = null; private boolean DEBUG = true; private Applet app = null; infoPanel(JSObject _win, String _url, Applet _app) { myurl = _url; app = _app; }// end of constructor public boolean mouseEnter(Event e, int x, int y) { boolean ret = false; if(DEBUG==true) System.out.println("in mouseEnter() "); if( myurl!=null ) ret = showDoc(); return ret; }// end of mouseEnter() boolean showDoc() { boolean ret = false; URL url = null; try { url = new URL( app.getCodeBase() + myurl ); if(DEBUG==true) System.out.println(" URL OK!"); /** Show the url in the given netscape window */ app.getAppletContext().showDocument( url, "Info"); ret = true; } catch( MalformedURLException e ) { System.out.println(" Can not create URL from string "+myurl); e.printStackTrace(); } return ret; }//end of showDoc() }// end of class infoPanelAll Files