package gov.nasa.arc.mct.fastplot.bridge.controls; import gov.nasa.arc.mct.fastplot.bridge.AbstractPlottingPackage; import gov.nasa.arc.mct.fastplot.bridge.PlotConstants; import gov.nasa.arc.mct.fastplot.bridge.PlotLocalControlsManager; import gov.nasa.arc.mct.fastplot.bridge.PlotObserver; import gov.nasa.arc.mct.fastplot.view.IconLoader; import java.awt.event.ActionListener; import java.util.Collection; import java.util.ResourceBundle; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.border.Border; /** * Base class for plot local controls. These are controls which will appear as part of the * plot view, used to make immediate changes to what is being shown (as opposed to broader * changes to the view). * * @see gov.nasa.arc.mct.fastplot.bridge.AbstractPlottingPackage#attachLocalControl(AbstractPlotLocalControl) * * @author vwoeltje */ public abstract class AbstractPlotLocalControl extends JPanel { private static final long serialVersionUID = 5762300765204572813L; private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(PlotLocalControlsManager.class.getName().substring(0, PlotLocalControlsManager.class.getName().lastIndexOf("."))+".Bundle"); private static final Border BUTTON_BORDER = BorderFactory.createEmptyBorder( PlotConstants.ARROW_BUTTON_BORDER_STYLE_BOTTOM, PlotConstants.ARROW_BUTTON_BORDER_STYLE_LEFT, PlotConstants.ARROW_BUTTON_BORDER_STYLE_BOTTOM, PlotConstants.ARROW_BUTTON_BORDER_STYLE_RIGHT); /** * Controls are attached to one specific plot, represented by this object */ private AbstractPlottingPackage plottingPackage = null; /** * Default constructor; does minimal setup of the underlying JPanel */ public AbstractPlotLocalControl() { setOpaque(false); } /** * Inform the local control about a change in key state. Some * controls only show/hide while certain keys are pressed. * @param key the key code, from KeyEvent * @param pressed whether or not the key is down */ public void informKeyState(int key, boolean pressed) { // By default, do nothing; some controls may override this. } /** * Informs the local control about whether or not the mouse is * within the local control's area. * @param inPlotArea true if the mouse is hovering over the plot */ public void informMouseHover(boolean inPlotArea) { // By default, do nothing; some controls may override this. } /** * Get the desired attachment locations for this control. This collection describes * the desired positioning of this specific control upon the plot. * * @see AttachmentLocation * * @return */ public abstract Collection<AttachmentLocation> getDesiredAttachmentLocations(); /** * Get a PlotObserver which should receive updates about the plot. Controls may use * this observer to respond to changes in the plot that should change the appearance * or behavior of control elements. * * This method may return null to indicate that a control does not use an observer * (for instance, because it does not need to respond to any changes to the plot) * * @return */ public abstract PlotObserver getPlotObserver(); /** * Add this control to a specific instance of a plot. This updates the control's * stored reference to its targeted plotting package, invokes the plotting package's * attachControl method, and registers the control as an Observer for the plot. * * @param plottingPackage the plot to which this control should be attached */ public void attachTo(AbstractPlottingPackage plottingPackage) { this.plottingPackage = plottingPackage; PlotObserver observer = getPlotObserver(); if (observer != null) { plottingPackage.registerObservor(observer); } //plottingPackage.attachControl(this) } @Override public boolean isOptimizedDrawingEnabled() { return false; } /** * Get the plot to which this control has been attached. (May be null, if * no plot attachment has been made) * @return the plot that is being controlled */ protected AbstractPlottingPackage getPlot() { return plottingPackage; } /** * Utility method to create an image-based JButton (since most plot controls use * this pattern, this method is provided as a convenience) * * Note that buttonName will both be used to name the component, and to look up * an appropriate tooltip from the resource bundle (if available) * * @param icon the icon used to represent this button * @param listener the listener which should be notified of button presses * @param buttonName the name for the button (also used to find tooltip) * @return an image-based JButton attached to the appropriate listener */ protected JButton makeButton(IconLoader.Icons icon, ActionListener listener, String buttonName) { JButton returnButton = new JButton(icon.getIcon()); if (BUNDLE.containsKey(buttonName + ".Tooltip")) { returnButton.setToolTipText(BUNDLE.getString(buttonName + ".Tooltip")); } returnButton.setName(buttonName); returnButton.setOpaque(false); returnButton.setContentAreaFilled(false); returnButton.setFocusPainted(true); returnButton.setBorder(BUTTON_BORDER); if (listener != null) { returnButton.addActionListener(listener); } return returnButton; } /** * Describes the desired attachment between the control's Swing component * and the plot content area. * * Expected behavior from the plot should resemble: * springLayout.putConstraint(controlPlacement, controlComponent, * distance, * contentPlacement, plotContentComponent); * * Note that the plot (AbstractPlottingPackage) to which a local control * is attached may not necessarily use SpringLayout, and is free to * interpret these requested attachment locations differently. * * @author vwoeltje */ public static class AttachmentLocation { private String controlPlacement; private String contentPlacement; private int distance; protected AttachmentLocation (String placement) { this(placement, placement, 0); } protected AttachmentLocation(String controlPlacement, String contentPlacement, int distance) { super(); this.controlPlacement = controlPlacement; this.contentPlacement = contentPlacement; this.distance = distance; } /** * Get the edge or location on the control's Swing component which should * be aligned to the plot area; should be one of SpringLayout.EAST, * SpringLayout.HORIZONTAL_CENTER, et cetera... (Although the plot does not * necessarily use SpringLayout, these parameters are well-suited to * describing desired control placement.) * * @return the location of the control's edge, as should be placed */ public String getControlPlacement() { return controlPlacement; } /** * Get the edge or location on the plot content area where the control's * Swing component should be aligned; should be one of SpringLayout.EAST, * SpringLayout.HORIZONTAL_CENTER, et cetera... (Although the plot does not * necessarily use SpringLayout, these parameters are well-suited to * describing desired control placement.) * * @return the location on the plot where the control should be placed */ public String getContentPlacement() { return contentPlacement; } /** * @return the distance from the placement point, in pixels */ public int getDistance() { return distance; } } }