import java.awt.*; import java.awt.event.*; import java.applet.*; import java.util.*; import sieve.phys.lwblockandplane.*; import sieve.sluice.views.*; import sieve.nuggets.LineGraph.*; import sieve.nuggets.*; import sieve.workbench.*; // for the unnecessary BnPPropertyPanel class import java.util.*; import java.beans.*; public class CompositeBnP extends Applet { ScrollPane scroller = null; BnPPropertyPanel pPanel = null; public CompositeBnP() { // generates data from a sim. of sliding a block down an incline plane BlockAndPlane bnp = new BlockAndPlane(); // displays and allows user selection of a data run (table) TableSelectionView tableSelector = new TableSelectionView(true); TableSelectionViewCustomizer tableSelectionCust = new TableSelectionViewCustomizer(); tableSelectionCust.setObject(tableSelector); tableSelectionCust.setBackground(Color.white); // displays and allows user selection of fields in a data run (table) FieldNameSelectionView fieldSelector = new FieldNameSelectionView(); FieldNameSelectionViewCustomizer fieldSelectionCust = new FieldNameSelectionViewCustomizer(); fieldSelectionCust.setObject(fieldSelector); fieldSelectionCust.setBackground(Color.white); // displays the parameters of a data run (table) AttributeViewer attrViewer = new AttributeViewer(); attrViewer.setBackground(Color.white); // graphs the data of a run LineGraph grapher = new LineGraph(); // raw numbers of a run TextTable textTable = new TextTable(); textTable.setBackground(Color.white); // attach the output of one component to the input of the next try { // add bnp as the source for tableSelector tableSelector.addSourceView(bnp); // add tableSelector as a listener to bnp bnp.addTableViewListener(tableSelector); // add tableSelector as the source for attrView and fieldSelector attrViewer.addSourceView(tableSelector); fieldSelector.addSourceView(tableSelector); // add attrView and fieldSelector as listeners to tableSelector tableSelector.addTableViewListener(fieldSelector); tableSelector.addTableViewListener(attrViewer); grapher.addSourceView(fieldSelector); fieldSelector.addTableViewListener(grapher); tableSelector.addTableViewListener(grapher); textTable.addSourceView(fieldSelector); fieldSelector.addTableViewListener(textTable); tableSelector.addTableViewListener(textTable); } catch (sieve.sluice.TooManySourcesException ex) { System.err.println("Error combining components: "+ex); ex.printStackTrace(); } // put them in the applet setLayout(new BorderLayout()); Container p = new BogusContainer(); p.setLayout(new BorderLayout()); Container p3 = new BogusContainer(); p3.setLayout(new BorderLayout()); p3.add("North", new Label("Block and Plane Simulation")); p3.add("Center", bnp); p.add("Center", p3); // next 3 lines avoid NullPointerException in PropertyPanel bnp.setBackground(Color.lightGray); bnp.setForeground(Color.black); bnp.setFont(new Font("SansSerif", Font.PLAIN, 12)); pPanel = new BnPPropertyPanel(bnp); scroller = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS); // scroller.add(pPanel); SizedContainer szCont = new SizedContainer(300, 200); szCont.add("North", new Label("Set Parameters")); szCont.add("Center", scroller); p.add("East", szCont); add("North", p); p = new BogusContainer(); p.setLayout(new GridLayout(1,0)); p3 = new BogusContainer(); p3.setLayout(new BorderLayout()); p3.add("North", new Label("Select a run")); p3.add("Center", tableSelectionCust); p.add(p3); p3 = new BogusContainer(); p3.setLayout(new BorderLayout()); p3.add("North", new Label("Select fields")); p3.add("Center", fieldSelectionCust); p.add(p3); p3 = new BogusContainer(); p3.setLayout(new BorderLayout()); p3.add("North", new Label("Parameters")); p3.add("Center", attrViewer); p.add("East", p3); add("Center", p); p = new BogusContainer(); p.setLayout(new BorderLayout()); p3 = new BogusContainer(); p3.setLayout(new BorderLayout()); p3.add("North", new Label("Graphed Data")); p3.add("Center", grapher); p.add("Center", p3); p3 = new BogusContainer(); p3.setLayout(new BorderLayout()); p3.add("North", new Label("Raw Data")); p3.add("Center", textTable); p.add("East", p3); add("South", p); } public void init() { scroller.add(pPanel); } public void update(Graphics g) { // System.out.println("CompositeBnP.update"); paint(g); } public static void main(String [] args) { Frame frame = new Frame(); frame.setLayout(new BorderLayout()); CompositeBnP cbnp = (CompositeBnP)frame.add("Center", new CompositeBnP()); WindowListener l = new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }; frame.addWindowListener(l); frame.pack(); frame.show(); cbnp.init(); } } class BogusContainer extends Panel { // This class prevents flickering in embedded lightweight components, // like BlockAndPlane's SimCanvas public void update(Graphics g) { paint(g); } } class SizedContainer extends Panel { Dimension mySize = null; SizedContainer(int width, int height) { this(new Dimension(width, height)); } SizedContainer(Dimension size) { mySize = size; setLayout(new BorderLayout()); } public void update(Graphics g) { paint(g); } public Dimension getPreferredSize() { return getMinimumSize(); } public Dimension getMinimumSize() { return mySize; } } /** This class is only required because Netscape security won't let us use java beans introspection. Therefore, I'm building this by hand. Normally, where this class is used, we would use sieve.workbench.PropertyPanel . This class emulates that functionality but does not use introspection. -Bo */ class BnPPropertyPanel extends Panel implements PropertyChangeListener { BlockAndPlane bnp = null; PropertyEditor editor = null; Class floatEditorClass = PropertyEditorManager.findEditor(Float.class).getClass(); Hashtable properties = new Hashtable(); BnPPropertyPanel(BlockAndPlane bnp) { this.bnp = bnp; setLayout(new GridLayout(0, 2)); add(new Label("Simulation Time Step: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getTimeStep())); editor.addPropertyChangeListener(this); properties.put(editor, "TimeStep"); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); add(new Label("Plane 1 Height: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane1Height())); editor.addPropertyChangeListener(this); properties.put(editor, "Plane1Height"); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); String propName = "Plane 1 Length"; add(new Label("Plane1Length: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane1Length())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Plane1Angle"; add(new Label("Plane 1 Angle: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane1Angle())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Plane1MuS"; add(new Label("Plane 1 Static Friction: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane1MuS())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Plane1MuK"; add(new Label("Plane 1 Kinetic Friction: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane1MuK())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Plane2Height"; add(new Label("Plane 2 Height: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane2Height())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Plane2Length"; add(new Label("Plane 2 Length: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane2Length())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Plane2Angle"; add(new Label("Plane 2 Angle: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane2Angle())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Plane2MuS"; add(new Label("Plane 2 Static Friction: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane2MuS())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Plane2MuK"; add(new Label("Plane 2 Kinetic Friction: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getPlane2MuK())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "FloorLength"; add(new Label("Floor Length: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getFloorLength())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "FloorMuS"; add(new Label("Floor Static Friction: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getFloorMuS())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "FloorMuK"; add(new Label("Floor Kinetic Friction: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getFloorMuK())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "MovingBodyHeight"; add(new Label("Block Height: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getMovingBodyHeight())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "MovingBodyLength"; add(new Label("Block Length: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getMovingBodyLength())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); propName = "Gravity"; add(new Label("Gravity: ")); try { editor = (PropertyEditor)floatEditorClass.newInstance(); editor.setValue(new Float(bnp.getGravity())); editor.addPropertyChangeListener(this); properties.put(editor, propName); } catch (Exception ex) { // ignore it } add(new PropertyText(editor)); } public synchronized void propertyChange(PropertyChangeEvent evt) { /* System.out.println("propertyChange: "+evt); System.out.println(" propertyChange: "+evt.getNewValue()); System.out.println(" propertyChange: "+evt.getSource()); System.out.println(" propertyChange: "+evt.getPropertyName()); */ Object source = evt.getSource(); if (source == null) return; Number newValue = (Number)((PropertyEditor)source).getValue(); String propertyName = (String)properties.get(source); if (propertyName == null) return; if ("Plane1Length".equals(propertyName)) { bnp.setPlane1Length(newValue.floatValue()); } else if ("Plane1Height".equals(propertyName)) { bnp.setPlane1Height(newValue.floatValue()); } else if ("TimeStep".equals(propertyName)) { bnp.setTimeStep(newValue.floatValue()); } else if ("Plane1Angle".equals(propertyName)) { bnp.setPlane1Angle(newValue.floatValue()); } else if ("Plane1MuS".equals(propertyName)) { bnp.setPlane1MuS(newValue.floatValue()); } else if ("Plane1MuK".equals(propertyName)) { bnp.setPlane1MuK(newValue.floatValue()); } else if ("Plane2Height".equals(propertyName)) { bnp.setPlane2Height(newValue.floatValue()); } else if ("Plane2Length".equals(propertyName)) { bnp.setPlane2Length(newValue.floatValue()); } else if ("Plane2Angle".equals(propertyName)) { bnp.setPlane2Angle(newValue.floatValue()); } else if ("Plane2MuS".equals(propertyName)) { bnp.setPlane2MuS(newValue.floatValue()); } else if ("Plane2MuK".equals(propertyName)) { bnp.setPlane2MuK(newValue.floatValue()); } else if ("FloorLength".equals(propertyName)) { bnp.setFloorLength(newValue.floatValue()); } else if ("FloorMuS".equals(propertyName)) { bnp.setFloorMuS(newValue.floatValue()); } else if ("FloorMuK".equals(propertyName)) { bnp.setFloorMuK(newValue.floatValue()); } else if ("MovingBodyHeight".equals(propertyName)) { bnp.setMovingBodyHeight(newValue.floatValue()); } else if ("MovingBodyLength".equals(propertyName)) { bnp.setMovingBodyLength(newValue.floatValue()); } else if ("Gravity".equals(propertyName)) { bnp.setGravity(newValue.floatValue()); } } }