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

Source Code of gov.nasa.arc.mct.fastplot.bridge.LegendEntry

/*******************************************************************************
* 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.components.FeedProvider;
import gov.nasa.arc.mct.fastplot.settings.LineSettings;
import gov.nasa.arc.mct.fastplot.utils.AbbreviatingPlotLabelingAlgorithm;
import gov.nasa.arc.mct.fastplot.utils.TruncatingLabel;
import gov.nasa.arc.mct.fastplot.view.LegendEntryPopupMenuFactory;
import gov.nasa.arc.mct.fastplot.view.legend.AbstractLegendEntry;
import gov.nasa.arc.mct.util.LafColor;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.font.FontRenderContext;
import java.awt.font.TextAttribute;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.ToolTipManager;
import javax.swing.border.Border;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import plotter.xy.LinearXYPlotLine;

/**
*  Legend entry for a plot line. The class responds to mouse entered events by increasing the brightness of the text labels.
*/
@SuppressWarnings("serial")
public class LegendEntry extends JPanel implements MouseListener, AbstractLegendEntry {

  private final static Logger logger = LoggerFactory.getLogger(LegendEntry.class);
 
 
  // Padding around labels to create space between the label text and its outside edge
  // Add a little spacing from the left-hand side
  private static final int    LEFT_PADDING  = 5;
  private static final Border PANEL_PADDING = BorderFactory.createEmptyBorder(0, LEFT_PADDING, 0, 0);
 
  private static final Border EMPTY_BORDER = BorderFactory.createEmptyBorder(1,1,1,1);
  private Border focusBorder = BorderFactory.createLineBorder(LafColor.TEXT_HIGHLIGHT);
 
  // Associated plot.
  private LinearXYPlotLine linePlot;

  // Gui widgets
  protected JLabel baseDisplayNameLabel= new TruncatingLabel();
  private Color backgroundColor;
  private Color foregroundColor;
  private Color originalPlotLineColor;
  private Stroke originalPlotLineStroke;
  private Stroke originalRegressionLineStroke;
  private Font originalFont;
  private Font boldFont;
  private Font strikeThruFont;
  private Font boldStrikeThruFont;

  private String baseDisplayName = "";
 
  boolean selected=false;
 
  private String currentToolTipTxt = "";
  private ToolTipManager toolTipManager;
 
  private String dataSetName = "";

  private String thisBaseDisplayName = ""
  private String valueString = "";
  private AbbreviatingPlotLabelingAlgorithm plotLabelingAlgorithm = new AbbreviatingPlotLabelingAlgorithm();
  private String computedBaseDisplayName = "";
  private FeedProvider.RenderingInfo renderingInfo;
 
  private LegendEntryPopupMenuFactory popupManager = null;

  private LineSettings lineSettings = new LineSettings();
 
  // Default width - will be adjusted to match base display name
  private int baseWidth = PlotConstants.PLOT_LEGEND_WIDTH;
 
  private LinearXYPlotLine regressionLine;

  /**
   * Construct a legend entry
   * @param theBackgroundColor background color of the entry
   * @param theForegroundColor text color
   * @param font text font
   */
  public LegendEntry(Color theBackgroundColor, Color theForegroundColor, Font font, AbbreviatingPlotLabelingAlgorithm thisPlotLabelingAlgorithm) {
    setBorder(EMPTY_BORDER);
    setOpaque(false);
   
    plotLabelingAlgorithm = thisPlotLabelingAlgorithm;
   
    backgroundColor = theBackgroundColor; 
    foregroundColor =  theForegroundColor;
    setForeground(foregroundColor);
    lineSettings.setMarker(lineSettings.getColorIndex());
    // Default to using same marker index as color index; may be later overridden if user-specified
   
    focusBorder = BorderFactory.createLineBorder(theForegroundColor);
   
    // NOTE: Original font size is 10. Decrease by 1 to size 9.
    // Need to explicitly cast to float from int on derived font size
    // Need to explicitly set to FontName=ArialMT/Arial-BoldMT and FontFamily=Arial to be
    // cross OS platforms L&F between MacOSX and Linux.
    // MacOSX defaults to Arial and Linux defaults to Dialog FontFamily.
    originalFont = font;
    originalFont = originalFont.deriveFont((float)(originalFont.getSize()-1))
    boldFont = originalFont.deriveFont(Font.BOLD);
    Map<TextAttribute, Object> attributes = new Hashtable<TextAttribute, Object>();
    attributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
    strikeThruFont = originalFont.deriveFont(attributes);
    boldStrikeThruFont = boldFont.deriveFont(attributes);
 
    // Setup the look of the labels.
    baseDisplayNameLabel.setBackground(backgroundColor);
    baseDisplayNameLabel.setForeground(foregroundColor);
    baseDisplayNameLabel.setFont(originalFont);
    baseDisplayNameLabel.setOpaque(true);
   
    // Sets as the default ToolTipManager
    toolTipManager = ToolTipManager.sharedInstance();
    toolTipManager.setEnabled(true);
    toolTipManager.setLightWeightPopupEnabled(true);
   
    // Defaults: toolTipManager.getDismissDelay()=4000ms,
    // toolTipManager.getInitialDelay()=750ms,
    // toolTipManager.getReshowDelay()=500ms
    toolTipManager.setDismissDelay(PlotConstants.MILLISECONDS_IN_SECOND * 3);
    toolTipManager.setInitialDelay(PlotConstants.MILLISECONDS_IN_SECOND / 2);
    toolTipManager.setReshowDelay(PlotConstants.MILLISECONDS_IN_SECOND / 2);
   
    // Place the labels according to the format specified in the UE spec.
    layoutLabels();

    // Listen to mouse events to drive the highlighting of legends when mouse enters.
    addMouseListener(this);
  }

  // Data getter and and setters
  void setPlot(LinearXYPlotLine thePlot) {
    linePlot = thePlot;
    updateLinePlotFromSettings();
  }


  private List<String> getPanelOrWindowContextTitleList() {
    List<String> panelOrWindowContextTitleList = new ArrayList<String>();
    panelOrWindowContextTitleList.clear();
   
    if (plotLabelingAlgorithm != null) {

      if (plotLabelingAlgorithm.getPanelContextTitleList().size() > 0) {
        panelOrWindowContextTitleList.addAll(this.plotLabelingAlgorithm.getPanelContextTitleList());
      }
     
      if (plotLabelingAlgorithm.getCanvasContextTitleList().size() > 0) {
        panelOrWindowContextTitleList.addAll(this.plotLabelingAlgorithm.getCanvasContextTitleList());
      }
     
    } else {
      logger.error("Plot labeling algorithm object is NULL!");
    }
       
    return panelOrWindowContextTitleList;
  }
 
  public void setBaseDisplayName(String theBaseDisplayName) {
   
    thisBaseDisplayName = theBaseDisplayName;
   
    if (thisBaseDisplayName != null) {
      thisBaseDisplayName = thisBaseDisplayName.trim();
    }
   
    baseDisplayName  = thisBaseDisplayName;
         
    // Format the base display name
    // Split string around newline character.
     String[] strings = baseDisplayName.split(PlotConstants.LEGEND_NEWLINE_CHARACTER);
        
       if (strings.length <= 1) {
      // Determine if first or second string is null
         if (baseDisplayName.indexOf(PlotConstants.LEGEND_NEWLINE_CHARACTER) == -1) {
        // first string is null.
        baseDisplayNameLabel.setText(baseDisplayName);
      } else if (theBaseDisplayName.equals(PlotConstants.LEGEND_NEWLINE_CHARACTER)) {
        baseDisplayNameLabel.setText("")
      } else {
        // second string is empty. Truncate first.
        baseDisplayNameLabel.setText(PlotConstants.LEGEND_ELLIPSES)
      }
     } else {
      
       // Use table labeling algorithm to display base display name.
       // line1 is base display name; while line2 is PUI name
       String line1 = strings[0];
      
       if (line1 != null) {
         baseDisplayName = line1.trim();
         thisBaseDisplayName = baseDisplayName;
       }
      
       List<String> baseDisplayNameList = new ArrayList<String>();
       baseDisplayNameList.add(line1);
     
       assert plotLabelingAlgorithm != null : "Plot labeling algorithm should NOT be NULL at this point.";
      
       baseDisplayName = plotLabelingAlgorithm.computeLabel(baseDisplayNameList, getPanelOrWindowContextTitleList());
      
       // since this name will be used in a legend, it must not be empty so use the initial display name if it would have been empty
       if (baseDisplayName != null && baseDisplayName.isEmpty()) {
         baseDisplayName = thisBaseDisplayName;
       }
       computedBaseDisplayName = baseDisplayName;

       updateLabelText();
     }
   
       valueString = formatNumericStringToScientificNotation(valueString);
      
       thisBaseDisplayName = theBaseDisplayName.replaceAll(PlotConstants.WORD_DELIMITERS, " ");
       currentToolTipTxt = "<HTML>" + thisBaseDisplayName.replaceAll(PlotConstants.LEGEND_NEWLINE_CHARACTER, "<BR>") + "<BR>" + valueString + "<HTML>";
       this.setToolTipText(currentToolTipTxt)
  }

  private String formatNumericStringToScientificNotation(String valueString) {
    if (valueString != null && !valueString.isEmpty()) {
            valueString = PlotterPlot.getNumberFormatter(Double.parseDouble(valueString)).format(Double.parseDouble(valueString));
        }
    return valueString;
  }
 
  void setData(FeedProvider.RenderingInfo info) {
    this.renderingInfo = info;
    String valueText = info.getValueText();
    if (!"".equals(valueText)) {
      valueString = PlotConstants.DECIMAL_FORMAT.format(Double.parseDouble(valueText));
      valueString = formatNumericStringToScientificNotation(valueString);
    }
    updateLabelFont();
    updateLabelText();
    thisBaseDisplayName = thisBaseDisplayName.replaceAll(PlotConstants.WORD_DELIMITERS, " ");
      currentToolTipTxt = "<HTML>" + thisBaseDisplayName.replaceAll(PlotConstants.LEGEND_NEWLINE_CHARACTER, "<BR>") + "<BR>" + valueString + "<HTML>";
      this.setToolTipText(currentToolTipTxt);
      
  }


  private void updateLabelFont() {
    if(selected) {
      if(renderingInfo == null || renderingInfo.isPlottable()) {
        baseDisplayNameLabel.setFont(boldFont);
      } else {
        baseDisplayNameLabel.setFont(boldStrikeThruFont);
      }
    } else {
      if(renderingInfo == null || renderingInfo.isPlottable()) {
        baseDisplayNameLabel.setFont(originalFont);
      } else {
        baseDisplayNameLabel.setFont(strikeThruFont);
      }
    }
  }


  private void updateLabelText() {
    String statusText = renderingInfo == null ? null : renderingInfo.getStatusText();
    if(statusText == null) {
      statusText = "";
    }
    statusText = statusText.trim();
    if(!"".equals(statusText)) {
      baseDisplayNameLabel.setText("(" + statusText + ") " + baseDisplayName);
    } else {
      baseDisplayNameLabel.setText(baseDisplayName);
    }
  }
 
  private void updateLabelWidth() {
    /* Record font & string to restore*/
    Font   f = baseDisplayNameLabel.getFont();
    String s = baseDisplayNameLabel.getText();
   
    if (f == originalFont && s.equals(baseDisplayName) && baseDisplayNameLabel.isValid()) {
      baseWidth = baseDisplayNameLabel.getWidth();
    }
   
  }
 
  /**
   * Layout the labels within a legend in line with the UE specification.
   */
  void layoutLabels() {
    setLayout(new BorderLayout());

    JPanel panel = new JPanel();
    panel.setBorder(PANEL_PADDING);
    panel.setBackground(backgroundColor);
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

    JPanel displayNamePanel = new JPanel();
    displayNamePanel.setLayout(new BoxLayout(displayNamePanel, BoxLayout.LINE_AXIS));
    displayNamePanel.add(baseDisplayNameLabel);
    displayNamePanel.setAlignmentX(Component.LEFT_ALIGNMENT);

    panel.add(displayNamePanel);

    add(panel, BorderLayout.CENTER);
  }

  @Override
  public void mouseClicked(MouseEvent e) {
    // do nothing 
  }

  @Override
  public void mouseEntered(MouseEvent e) {
   
    toolTipManager.registerComponent(this);

    if (!selected) {
      // Highlight this entry on the plot.
      originalPlotLineColor  = linePlot.getForeground();
      originalPlotLineStroke = linePlot.getStroke();
    }
   
    selected = true;
    // Highlight this legend entry
    baseDisplayNameLabel.setForeground(foregroundColor.brighter());
    updateLabelFont();

    linePlot.setForeground(originalPlotLineColor.brighter().brighter());
    if(originalPlotLineStroke == null) {
      linePlot.setStroke(new BasicStroke(PlotConstants.SELECTED_LINE_THICKNESS));
    } else if (originalPlotLineStroke instanceof BasicStroke) {
      BasicStroke stroke = (BasicStroke) originalPlotLineStroke;
      linePlot.setStroke(new BasicStroke(stroke.getLineWidth() * PlotConstants.SELECTED_LINE_THICKNESS, stroke.getEndCap(), stroke
          .getLineJoin(), stroke.getMiterLimit(), stroke.getDashArray(), stroke.getDashPhase()));

    } //Otherwise, it's a stroke we can't change (ie EMPTY_STROKE)

    if (regressionLine != null) {
      originalRegressionLineStroke = regressionLine.getStroke();
      regressionLine.setForeground(originalPlotLineColor.brighter().brighter());
      Stroke stroke = (BasicStroke) regressionLine.getStroke();
      //TODO synch with plot thickness feature changes
      if(stroke == null) {
        regressionLine.setStroke(new BasicStroke(PlotConstants.SLOPE_LINE_WIDTH*2,
                    BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_MITER,
                    10.0f, PlotConstants.dash1, 0.0f));
      } else {
        regressionLine.setStroke(new BasicStroke(PlotConstants.SLOPE_LINE_WIDTH*2,
                    BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_MITER,
                    10.0f, PlotConstants.dash1, 0.0f));
      }
    }
       

    this.setToolTipText(currentToolTipTxt);
   
  }

  @Override
  public void mouseExited(MouseEvent e) {
   
    toolTipManager.unregisterComponent(this);
   
    selected = false;
    // Return this legend entry to its original look.
    baseDisplayNameLabel.setForeground(foregroundColor);
    updateLabelFont();
   
    // Return this entry on the plot to its original look.
    linePlot.setForeground(originalPlotLineColor);
    linePlot.setStroke(originalPlotLineStroke);
    if (regressionLine != null) {
      regressionLine.setForeground(originalPlotLineColor);
      regressionLine.setStroke(originalRegressionLineStroke);
    }
  }

  @Override
  public void mousePressed(MouseEvent e) {
    // open the color changing popup 
    if (popupManager != null && e.isPopupTrigger()) {
      setBorder(focusBorder); //TODO: Externalize the color of this?
      JPopupMenu popup = popupManager.getPopup(this);
      popup.show(this, e.getX(), e.getY());
      popup.addPopupMenuListener(new PopupMenuListener() {

        @Override
        public void popupMenuCanceled(PopupMenuEvent arg0) {
          setBorder(EMPTY_BORDER);
        }

        @Override
        public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) {
          setBorder(EMPTY_BORDER);
        }

        @Override
        public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) {
         
        }
       
      });
    }
  }

  @Override
  public void mouseReleased(MouseEvent e) {
    if (popupManager != null && e.isPopupTrigger()) {
      popupManager.getPopup(this).show(this, e.getX(), e.getY());
    }
  }
 
  public String getToolTipText() {
    return currentToolTipTxt;
  }

  // Retrieves whatever is set in the label text field
  public String getBaseDisplayNameLabel() {
    return baseDisplayNameLabel.getText();
  }
   
  // Retrieves base display name + PUI name
  public String getFullBaseDisplayName() {
    return thisBaseDisplayName;
  }
 
  // Retrieves only base display name (w/o PUI name)
  // after running thru labeling algorithm
  public String getComputedBaseDisplayName() {
    return computedBaseDisplayName;
  }
 
  // Retrieves truncated with ellipse
  public String getTruncatedBaseDisplayName() {
    return baseDisplayName;
  }
 
  public void setPlotLabelingAlgorithm(AbbreviatingPlotLabelingAlgorithm plotLabelingAlgorithm) {
    this.plotLabelingAlgorithm = plotLabelingAlgorithm;
  }
 
  public AbbreviatingPlotLabelingAlgorithm getPlotLabelingAlgorithm() {
    return this.plotLabelingAlgorithm;
  }
 
  public int getLabelWidth() {
    updateLabelWidth();
    return baseWidth + LEFT_PADDING;
  }

  @Override
  public void setForeground(Color fg) {
    Color lineColor = fg;
    Color labelColor = fg;
    if (linePlot != null) {
      if (linePlot.getForeground() != foregroundColor) lineColor = fg;
      linePlot.setForeground(lineColor);
    }
   
    if (regressionLine != null) {
      if (regressionLine.getForeground() != foregroundColor) lineColor = fg.brighter().brighter();
      regressionLine.setForeground(lineColor);
    }
   
    if (baseDisplayNameLabel != null) {
      if (baseDisplayNameLabel.getForeground() != foregroundColor) labelColor = fg.brighter();
      baseDisplayNameLabel.setForeground(labelColor);
    }
   
    foregroundColor = fg;   
    focusBorder = BorderFactory.createLineBorder(fg);
   
    // Infer the appropriate index for this color
    for (int i = 0; i < PlotConstants.MAX_NUMBER_OF_DATA_ITEMS_ON_A_PLOT; i++) {
      if (PlotLineColorPalette.getColor(i).getRGB() == fg.getRGB()) {
        lineSettings.setColorIndex(i);
      }
    }
   
    super.setForeground(fg);
  }

  public LegendEntryPopupMenuFactory getPopup() {
    return popupManager;
  }

  public void setPopup(LegendEntryPopupMenuFactory popup) {
    this.popupManager = popup;
  }
 
  public void setLineSettings(LineSettings settings) {
    lineSettings = settings;
    updateLinePlotFromSettings();
  }
 
  public LineSettings getLineSettings() {
    return lineSettings;
  }
 
  private void updateLinePlotFromSettings() {
    /* Color */
    int index = lineSettings.getColorIndex();
    Color c = PlotLineColorPalette.getColor(index);
    setForeground(c);
   
    /* Thickness */
    Stroke s = linePlot.getStroke();
    if (s == null || s instanceof BasicStroke) {
      int t = lineSettings.getThickness();
      linePlot.setStroke(t == 1 ? null : new BasicStroke(t));
      originalPlotLineStroke = linePlot.getStroke();
    } // We only want to modify known strokes
   
    /* Marker */
    if (linePlot.getPointIcon() != null) {
      Shape shape = null;
      if (lineSettings.getUseCharacter()) {
        Graphics g = getGraphics();
        if (g != null && g instanceof Graphics2D) {
          FontRenderContext frc = ((Graphics2D)g).getFontRenderContext();
          shape = PlotLineShapePalette.getShape(lineSettings.getCharacter(), frc);
        }
      } else {
        int marker = lineSettings.getMarker();     
        shape = PlotLineShapePalette.getShape(marker);
      }
      if (shape != null) {
        linePlot.setPointIcon(new PlotMarkerIcon(shape));       
        baseDisplayNameLabel.setIcon(new PlotMarkerIcon(shape, false, 12, 12));
      }
    }
   
    linePlot.repaint()
    repaint();
  }

  /** Get whether a regression line is displayed or not.
   * @return regressionLine
   */
  public boolean hasRegressionLine() {
    return lineSettings.getHasRegression();
  }

  /** Set whether a regression line is displayed or not.
   * @param regressionLine boolean indicator
   */
  public void setHasRegressionLine(boolean regressionLine) {
    lineSettings.setHasRegression(regressionLine);
  }

  /** Get the number of regression points to use.
   * @return numberRegressionPoints the number of regression points to use
   */
  public int getNumberRegressionPoints() {
    return lineSettings.getRegressionPoints();
  }

  /** Set the number of regression points to use.
   * @param numberRegressionPoints
   */
  public void setNumberRegressionPoints(int numberRegressionPoints) {
    lineSettings.setRegressionPoints(numberRegressionPoints);
  }

  /** Get the regression line for this legend entry.
   * @return regressionLine a LinearXYPlotLine
   */
  public LinearXYPlotLine getRegressionLine() {
    return regressionLine;
  }

  /** Set the regression line for this legend entry.
   * @param regressionLine a LinearXYPlotLine
   */
  public void setRegressionLine(LinearXYPlotLine regressionLine) {
    this.regressionLine = regressionLine;
    if (regressionLine != null)
      regressionLine.setForeground(foregroundColor);
  }
  /**
   * @return the dataSetName
   */
  public String getDataSetName() {
    return dataSetName;
  }

  /**
   * @param dataSetName the dataSetName to set
   */
  public void setDataSetName(String dataSetName) {
    this.dataSetName = dataSetName;
  }

  @Override
  public void attachPlotLine(AbstractPlotLine plotLine) {
    // TODO Auto-generated method stub
   
  }

  @Override
  public String getDisplayedName() {
    return this.baseDisplayName;
  }

}
TOP

Related Classes of gov.nasa.arc.mct.fastplot.bridge.LegendEntry

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.