Package gov.nasa.arc.mct.fastplot.settings.controls

Source Code of gov.nasa.arc.mct.fastplot.settings.controls.PlotSettingsAxisGroup$ManualTimeEntryArea

package gov.nasa.arc.mct.fastplot.settings.controls;

import gov.nasa.arc.mct.fastplot.bridge.PlotConstants;
import gov.nasa.arc.mct.fastplot.bridge.PlotterPlot;
import gov.nasa.arc.mct.fastplot.settings.PlotConfiguration;
import gov.nasa.arc.mct.fastplot.settings.PlotSettingsPanel;
import gov.nasa.arc.mct.fastplot.settings.PlotSettingsSubPanel;
import gov.nasa.arc.mct.fastplot.view.NumericTextField;
import gov.nasa.arc.mct.fastplot.view.PlotViewManifestation;
import gov.nasa.arc.mct.fastplot.view.TimeDuration;
import gov.nasa.arc.mct.fastplot.view.TimeSpanTextField;
import gov.nasa.arc.mct.fastplot.view.TimeTextField;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.ResourceBundle;
import java.util.TimeZone;

import javax.swing.AbstractButton;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.text.MaskFormatter;

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

public abstract class PlotSettingsAxisGroup extends PlotSettingsPanel implements ActionListener {
  private static final long serialVersionUID = -6810586939806488596L;

  // Names, for automatic naming of nested Swing components
  protected static final String MIN_SUFFIX = "Min";
  protected static final String MAX_SUFFIX = "Max";
  protected static final String SPAN_SUFFIX = "Span";
  protected static final String AUTO_SUFFIX = "Auto";
  protected static final String CURRENT_SUFFIX = "Current";
  protected static final String MANUAL_SUFFIX = "Manual";
  protected static final String VALUE_SUFFIX  = "Value";

  // Access bundle file where externalized strings are defined.
  private static final ResourceBundle BUNDLE =
                               ResourceBundle.getBundle("gov.nasa.arc.mct.fastplot.view.Bundle");

  // Logger
    private final static Logger logger = LoggerFactory.getLogger(PlotSettingsAxisGroup.class);

 
  // Other constants
  private static final Double NONTIME_AXIS_SPAN_INIT_VALUE = Double.valueOf(30);
  private static final int JTEXTFIELD_COLS = 8;
  private static final int NUMERIC_TEXTFIELD_COLS1 = 12;
  private static final String MANUAL_LABEL = BUNDLE.getString("Manual.label");
    private static final int INTERCONTROL_HORIZONTAL_SPACING = 0;
  private static final DecimalFormat PARENTHESIZED_LABEL_FORMAT = new DecimalFormat("###.###");
  private static final int SPACE_BETWEEN_ROW_ITEMS = 3;


  // Fields
  private AxisBoundsPanel minControls;
  private AxisBoundsPanel maxControls;
  private AxisSpanCluster spanControls;
  private String minText = "Min";
  private String maxText = "Max";
  private String title = "Axis";
  private boolean temporal;
  private boolean manualUpdates = true; // Does manual update with current value?
 
  private Runnable autoControlsCallback = new Runnable() {
    @Override
    public void run() {
      if (!temporal) {
        minControls.auto.setEnabled(!maxControls.auto.isSelected());
        minControls.autoValue.setEnabled(!maxControls.auto.isSelected());
        maxControls.auto.setEnabled(!minControls.auto.isSelected());
        maxControls.autoValue.setEnabled(!minControls.auto.isSelected());
        if (!maxControls.auto.isSelected() && !minControls.auto.isSelected()) {
          spanControls.setSpanValue(getValue(maxControls) - getValue(minControls));
        }
        if (!maxControls.auto.isSelected()) {
          minControls.autoValue.setValue(getValue(maxControls) - spanControls.getSpanValue());
        }
        if (!minControls.auto.isSelected()) {
          maxControls.autoValue.setValue(getValue(minControls) + spanControls.getSpanValue());
        }
      } else {
        maxControls.updateAuto(getValue(minControls) + spanControls.getSpanValue());
      }
    }
  };
 
  public PlotSettingsAxisGroup(boolean temporal) {
    this.temporal = temporal;
    this.minControls  = new AxisBoundsPanel(false);
    this.maxControls  = new AxisBoundsPanel(true);
    this.spanControls = new AxisSpanCluster();
    addSubPanel(minControls);
    addSubPanel(maxControls);
    addSubPanel(spanControls);
    minControls.addCallback(autoControlsCallback);
    maxControls.addCallback(autoControlsCallback);
  }
 
  public JPanel getMinControls() {
    return minControls;
  }

  public JPanel getMaxControls() {
    return maxControls;
  }

  public JPanel getSpanControls() {
    return spanControls;
  }

  public String getMinText() {
    return minText;
  }

  public String getMaxText() {
    return maxText;
  }

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }
 
  @Override
  public void setName(String name) {
    super.setName(name);
    minControls.setName(name + MIN_SUFFIX);
    maxControls.setName(name + MAX_SUFFIX);
    spanControls.setName(name + SPAN_SUFFIX);   
  }
 
  public abstract void setBounds(PlotConfiguration settings, double min, double max)
  public abstract double getBoundMinimum(PlotConfiguration settings);
  public abstract double getBoundMaximum(PlotConfiguration settings);
  public abstract double getActualMinimum(PlotViewManifestation view);
  public abstract double getActualMaximum(PlotViewManifestation view);

  public void updateFrom(PlotViewManifestation view) {   
    if (temporal) {
      minControls.updateCurrent(getActualMinimum(view));
      maxControls.updateCurrent(getActualMaximum(view));
      minControls.updateAuto((double) view.getCurrentMCTTime());
      maxControls.updateAuto(getValue(minControls) + spanControls.getSpanValue());
      if (!maxControls.auto.isSelected()) {
        spanControls.setSpanValue(getValue(maxControls) - getValue(minControls));
      }
    } else {
      minControls.currentValue.setValue(getActualMinimum(view));
      maxControls.currentValue.setValue(getActualMaximum(view));
    }
  }
 
  private double getValue(AxisBoundsPanel panel)  {
    try {
      boolean maximum = panel == maxControls;
      AxisBoundsPanel other = maximum ? minControls : maxControls;
      if (temporal) {
        TimeSpanTextField field = (TimeSpanTextField) spanControls.spanValue;
        if (panel.auto.isSelected()) {
          return maximum ? (field.getDurationInMillis() + getValue(other)) :
                         panel.autoValue.getValue(); // Now
        } else if (panel.current.isSelected()) {
          return panel.currentValue.getValue();         
        } else if (panel.manual.isSelected()) {
          return ((ManualTimeEntryArea)panel.manualValue).getValue();
        }
      } else {
        NumericTextField field = (NumericTextField) spanControls.spanValue;
        if (panel.auto.isSelected()) {
          return getValue(other) + (maximum ? 1 : -1) * field.getDoubleValue();
        } else if (panel.current.isSelected()) {
          return panel.currentValue.getValue();
        } else if (panel.manual.isSelected()) {
          field = (NumericTextField) panel.manualValue;
          return field.getDoubleValue();
        }
      }
    } catch (ParseException pe) {
      logger.error("Parse exception in axis bounds panel.")
    }
    logger.error("Could not interpret user input from axis bounds panel.");
    return Double.NaN;
  }

  // Non-time axis Maximums panel
  class AxisBoundsPanel extends PlotSettingsSubPanel {
    private static final long serialVersionUID = -768623994853270825L;

    private JRadioButton         current;   
    private ParenthesizedLabel   currentValue;
    private JRadioButton         manual;   
    private JComponent           manualValue;
    private JRadioButton         auto;   
    private ParenthesizedLabel   autoValue;   
   
    private double               cachedManualValue;
   
    private boolean maximal;
   
    public AxisBoundsPanel(boolean maximal) {
      setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

      current = new JRadioButton(BUNDLE.getString( temporal ?
          (maximal ? "CurrentMax.label" : "Currentmin.label") :
          (maximal ? "CurrentLargestDatum.label" : "CurrentSmallestDatum.label")
      ), true);   
      currentValue = temporal ? new ParenthesizedTimeLabel(current) : new ParenthesizedNumericLabel(current);
     
      manual = new JRadioButton( MANUAL_LABEL, false);
      manualValue = temporal ? getTimeManualValue() : getNonTimeManualValue();
     
      auto = new JRadioButton(BUNDLE.getString(temporal ?
          (maximal ? "MinPlusSpan.label" : "Now.label"        ) :
          (maximal ? "MinPlusSpan.label" : "MaxMinusSpan.label")
      ), false);
      autoValue = temporal ? new ParenthesizedTimeLabel(current) : new ParenthesizedNumericLabel(auto);

      ButtonGroup maximumsGroup = new ButtonGroup();
      maximumsGroup.add(manual);
      maximumsGroup.add(current);
      maximumsGroup.add(auto);

      manual.addActionListener(this);
      current.addActionListener(this);
      auto.addActionListener(this);
     
      // Layout
      add(createMultiItemRow(current, currentValue));
      add(createMultiItemRow(manual,  manualValue) );
      add(createMultiItemRow(auto,    autoValue)   );

      // Note the maximality
      this.maximal = maximal;
     
      //TODO: Tooltips, instrumentation
    }
   
    private JComponent getTimeManualValue() {
      GregorianCalendar calendar = new GregorianCalendar();     
        ManualTimeEntryArea entryArea = new ManualTimeEntryArea(calendar);
        entryArea.addFocusListener(this);
        entryArea.addActionListener(this);
        return entryArea;
    }
   
    private JComponent getNonTimeManualValue() {
      DecimalFormat format = new DecimalFormat("###.######");
      format.setParseIntegerOnly(false);
      manualValue = new NumericTextField(NUMERIC_TEXTFIELD_COLS1, format);
      ((NumericTextField)manualValue).addFocusListener(this);
      ((NumericTextField)manualValue).addActionListener(this);
      ((JTextField)manualValue).setColumns(JTEXTFIELD_COLS);
      return manualValue;
    }
   
    public void updateCurrent(double value) {
      currentValue.setValue(value);
      if (temporal && manualUpdates) {
        updateManual(value);
      }
    }
   
    public void updateManual(double value) {
      if (temporal) ((ManualTimeEntryArea) manualValue).setValue(value);
      else          ((NumericTextField)    manualValue).setValue(value);
    }
   
    public void updateAuto(double value) {
      autoValue.setValue(value);
    }
   
    public void addActionListener(ActionListener actionListener) {
      current.addActionListener(actionListener);
      manual.addActionListener(actionListener);
      auto.addActionListener(actionListener);
    }

    public void removeActionListener(ActionListener actionListener) {
      current.removeActionListener(actionListener);
      manual.removeActionListener(actionListener);
      auto.removeActionListener(actionListener);
    }

    @Override
    public void populate(PlotConfiguration settings) {
      // All handled in the span control - nothing to do here
    }

    @Override
    public void reset(PlotConfiguration settings, boolean hard) {
      if (temporal) {
        if (hard) {
          current.setSelected(true);
          manualUpdates = true;
        } else {
          if (maximal && !auto.isSelected()) {
            spanControls.setSpanValue(getValue(maxControls) - getValue(minControls));
          }
          manualUpdates &= !manual.isSelected();
        }
      } else {
        NumericTextField field = (NumericTextField) manualValue;
        if (hard) {
          manual.setSelected(true);           
          cachedManualValue = maximal ? getBoundMaximum(settings) : getBoundMinimum(settings);
          field.setValue(cachedManualValue);
        }
        // Prevent empty manual value field
        if (field.getText().isEmpty()) {
          field.setValue(cachedManualValue);
        }
        autoControlsCallback.run(); // Update enabled state
      }
    }

    @Override
    public boolean isDirty() {   
      try {
      return !(temporal ? current : manual).isSelected() ||
              (temporal ? false :
                ((NumericTextField) manualValue).getDoubleValue() != cachedManualValue
                 );
      } catch (ParseException pe) {
        return false;
      }
    }

    @Override
    public boolean isValidated() {
      return true;
    }
   
    @Override
    public void setName(String name) {
      auto.setName(name + AUTO_SUFFIX);
      current.setName(name + CURRENT_SUFFIX);
      manual.setName(name + MANUAL_SUFFIX);
      autoValue.setName(name + AUTO_SUFFIX + VALUE_SUFFIX);
      currentValue.setName(name + CURRENT_SUFFIX + VALUE_SUFFIX);
      manualValue.setName(name + MANUAL_SUFFIX + VALUE_SUFFIX);
    }
   
  }



  // Panel holding span controls
  class AxisSpanCluster extends PlotSettingsSubPanel {
    private static final long serialVersionUID = -3947426156383446643L;
    private JTextField spanValue;
    private JLabel spanTag;

    public AxisSpanCluster() {
      setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

          spanTag = new JLabel(BUNDLE.getString("SpanTextField.label"));

          // Create a text field with a ddd/hh:mm:ss format for time
          spanValue = temporal ? getTimeSpanTextFieldFormat() : getNonTimeTextField();
         
          spanValue.addActionListener(this);
          spanValue.addFocusListener(this);
   
          add(spanTag);
            add(Box.createHorizontalStrut(INTERCONTROL_HORIZONTAL_SPACING));
            add(spanValue);
            if (temporal) {
              add(Box.createHorizontalStrut(INTERCONTROL_HORIZONTAL_SPACING + 3));
              add(new JLabel(BUNDLE.getString("YearSpan")));
              add(Box.createHorizontalStrut(INTERCONTROL_HORIZONTAL_SPACING + 3));
              add(((TimeSpanTextField)spanValue).getYearSpanValue());
            }
           
            // Instrument
            spanTag.setName("spanTag");
    }

    JTextField getNonTimeTextField() {
      NumericTextField nonTimeSpanValue = new NumericTextField(NUMERIC_TEXTFIELD_COLS1, PARENTHESIZED_LABEL_FORMAT);
      nonTimeSpanValue.setColumns(JTEXTFIELD_COLS);
      nonTimeSpanValue.setValue(NONTIME_AXIS_SPAN_INIT_VALUE);
      return nonTimeSpanValue;
    }
   
    JTextField getTimeSpanTextFieldFormat() {
      MaskFormatter formatter = null;
      try {
        formatter = new MaskFormatter("###/##:##:##");
        formatter.setPlaceholderCharacter('0');
      } catch (ParseException e) {
        logger.error("Error in creating a mask formatter", e);
      }
          return new TimeSpanTextField(formatter);
    }
   
    public void setName(String name) {
      super.setName(name);
      spanValue.setName(name + VALUE_SUFFIX);
    }
   
    public double getSpanValue() {
      try {
        if (temporal) {
          TimeSpanTextField field = (TimeSpanTextField) spanValue;
          return field.getDurationInMillis();         
        } else {
          NumericTextField field = (NumericTextField) spanValue;
          return field.getDoubleValue();
        }
      } catch (ParseException pe) {
        return Double.NaN;
      }
    }
   
    public void setSpanValue(double value) {
      if (value > 0) {
        if (temporal) {
          TimeSpanTextField field = (TimeSpanTextField) spanValue;
          field.setTime(new TimeDuration((long)value));
        } else {
          NumericTextField field = (NumericTextField) spanValue;
          field.setValue(value);     
        }
      }
    }

    @Override
    public void populate(PlotConfiguration settings) {
      PlotSettingsAxisGroup.this.setBounds(settings, getValue(minControls), getValue(maxControls));
    }
   


    @Override
    public void reset(PlotConfiguration settings, boolean hard) {
      if (temporal) {
        spanValue.setEnabled(maxControls.auto.isSelected());
      } else {
        spanValue.setEnabled(minControls.auto.isSelected() || maxControls.auto.isSelected());
        NumericTextField field = (NumericTextField) spanValue;
        field.setValue(getBoundMaximum(settings) - getBoundMinimum(settings));
      }
    }

    @Override
    public boolean isDirty() {
      // TODO Auto-generated method stub
      return false;
    }

    @Override
    public boolean isValidated() {
      return getValue(maxControls) > getValue(minControls);
    }
   
  }
 
  private class ManualTimeEntryArea extends JPanel {
    private static final long serialVersionUID = 5096738756047815979L;

    private JComboBox yearBox;
    private TimeTextField timeField;
   
    public ManualTimeEntryArea(Calendar calendar) {
      Integer[] years = new Integer[10];
      for (int i = 0 ; i < 10; i++ ) {
        years[i] = new Integer(calendar.get(Calendar.YEAR) - i);
      }
      yearBox = new JComboBox(years);
      yearBox.setEditable(true);
     
          MaskFormatter formatter = null;
      try {
        formatter = new MaskFormatter("###/##:##:##");
        formatter.setPlaceholderCharacter('0');
      } catch (ParseException e) {
        logger.error("Parse error in creating time field", e);
      }
     
      timeField = new TimeTextField(formatter, calendar.get(Calendar.YEAR));
         
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
        add(timeField);
        add(yearBox);
       
        yearBox.setPreferredSize(new Dimension(60,timeField.getPreferredSize().height - 1));
    }
   
    public void addActionListener(ActionListener al) {
      timeField.addActionListener(al);
      yearBox.addActionListener(al);
    }
   
    public void addFocusListener(FocusListener fl) {
      timeField.addFocusListener(fl);
      yearBox.addFocusListener(fl);
    }
   
    public void setValue(double d) {
      GregorianCalendar cal = new GregorianCalendar();
      cal.setTimeZone(TimeZone.getTimeZone(PlotConstants.DEFAULT_TIME_ZONE));
      cal.setTimeInMillis((long) d);
      int year = cal.get(Calendar.YEAR);
      timeField.setTime(cal);
      yearBox.getModel().setSelectedItem(Integer.valueOf(year));
      yearBox.revalidate();
    }
   
    public long getValue() {
      GregorianCalendar cal = new GregorianCalendar();
      cal.setTimeInMillis(timeField.getValueInMillis());
      cal.set(Calendar.YEAR, (Integer) yearBox.getSelectedItem());
      return cal.getTimeInMillis();
    }
  }

 
    private abstract class ParenthesizedLabel extends JLabel {
    private static final long serialVersionUID = 4908562204337928432L;

    abstract void setValue(Double value);
    abstract double getValue();
    }

  private class ParenthesizedTimeLabel extends ParenthesizedLabel {
    private static final long serialVersionUID = -6004293775277749905L;

    private GregorianCalendar timeInMillis = new GregorianCalendar();

    private JRadioButton companionButton;
   
    // TODO: This should be the user-selected date
    private DateFormat dateFormat = new SimpleDateFormat(PlotConstants.DEFAULT_TIME_FORMAT);
   
    public ParenthesizedTimeLabel(JRadioButton button) {
      dateFormat.setTimeZone(TimeZone.getTimeZone(PlotConstants.DEFAULT_TIME_ZONE));
      companionButton = button;
      this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
          companionButton.setSelected(true);
          companionButton.requestFocusInWindow();
          //TODO : Fire callbacks!
        }
      });
    }

    public void setValue (Double value) {
      timeInMillis.setTimeInMillis(value.longValue());
      setText("(" + dateFormat.format(timeInMillis.getTime()) + " "
          + timeInMillis.get(Calendar.YEAR) + ")");   
    }
   
    public double getValue() {
      return (double) timeInMillis.getTimeInMillis();
    }

  }

  private class ParenthesizedNumericLabel extends ParenthesizedLabel {
    private static final long serialVersionUID = 3403375470853249483L;
    private JRadioButton companionButton;

    public ParenthesizedNumericLabel(JRadioButton button) {
     
      companionButton = button;
      this.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) {
          companionButton.setSelected(true);
          companionButton.requestFocusInWindow();
          //TODO: Fire callbacks!
        }
      });
    }

    public double getValue() {
      String data = getText();
      if (data == null) {
        return Double.NaN;
      }
      if (data.length() < 3) {
        logger.error("Numeric label in plot settings contained invalid content [" + data + "]");
        return Double.NaN;
      }
      Double result = null;
      try {
        result = Double.parseDouble(data.substring(1, data.length() - 1));
       
      } catch(NumberFormatException e) {
        logger.error("Could not parse numeric value from ["+ data.substring(1, data.length() - 1) + "]");
      }
      return result;
    }

    public void setValue(Double input) {
     
      String formatNum = PARENTHESIZED_LABEL_FORMAT.format(input);
     
      if ( (input.doubleValue() >= PlotConstants.MILLION_VALUES) || (input.doubleValue() <= PlotConstants.NEGATIVE_MILLION_VALUES) ) {
                formatNum = PlotterPlot.getNumberFormatter(input.doubleValue()).format(input.doubleValue());
      }

      if (formatNum.equals("0"))
        formatNum = "0.0";
     
      if (formatNum.equals("1"))
        formatNum = "1.0";
     
      setText("(" + formatNum + ")");
    }
  }
 
  // Convenience method for populating and applying a standard layout for multi-item rows
    private JPanel createMultiItemRow(final JComponent button, JComponent secondItem) {
      JPanel panel = new JPanel();
      panel.setLayout(new GridBagLayout());
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = 0;
      gbc.anchor = GridBagConstraints.BASELINE_LEADING;
      if (button != null && button instanceof JRadioButton) {
        ((AbstractButton) button).setSelected(false);
        panel.add(button, gbc);
      } else if (button != null && button instanceof JComboBox){
        panel.add(button, gbc);
      }
      if (secondItem != null) {
        gbc.gridx = 1;
        gbc.insets = new Insets(0, SPACE_BETWEEN_ROW_ITEMS, 0, 0);
        gbc.weightx = 1;
        panel.add(secondItem, gbc);
      }
      panel.setName("multiItemRow");
    return panel;
  }
}
TOP

Related Classes of gov.nasa.arc.mct.fastplot.settings.controls.PlotSettingsAxisGroup$ManualTimeEntryArea

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.