/* JView.java Java 3D tensegrity viewer for single models History: 01 Jun 2006 Fix glitch in Scrollbar (didn't account for bubble). Add drag rotation and scroll. 26 May 2006 Put the magnify scrollbar on the right. 21 Nov 2005 Created from TViewJ3D.java. Comments: Use ThreeD instead of JThreeD and it will work as a wireframe viewer. */ import java.awt.*; import java.awt.event.*; // for WindowAdapter and WindowEvent import java.io.*; /** GUI for viewing tensegrities with simple hubs @author Bob Burkhardt */ public class JView extends Frame implements ThreeDClient, ActionListener, AdjustmentListener, MouseListener, MouseMotionListener { JThreeD m_threed; Scrollbar m_magnifybar; Button m_reload; Label m_messenger; /** How many integer units to divide the zoom Scrollbar's range into. Scrollbar is set so its output value ranges from 0 to -SCROLL_RESOLUTION. */ static final int SCROLL_RESOLUTION = 1000; /** How wide to make the zoom Scrollbar bubble. Should be some smaller percentage of the SCROLL_RESOLUTION value and definitely not bigger than it. */ static final int SCROLL_BUBBLE_WIDTH = 50; /** The maximum magnification that is allowed. The minimum is none (1.0f). */ static final float MAX_MAGNIFICATION = 12.0f; /** Amount the figure is currently being magnified. Varies from 0 (no magnification) to -SCROLL_RESOLUTION (MAX_MAGNIFICATION). */ int m_magnify_value; /** Name of file containing data for file being viewed. */ String m_model_filename; /** Initial dimension of Canvas3D square. */ static final int INITIAL_DIM = 700; /** Indicate whether left-mouse-button drag is in progress. MOUSE_PRESSED indicates drag in progress; otherwise, MOUSE_RELEASED. */ int m_drag = MouseEvent.MOUSE_RELEASED; /** Requires the model filename as an argument. */ public static void main(String args[]) { if (args.length != 1) { System.out.println("Usage: JView "); System.exit(1); } JView viewer = new JView(args[0], INITIAL_DIM, INITIAL_DIM); viewer.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); viewer.show(); viewer.load(); } public JView(String model_filename, int width, int height) { super("Tensegrity Viewer"); setSize(width, height); m_model_filename = model_filename; setLayout(new BorderLayout()); Panel p = new Panel(); p.setLayout(new FlowLayout()); m_reload = new Button("Reload"); m_reload.addActionListener(this); p.add(m_reload); add("North", p); m_magnifybar = new Scrollbar(Scrollbar.VERTICAL, 0, SCROLL_BUBBLE_WIDTH, -SCROLL_RESOLUTION, SCROLL_BUBBLE_WIDTH); m_magnifybar.addAdjustmentListener(this); add("East", m_magnifybar); m_threed = new JThreeD(this, MAX_MAGNIFICATION, width, height); m_threed.addMouseListener(this); m_threed.addMouseMotionListener(this); add("Center", m_threed); m_messenger = new Label(); add("South", m_messenger); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } /** Display a status message to the user. */ public void userMessage(String msg) { m_messenger.setText(msg); } /** Create data stream for specified model and send to m_threed. @param model_name name of file containing model data */ public void load() { try { resetMagnification(); File model_file = new File(m_model_filename); FileInputStream is = new FileInputStream(model_file); m_threed.load(is); } catch (Exception e) { userMessage(e.toString()); } } /** Handle Button events. */ public void actionPerformed(ActionEvent evt) { if (evt.getSource() == m_reload) load(); } /** Handle Scrollbar events. */ public void adjustmentValueChanged(AdjustmentEvent evt) { int old_value = m_magnify_value; m_magnify_value = m_magnifybar.getValue(); float max = (float)-SCROLL_RESOLUTION; float int_mag = (float)m_magnify_value; if (old_value != m_magnify_value) m_threed.setMagnification(1.0f + (MAX_MAGNIFICATION - 1.0f)*int_mag/max); } /** Watch for presses of the left mouse button, and update state accordingly (part of MouseListener interface). */ public void mousePressed(MouseEvent evt) { if (evt.getButton() == MouseEvent.BUTTON1) { m_drag = MouseEvent.MOUSE_PRESSED; m_threed.startDrag(evt.getX(), evt.getY()); } } /** Watch for presses of the left mouse button, and update state accordingly (part of MouseListener interface). */ public void mouseReleased(MouseEvent evt) { if (evt.getButton() == MouseEvent.BUTTON1) m_drag = MouseEvent.MOUSE_RELEASED; } /** Implement this for the MouseListener interface, but ignore the events. */ public void mouseClicked(MouseEvent evt) { } /** Implement this for the MouseListener interface, but ignore the events. */ public void mouseEntered(MouseEvent evt) { } /** Implement this for the MouseListener interface, but ignore the events. */ public void mouseExited(MouseEvent evt) { } /** Watch for mouse movements and adjust rotation accordingly (part of MouseMotionListener interface). */ public void mouseDragged(MouseEvent evt) { if (m_drag == MouseEvent.MOUSE_PRESSED) if ((evt.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0) m_threed.updateShift(evt.getX(), evt.getY()); else m_threed.updateRotation(evt.getX(), evt.getY()); } /** Implement this for the MouseMotionListener interface, but ignore the events. */ public void mouseMoved(MouseEvent evt) { } /** Put magnify Scrollbar at its minimum-magnification value (0). This is actually the maximum as far as the Scrollbar's internals are concerned. The maximum-magnification value is -SCROLL_RESOLUTION. This method also communicates with m_threed to make sure the magnification gets reset to 1.0 there. */ private void resetMagnification() { m_magnifybar.setValue(0); m_magnify_value = 0; m_threed.resetMagnification(); } /** This method does everything necessary to reset the rotation amount to none, which just amounts to telling m_threed to do this. */ private void resetRotation() { m_threed.resetRotation(); } /** This method does everything necessary to reset the shift vector to zero, which just amounts to telling m_threed to do this. */ private void resetShift() { m_threed.resetShift(); } }