Package gov.nasa.arc.mct.fastplot.bridge

Source Code of gov.nasa.arc.mct.fastplot.bridge.StackPlotLayout$XYPlotComponents

/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.arc.mct.fastplot.bridge;

import gov.nasa.arc.mct.fastplot.bridge.PlotConstants.AxisOrientationSetting;
import gov.nasa.arc.mct.fastplot.utils.ComponentTraverser;
import gov.nasa.arc.mct.fastplot.utils.ComponentTraverser.ComponentProcedure;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JLabel;

import plotter.xy.SlopeLineDisplay;
import plotter.xy.XYAxis;
import plotter.xy.XYLocationDisplay;
import plotter.xy.XYPlot;

/**
* Manages layout for stack plots. Primarily functions as a grid bag layout, but
* also forces alignment on y axes by monitoring / adjusting y axis width and
* legend manager width.
*
* @author vwoeltje
*
*/
public class StackPlotLayout extends GridBagLayout {
  private static final long serialVersionUID = 1L;

  private PlotView plotView;
 
  public StackPlotLayout (PlotView plotView) {
    this.plotView = plotView;
  }
 
  @Override
  public void layoutContainer(Container parent) {
    final List<XYPlotComponents> componentList = new ArrayList<XYPlotComponents>();
   
    /* Find all XYPlots and create mappings to their internal elements */
    ComponentTraverser.traverse(parent, new ComponentProcedure() {
      @Override
      public void run(Component c) {
        if (c instanceof XYPlot) componentList.add(new XYPlotComponents((XYPlot) c));     
      }     
    });
   
    /* Desired widths */
    int yAxisWidth   = 1;
    int legendWidth  = 1;

    /* Desired height (in case legend gets tall) */
    int legendHeight = 1;
 
    /* Swap minimum width and height if we are a sideways stackplot */
    int minWidth, minHeight;   
    if (plotView.getAxisOrientationSetting() == AxisOrientationSetting.X_AXIS_AS_TIME) {
      minWidth = PlotConstants.MINIMUM_PLOT_WIDTH;
      minHeight = PlotConstants.MINIMUM_PLOT_HEIGHT;       
    } else if (plotView.getAxisOrientationSetting() == AxisOrientationSetting.Y_AXIS_AS_TIME){
      minWidth = PlotConstants.MINIMUM_PLOT_HEIGHT;
      minHeight = PlotConstants.MINIMUM_PLOT_WIDTH;     
    } else {
      minWidth = PlotConstants.MINIMUM_PLOT_WIDTH;
      minHeight = PlotConstants.MINIMUM_PLOT_HEIGHT;
    }
 
   
    /* Find the largest "desired" width/height for the components */
    for (XYPlotComponents xyPlotComps : componentList) {
      int textMargin = xyPlotComps.getYAxis().getTextMargin();
     
      yAxisWidth = Math.max(xyPlotComps.getYAxis().getWidth(), yAxisWidth);
      for (Component c : xyPlotComps.getYAxis().getComponents()) {
        yAxisWidth = Math.max(c.getWidth() + textMargin, yAxisWidth);
      }
      for (LegendEntry c : xyPlotComps.getLegend().getLegendEntryList()) { 
        legendWidth = Math.max(c.getLabelWidth(), legendWidth);               
      }     
      legendHeight = Math.max(xyPlotComps.getLegend().getHeight(), legendHeight);   
     
      if (plotView.getAxisOrientationSetting() == AxisOrientationSetting.Y_AXIS_AS_TIME) {
        legendWidth = constrainLegendWidth(legendWidth, yAxisWidth, minWidth, parent.getWidth());
        realign(xyPlotComps, yAxisWidth, legendWidth,
            yAxisWidth + minWidth + (componentList.size() > 1 ? legendWidth : 0),
            Math.max(legendHeight, minHeight + xyPlotComps.getSlopeLineDisplay().getHeight()) +
            xyPlotComps.getXAxis().getHeight());
        yAxisWidth = legendWidth = 1; // reset widths
      }     
    } 
   
   
    /* Set all PreferredSizes to the desired widths we've discovered */
    if (plotView.getAxisOrientationSetting() == AxisOrientationSetting.X_AXIS_AS_TIME) {
      legendWidth = constrainLegendWidth(legendWidth, yAxisWidth, minWidth, parent.getWidth());
      for (XYPlotComponents xyPlotComps : componentList) {
        realign(xyPlotComps, yAxisWidth, legendWidth + PlotLineGlobalConfiguration.getLegendPadding(),
            yAxisWidth + minWidth,
            Math.max(legendHeight, minHeight + xyPlotComps.getSlopeLineDisplay().getHeight()) +
            xyPlotComps.getXAxis().getHeight());     
      }   
    }
   
    super.layoutContainer(parent);
  }
 
  private int constrainLegendWidth(int legendWidth, int yAxisWidth, int minWidth, int parentWidth) {
    int pad = PlotLineGlobalConfiguration.getLegendPadding();
    /* If there's not enough room for minimum-sized plot, shrink legends */
    if (yAxisWidth + legendWidth + pad + minWidth > parentWidth) {
      int reducedWidth = parentWidth - minWidth - yAxisWidth - pad;
      return (reducedWidth < 0) ? 0 : reducedWidth;
    } else {
      return legendWidth;
    }
  }
 
  private void realign (XYPlotComponents xyPlotComps, int yAxisWidth, int legendWidth, int fullWidth, int fullHeight) {
    XYPlot plot  = xyPlotComps.getPlot();
    XYAxis yAxis = xyPlotComps.getYAxis();
    LegendManager legend = xyPlotComps.getLegend();
       
    yAxis.setPreferredSize(new Dimension ( yAxisWidth,
      yAxis.getPreferredSize().height));     
   
    /* X Axis starts at left edge of Y Axis, so margin must equal Y Axis width */
    xyPlotComps.getXAxis().setStartMargin(yAxisWidth);
     
    legend.setPreferredSize(new Dimension(legendWidth,
        legend.getPreferredSize().height));
     
    plot.setPreferredSize(new Dimension(fullWidth, fullHeight))
   
    /* Initially, let the slope & location displays be as big as they want */
    JLabel  slopeDisplay    = xyPlotComps.getSlopeLineDisplay();
    JLabel  locationDisplay = xyPlotComps.getLocationDisplay();
    letSizeFreely(slopeDisplay);
    letSizeFreely(locationDisplay);

    /* Then clamp them to content width */
    int contentWidth = plot.getContents().getWidth();
    if (slopeDisplay.getPreferredSize().width    > contentWidth) {
      slopeDisplay.setPreferredSize(new Dimension (contentWidth, slopeDisplay.getPreferredSize().height));
    }
    if (locationDisplay.getPreferredSize().width > contentWidth) {
      locationDisplay.setPreferredSize(new Dimension (contentWidth, locationDisplay.getPreferredSize().height));
    }
   
    /* Hide the location display if there is insufficient room */
    if (!slopeDisplay.getText().isEmpty() && locationDisplay.getPreferredSize().width + slopeDisplay.getPreferredSize().width > contentWidth) {
      locationDisplay.setPreferredSize(new Dimension (1,locationDisplay.getPreferredSize().height));
    }
   
    /* Finally, request that these new preferred sizes get enforced */
    plot.revalidate();   
  }

  /**
   * Prevent JLabels from shrinking when empty, but size freely when filled
   * (originally from PlotDataCursor)
   */
  private void letSizeFreely(JLabel label) { 
    if (label.getText().isEmpty() || !label.isVisible()) {
      label.setText("Ag");
      Dimension size = label.getPreferredSize();
      size.width = 1;
      label.setText("");
      label.setPreferredSize(size);
    } else {
      label.setPreferredSize(null);
    }
  }
 

  /*
   * Provide access to components in an XYPlot. Helpful insofar as getLegend() is
   * not available in XYPlot itself (legends are tacked on external to Plotter package)
   */
  private static class XYPlotComponents {
    private XYPlot            plot;
    private LegendManager     legend = null;
    private SlopeLineDisplay  slope  = null;
    private XYLocationDisplay location = null;
   
    public XYPlotComponents(XYPlot xyPlot) {
      plot = xyPlot;
      findLegend();
   
   
    public XYPlot getPlot() {
      return plot;
    }
   
    public XYAxis  getYAxis()  {
      return plot.getYAxis();
    }
   
    public XYAxis  getXAxis()  {
      return plot.getXAxis();
    }
   
    public JLabel getSlopeLineDisplay() {
      return slope;
    }
   
   
    public JLabel getLocationDisplay() {
      return location;
    }
   
    public LegendManager getLegend() {
      /* It may be the case that a legend has been added since
       * this object was created, so look for it */      
      if (legend == null) findLegend();
      return legend;
    }
   
    private void findLegend() {
      for (Component c : plot.getComponents()) {
        if (c instanceof LegendManager) {
          legend = (LegendManager) c;
        }
        if (c instanceof SlopeLineDisplay) {
          slope  = (SlopeLineDisplay) c;
        }
        if (c instanceof XYLocationDisplay) {
          location = (XYLocationDisplay) c;         
        }
      }
    }
  }
}
TOP

Related Classes of gov.nasa.arc.mct.fastplot.bridge.StackPlotLayout$XYPlotComponents

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.