package gov.nasa.arc.mct.fastplot.bridge.controls; import gov.nasa.arc.mct.fastplot.bridge.AbstractAxis; import gov.nasa.arc.mct.fastplot.bridge.AbstractAxis.AxisVisibleOrientation; import gov.nasa.arc.mct.fastplot.bridge.PlotObserver; import gov.nasa.arc.mct.fastplot.view.IconLoader.Icons; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.SpringLayout; /** * Base class for pan- or zoom-style controls. Both controls behave similarly in * terms of layout, interaction, etc.; this class describes those commonalities. * * @author vwoeltje * */ public abstract class AbstractPanZoomControls extends AbstractPlotLocalControl implements ActionListener { private static final long serialVersionUID = 3970100144412350694L; private static final List<AttachmentLocation> X_ATTACHMENTS = Arrays.asList( new AttachmentLocation(SpringLayout.NORTH, SpringLayout.SOUTH, 2), new AttachmentLocation(SpringLayout.HORIZONTAL_CENTER, SpringLayout.HORIZONTAL_CENTER, 0)); private static final List<AttachmentLocation> Y_ATTACHMENTS = Arrays.asList( new AttachmentLocation(SpringLayout.EAST, SpringLayout.WEST, -2), new AttachmentLocation(SpringLayout.VERTICAL_CENTER, SpringLayout.VERTICAL_CENTER, 0)); private AbstractAxis axis; private JButton toStart, toEnd; private boolean keyState = false; private boolean mouseState = false; /** * Create controls for the specified plot axis. The axis will be used to determine the orientation * of controls (horizontal or vertical), and will receive updates when controls are clicked. * @param axis */ public AbstractPanZoomControls(AbstractAxis axis) { super(); this.axis = axis; AxisVisibleOrientation orientation = axis.getVisibleOrientation(); toStart = makeButton(getIcon(orientation, true), this, getName(orientation, true)); toEnd = makeButton(getIcon(orientation, false), this, getName(orientation, false)); toStart.setVisible(true); toEnd.setVisible(true); switch(axis.getVisibleOrientation()) { case HORIZONTAL: setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); add(toStart); add(toEnd); break; case VERTICAL: setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); add(toEnd); add(toStart); break; } setVisible(false); } /** * Apply whatever adjustment this control performs (panning or zooming) * The "less" argument indicates whether or not this adjustment goes toward the bottom-left. * * Note that currentSpan is presumed to be calculated as getEnd-getStart for the axis; so, * the sign will be negative if the axes have been inverted (i.e. "max at left"). Implementing * classes may use this sign (implicitly or explicitly) to adjust the axis in the correct * direction. * * @param axis the axis to update * @param currentSpan the current axis span * @param less */ public abstract void adjustAxis(AbstractAxis axis, double currentSpan, boolean less); /* (non-Javadoc) * @see gov.nasa.arc.mct.fastplot.bridge.controls.AbstractPlotLocalControl#informKeyState(int, boolean) */ @Override public void informKeyState(int key, boolean pressed) { if (key == getTriggerKeyCode()) { keyState = pressed; setVisible(mouseState && keyState); } } /* (non-Javadoc) * @see gov.nasa.arc.mct.fastplot.bridge.controls.AbstractPlotLocalControl#informMouseHover(boolean) */ @Override public void informMouseHover(boolean inPlotArea) { mouseState = inPlotArea; setVisible(mouseState && keyState); } @Override public Collection<AttachmentLocation> getDesiredAttachmentLocations() { switch (axis.getVisibleOrientation()) { case HORIZONTAL: return X_ATTACHMENTS; case VERTICAL: return Y_ATTACHMENTS; } return Collections.<AttachmentLocation>emptyList(); } @Override public PlotObserver getPlotObserver() { return null; } @Override public void actionPerformed(ActionEvent evt) { if (evt.getSource().equals(toStart)) { adjustAxis(axis, axis.getEnd() - axis.getStart(), true); } else if (evt.getSource().equals(toEnd)) { adjustAxis(axis, axis.getEnd() - axis.getStart(), false); } //Note: Axis is responsible for introducing a pin and/or notifying observers } /** * Utility method to determine appropriate icon for pan button * @param less true if the pan button goes toward the bottom or left; otherwise, false * @return */ protected abstract Icons getIcon(AxisVisibleOrientation o, boolean less); /** * Utility method to determine an appropriate name for a pan button * @param less true if the pan button goes toward the bottom or left; otherwise, false * @return */ protected abstract String getName(AxisVisibleOrientation o, boolean less); /** * Get the key that is used to show/hide this control; should be one of the * KeyEvent.VK_* codes. * @return the key code used to enable these controls */ protected abstract int getTriggerKeyCode(); }