package gov.nasa.arc.mct.fastplot.settings; import gov.nasa.arc.mct.fastplot.bridge.PlotConstants.AxisBounds; import gov.nasa.arc.mct.fastplot.bridge.PlotConstants.AxisType; import gov.nasa.arc.mct.fastplot.bridge.PlotConstants.NonTimeAxisSubsequentBoundsSetting; import gov.nasa.arc.mct.fastplot.bridge.PlotConstants.TimeAxisSubsequentBoundsSetting; import gov.nasa.arc.mct.fastplot.settings.controls.PlotSettingsCheckBox; import java.awt.Color; import java.awt.Component; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.text.NumberFormat; import java.util.ResourceBundle; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JFormattedTextField; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.border.LineBorder; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.DocumentFilter; import javax.swing.text.InternationalFormatter; public class PlotBehaviorPanel extends PlotSettingsPanel { private static final long serialVersionUID = 3317532599862428211L; // Access bundle file where externalized strings are defined. private static final ResourceBundle BUNDLE = ResourceBundle.getBundle("gov.nasa.arc.mct.fastplot.view.Bundle"); private static final int BEHAVIOR_CELLS_X_PADDING = 18; private static final int INDENTATION_SEMI_FIXED_CHECKBOX = 16; private static final int NONTIME_TITLE_SPACING = 0; private static final int PADDING_COLUMNS = 3; /* * Plot Behavior panel controls */ private JRadioButton nonTimeMinAutoAdjustMode; private JRadioButton nonTimeMaxAutoAdjustMode; private JRadioButton nonTimeMinFixedMode; private JRadioButton nonTimeMaxFixedMode; private JCheckBox nonTimeMinSemiFixedMode; private JCheckBox nonTimeMaxSemiFixedMode; private JTextField nonTimeMinPadding; private JTextField nonTimeMaxPadding; private PlotSettingsCheckBox pinTimeAxis; private JRadioButton timeJumpMode; private JRadioButton timeScrunchMode; private JTextField timeJumpPadding; private JTextField timeScrunchPadding; private JLabel behaviorTimeAxisLetter; private JLabel behaviorNonTimeAxisLetter; public PlotBehaviorPanel() { setLayout(new GridBagLayout()); JPanel modePanel = new JPanel(new GridLayout(1, 1)); JButton bMode = new JButton(BUNDLE.getString("Mode.label")); bMode.setAlignmentY(CENTER_ALIGNMENT); modePanel.add(bMode); JPanel minPanel = new JPanel(new GridLayout(1, 1)); JLabel bMin = new JLabel(BUNDLE.getString("Min.label")); bMin.setHorizontalAlignment(JLabel.CENTER); minPanel.add(bMin); JPanel maxPanel = new JPanel(new GridLayout(1, 1)); maxPanel.add(new JLabel(BUNDLE.getString("Max.label"))); GridLinedPanel timeAxisPanel = createGriddedTimeAxisPanel(); GridLinedPanel nonTimeAxisPanel = createGriddedNonTimeAxisPanel(); behaviorTimeAxisLetter = new JLabel("_"); JPanel behaviorTimeTitlePanel = new JPanel(); behaviorTimeTitlePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, NONTIME_TITLE_SPACING)); behaviorTimeTitlePanel.add(new JLabel(BUNDLE.getString("TimeAxis.label") + " (")); behaviorTimeTitlePanel.add(behaviorTimeAxisLetter); behaviorTimeTitlePanel.add(new JLabel("):")); pinTimeAxis = new PlotSettingsCheckBox(BUNDLE.getString("PinTimeAxis.label")) { private static final long serialVersionUID = 4533604843417685876L; @Override public boolean getFrom(PlotConfiguration settings) { return settings.getPinTimeAxis(); } @Override public void populate(PlotConfiguration settings) { settings.setPinTimeAxis(isSelected()); } }; behaviorTimeTitlePanel.add(pinTimeAxis); addSubPanel(pinTimeAxis); behaviorNonTimeAxisLetter = new JLabel("_"); JPanel behaviorNonTimeTitlePanel = new JPanel(); behaviorNonTimeTitlePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, NONTIME_TITLE_SPACING)); behaviorNonTimeTitlePanel.add(new JLabel(BUNDLE.getString("NonTimeAxis.label") + " (")); behaviorNonTimeTitlePanel.add(behaviorNonTimeAxisLetter); behaviorNonTimeTitlePanel.add(new JLabel("):")); GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 0; gbc.gridy = 0; gbc.insets = new Insets(6, 0, 0, 0); add(behaviorTimeTitlePanel, gbc); gbc.gridy++; gbc.insets = new Insets(0, 0, 0, 0); add(timeAxisPanel, gbc); gbc.gridy++; gbc.insets = new Insets(6, 0, 0, 0); add(behaviorNonTimeTitlePanel, gbc); gbc.gridy++; gbc.insets = new Insets(0, 0, 0, 0); add(nonTimeAxisPanel, gbc); // Listen nonTimeMinAutoAdjustMode.addActionListener(this); nonTimeMaxAutoAdjustMode.addActionListener(this); nonTimeMinFixedMode.addActionListener(this); nonTimeMaxFixedMode.addActionListener(this); nonTimeMinSemiFixedMode.addActionListener(this); nonTimeMaxSemiFixedMode.addActionListener(this); nonTimeMinPadding.addActionListener(this); nonTimeMaxPadding.addActionListener(this); timeJumpMode.addActionListener(this); timeScrunchMode.addActionListener(this); timeJumpPadding.addActionListener(this); timeScrunchPadding.addActionListener(this); timeJumpPadding.addFocusListener(focusActivator); timeScrunchPadding.addFocusListener(focusActivator); nonTimeMinPadding.addFocusListener(focusActivator); nonTimeMaxPadding.addFocusListener(focusActivator); nonTimeMinPadding.getDocument().addDocumentListener(documentListener); // Apply needs to disable if min+max>99, nonTimeMaxPadding.getDocument().addDocumentListener(documentListener); // so listen to all changes to both // Instrument setName("plotBehavior"); modePanel.setName("modePanel"); bMode.setName("bMode"); minPanel.setName("minPanel"); bMin.setName("bMin"); maxPanel.setName("maxPanel"); timeAxisPanel.setName("timeAxisPanel"); nonTimeAxisPanel.setName("nonTimeAxisPanel"); behaviorTimeAxisLetter.setName("behaviorTimeAxisLetter"); behaviorNonTimeAxisLetter.setName("behaviorNonTimeAxisLetter"); } /* (non-Javadoc) * @see gov.nasa.arc.mct.fastplot.settings.PlotSettingsPanel#populate(gov.nasa.arc.mct.fastplot.settings.PlotConfiguration) */ @Override public void populate(PlotConfiguration settings) { super.populate(settings); // TODO: Break other parts down into PlotSettingsSubPanels, too settings.setNonTimeMinPadding(Double.parseDouble(nonTimeMinPadding.getText()) / 100d); settings.setNonTimeMaxPadding(Double.parseDouble(nonTimeMaxPadding.getText()) / 100d); if (timeJumpMode.isSelected()) { settings.setTimePadding(Double.parseDouble(timeJumpPadding.getText()) / 100d); settings.setTimeAxisSubsequentSetting(TimeAxisSubsequentBoundsSetting.JUMP); } else if (timeScrunchMode.isSelected()) { settings.setTimePadding(Double.parseDouble(timeScrunchPadding.getText()) / 100d); settings.setTimeAxisSubsequentSetting(TimeAxisSubsequentBoundsSetting.SCRUNCH); } if (nonTimeMinSemiFixedMode.isSelected()) { settings.setNonTimeAxisSubsequentMinSetting(NonTimeAxisSubsequentBoundsSetting.SEMI_FIXED); } else if (nonTimeMinFixedMode.isSelected()) { settings.setNonTimeAxisSubsequentMinSetting(NonTimeAxisSubsequentBoundsSetting.FIXED); } else if (nonTimeMinAutoAdjustMode.isSelected()) { settings.setNonTimeAxisSubsequentMinSetting(NonTimeAxisSubsequentBoundsSetting.AUTO); } if (nonTimeMaxSemiFixedMode.isSelected()) { settings.setNonTimeAxisSubsequentMaxSetting(NonTimeAxisSubsequentBoundsSetting.SEMI_FIXED); } else if (nonTimeMaxFixedMode.isSelected()) { settings.setNonTimeAxisSubsequentMaxSetting(NonTimeAxisSubsequentBoundsSetting.FIXED); } else if (nonTimeMaxAutoAdjustMode.isSelected()) { settings.setNonTimeAxisSubsequentMaxSetting(NonTimeAxisSubsequentBoundsSetting.AUTO); } } private JToggleButton cachedTimeMode; private JToggleButton cachedNonTimeMin; private JToggleButton cachedNonTimeMax; private double cachedTimePadding; private double cachedNonTimeMinPadding; private double cachedNonTimeMaxPadding; /* (non-Javadoc) * @see gov.nasa.arc.mct.fastplot.settings.PlotSettingsPanel#reset(gov.nasa.arc.mct.fastplot.settings.PlotConfiguration, boolean) */ @Override public void reset(PlotConfiguration settings, boolean hard) { super.reset(settings, hard); switch (settings.getAxisOrientationSetting()) { case X_AXIS_AS_TIME: behaviorTimeAxisLetter.setText("x"); behaviorNonTimeAxisLetter.setText("y"); break; case Y_AXIS_AS_TIME: behaviorTimeAxisLetter.setText("y"); behaviorNonTimeAxisLetter.setText("x"); break; case Z_AXIS_AS_TIME: behaviorTimeAxisLetter.setText("z"); behaviorNonTimeAxisLetter.setText("x/y"); } if (hard) { switch(settings.getTimeAxisSubsequentSetting()) { case JUMP: timeJumpMode .setSelected(true); break; case SCRUNCH: timeScrunchMode.setSelected(true); break; } switch(settings.getNonTimeAxisSubsequentMinSetting()) { case AUTO: nonTimeMinAutoAdjustMode.setSelected(true); nonTimeMinSemiFixedMode.setSelected(false); nonTimeMinSemiFixedMode.setEnabled(false); break; case FIXED: nonTimeMinFixedMode.setSelected(true); nonTimeMinSemiFixedMode.setSelected(false); nonTimeMinSemiFixedMode.setEnabled(true); break; case SEMI_FIXED: nonTimeMinFixedMode.setSelected(true); nonTimeMinSemiFixedMode.setSelected(true); nonTimeMinSemiFixedMode.setEnabled(true); break; } switch(settings.getNonTimeAxisSubsequentMaxSetting()) { case AUTO: nonTimeMaxAutoAdjustMode.setSelected(true); nonTimeMaxSemiFixedMode.setSelected(false); nonTimeMaxSemiFixedMode.setEnabled(false); break; case FIXED: nonTimeMaxFixedMode.setSelected(true); nonTimeMaxSemiFixedMode.setSelected(false); nonTimeMaxSemiFixedMode.setEnabled(true); break; case SEMI_FIXED: nonTimeMaxFixedMode.setSelected(true); nonTimeMaxSemiFixedMode.setSelected(true); nonTimeMaxSemiFixedMode.setEnabled(true); break; } timeJumpPadding.setText(String.valueOf((int) (settings.getTimePadding() * 100))); timeScrunchPadding.setText(String.valueOf((int) (settings.getTimePadding() * 100))); nonTimeMinPadding.setText(String.valueOf((int) (settings.getNonTimeMinPadding() * 100))); nonTimeMaxPadding.setText(String.valueOf((int) (settings.getNonTimeMaxPadding() * 100))); cacheState(); } } /* (non-Javadoc) * @see gov.nasa.arc.mct.fastplot.settings.PlotSettingsPanel#isDirty() */ @Override public boolean isDirty() { return super.isDirty() || cachedTimeMode != findSelection(timeJumpMode, timeScrunchMode) || cachedNonTimeMin != findSelection(nonTimeMinAutoAdjustMode, nonTimeMinSemiFixedMode, nonTimeMinFixedMode) || cachedNonTimeMax != findSelection(nonTimeMaxAutoAdjustMode, nonTimeMaxSemiFixedMode, nonTimeMaxFixedMode) || cachedTimePadding != Double.parseDouble( ((cachedTimeMode == timeJumpMode) ? timeJumpPadding : timeScrunchPadding).getText() ) || cachedNonTimeMinPadding != Double.parseDouble(nonTimeMinPadding.getText()) || cachedNonTimeMaxPadding != Double.parseDouble(nonTimeMaxPadding.getText()); } private void cacheState() { cachedTimeMode = findSelection(timeJumpMode, timeScrunchMode); cachedNonTimeMin = findSelection(nonTimeMinAutoAdjustMode, nonTimeMinSemiFixedMode, nonTimeMinFixedMode); cachedNonTimeMax = findSelection(nonTimeMaxAutoAdjustMode, nonTimeMaxSemiFixedMode, nonTimeMaxFixedMode); cachedTimePadding = Double.parseDouble( ((cachedTimeMode == timeJumpMode) ? timeJumpPadding : timeScrunchPadding).getText() ); cachedNonTimeMinPadding = Double.parseDouble(nonTimeMinPadding.getText()); cachedNonTimeMaxPadding = Double.parseDouble(nonTimeMaxPadding.getText()); } private JToggleButton findSelection (JToggleButton... buttons) { for (JToggleButton b : buttons) if (b.isSelected()) return b; return null; // TODO: Assert something here? } // The Time Axis table within the Plot Behavior area private GridLinedPanel createGriddedTimeAxisPanel() { JLabel titleMode = new JLabel(BUNDLE.getString("Mode.label")); JLabel titleMin = new JLabel(BUNDLE.getString("Min.label")); JLabel titleMinPadding = new JLabel(BUNDLE.getString("Min.label")); JLabel titleMax = new JLabel(BUNDLE.getString("Max.label")); JLabel titleMaxPadding = new JLabel(BUNDLE.getString("Max.label")); JLabel titleSpan = new JLabel(BUNDLE.getString("Span.label")); JLabel titleMax_Min = new JLabel("(" + BUNDLE.getString("MaxMinusMin.label") +")"); JPanel titlePanelSpan = new JPanel(); titlePanelSpan.setLayout(new BoxLayout(titlePanelSpan, BoxLayout.Y_AXIS)); titlePanelSpan.add(titleSpan); titlePanelSpan.add(titleMax_Min); titleSpan.setAlignmentX(Component.CENTER_ALIGNMENT); titleMax_Min.setAlignmentX(Component.CENTER_ALIGNMENT); JLabel titlePaddingOnRedraw = new JLabel(BUNDLE.getString("PaddingOnRedraw.label")); setFontToBold(titleMode); setFontToBold(titleMin); setFontToBold(titleMax); setFontToBold(titleMinPadding); setFontToBold(titleMaxPadding); setFontToBold(titlePaddingOnRedraw); setFontToBold(titleSpan); setFontToBold(titleMax_Min); timeJumpMode = new JRadioButton(BUNDLE.getString("Jump.label")); timeScrunchMode = new JRadioButton(BUNDLE.getString("Scrunch.label")); JPanel timeJumpModePanel = new JPanel(); timeJumpModePanel.add(timeJumpMode); JPanel timeScrunchModePanel = new JPanel(); timeScrunchModePanel.add(timeScrunchMode); ButtonGroup modeGroup = new ButtonGroup(); modeGroup.add(timeJumpMode); modeGroup.add(timeScrunchMode); timeJumpMode.setSelected(true); timeJumpPadding = createPaddingTextField(AxisType.TIME_IN_JUMP_MODE, AxisBounds.MAX); timeScrunchPadding = createPaddingTextField(AxisType.TIME_IN_SCRUNCH_MODE, AxisBounds.MAX); timeJumpPadding.addFocusListener(new FocusBasedSelector(timeJumpMode)); timeScrunchPadding.addFocusListener(new FocusBasedSelector(timeScrunchMode)); JPanel timeJumpPaddingPanel = new JPanel(); timeJumpPaddingPanel.add(timeJumpPadding); timeJumpPaddingPanel.add(new JLabel(BUNDLE.getString("Percent.label"))); JPanel timeScrunchPaddingPanel = new JPanel(); timeScrunchPaddingPanel.add(timeScrunchPadding); timeScrunchPaddingPanel.add(new JLabel(BUNDLE.getString("Percent.label"))); GridLinedPanel griddedPanel = new GridLinedPanel(); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = 1; gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 1; gbc.weighty = 1; gbc.ipadx = BEHAVIOR_CELLS_X_PADDING; gbc.gridheight = 2; griddedPanel.setGBC(gbc); // Title row A int row = 0; griddedPanel.addCell(titleMode, 0, row); griddedPanel.addCell(titleMin, 1, row); griddedPanel.addCell(titleMax, 2, row); gbc.gridheight = 2; griddedPanel.addCell(titlePanelSpan, 3, row); gbc.gridheight = 1; gbc.gridwidth = 2; griddedPanel.addCell(titlePaddingOnRedraw, 4, row); gbc.gridwidth = 1; // Title row B - only two entries row++; griddedPanel.addCell(titleMinPadding, 4, row); griddedPanel.addCell(titleMaxPadding, 5, row); // Row 1 row++; griddedPanel.addCell(timeJumpModePanel, 0, row, GridBagConstraints.WEST); griddedPanel.addCell(new JLabel(BUNDLE.getString("AutoAdjusts.label")), 1, row); griddedPanel.addCell(new JLabel(BUNDLE.getString("AutoAdjusts.label")), 2, row); griddedPanel.addCell(new JLabel(BUNDLE.getString("Fixed.label")), 3, row); griddedPanel.addCell(new JLabel(BUNDLE.getString("Dash.label")), 4, row); griddedPanel.addCell(timeJumpPaddingPanel, 5, row); // Row 2 row++; griddedPanel.addCell(timeScrunchModePanel, 0, row, GridBagConstraints.WEST); griddedPanel.addCell(new JLabel(BUNDLE.getString("Fixed.label")), 1, row); griddedPanel.addCell(new JLabel(BUNDLE.getString("AutoAdjusts.label")), 2, row); griddedPanel.addCell(new JLabel(BUNDLE.getString("AutoAdjusts.label")), 3, row); griddedPanel.addCell(new JLabel(BUNDLE.getString("Dash.label")), 4, row); griddedPanel.addCell(timeScrunchPaddingPanel, 5, row); return griddedPanel; } // The Non-Time Axis table within the Plot Behavior panel private GridLinedPanel createGriddedNonTimeAxisPanel() { JLabel titleMin = new JLabel(BUNDLE.getString("Min.label")); JLabel titleMax = new JLabel(BUNDLE.getString("Max.label")); JLabel titlePadding = new JLabel(BUNDLE.getString("Padding.label")); JLabel titleMinPadding = new JLabel(BUNDLE.getString("Min.label")); JLabel titleMaxPadding = new JLabel(BUNDLE.getString("Max.label")); setFontToBold(titleMin); setFontToBold(titleMax); setFontToBold(titlePadding); setFontToBold(titleMinPadding); setFontToBold(titleMaxPadding); nonTimeMinAutoAdjustMode = new JRadioButton(BUNDLE.getString("AutoAdjusts.label")); nonTimeMaxAutoAdjustMode = new JRadioButton(BUNDLE.getString("AutoAdjusts.label")); nonTimeMinFixedMode = new JRadioButton(BUNDLE.getString("Fixed.label")); nonTimeMaxFixedMode = new JRadioButton(BUNDLE.getString("Fixed.label")); JPanel nonTimeMinAutoAdjustModePanel = new JPanel(); nonTimeMinAutoAdjustModePanel.add(nonTimeMinAutoAdjustMode); JPanel nonTimeMaxAutoAdjustModePanel = new JPanel(); nonTimeMaxAutoAdjustModePanel.add(nonTimeMaxAutoAdjustMode); JPanel nonTimeMinFixedModePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0)); nonTimeMinFixedModePanel.add(nonTimeMinFixedMode); JPanel nonTimeMaxFixedModePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0)); nonTimeMaxFixedModePanel.add(nonTimeMaxFixedMode); nonTimeMinAutoAdjustMode.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { nonTimeMinSemiFixedMode.setEnabled(false); nonTimeMinSemiFixedMode.setSelected(false); } }); nonTimeMinFixedMode.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if(nonTimeMinFixedMode.isSelected()) { nonTimeMinSemiFixedMode.setEnabled(true); } else { nonTimeMinSemiFixedMode.setEnabled(false); nonTimeMinSemiFixedMode.setSelected(false); } } }); nonTimeMaxAutoAdjustMode.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { nonTimeMaxSemiFixedMode.setEnabled(false); nonTimeMaxSemiFixedMode.setSelected(false); } }); nonTimeMaxFixedMode.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if(nonTimeMaxFixedMode.isSelected()) { nonTimeMaxSemiFixedMode.setEnabled(true); } else { nonTimeMaxSemiFixedMode.setEnabled(false); nonTimeMaxSemiFixedMode.setSelected(false); } } }); nonTimeMinAutoAdjustMode.setSelected(true); nonTimeMaxAutoAdjustMode.setSelected(true); ButtonGroup minGroup = new ButtonGroup(); minGroup.add(nonTimeMinAutoAdjustMode); minGroup.add(nonTimeMinFixedMode); ButtonGroup maxGroup = new ButtonGroup(); maxGroup.add(nonTimeMaxAutoAdjustMode); maxGroup.add(nonTimeMaxFixedMode); nonTimeMinSemiFixedMode = new JCheckBox(BUNDLE.getString("SemiFixed.label")); nonTimeMaxSemiFixedMode = new JCheckBox(BUNDLE.getString("SemiFixed.label")); JPanel nonTimeMinSemiFixedModePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 2)); JPanel nonTimeMaxSemiFixedModePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 2)); nonTimeMinSemiFixedModePanel.add(nonTimeMinSemiFixedMode); nonTimeMaxSemiFixedModePanel.add(nonTimeMaxSemiFixedMode); nonTimeMinSemiFixedMode.setEnabled(false); nonTimeMaxSemiFixedMode.setEnabled(false); nonTimeMinPadding = createPaddingTextField(AxisType.NON_TIME, AxisBounds.MIN); nonTimeMaxPadding = createPaddingTextField(AxisType.NON_TIME, AxisBounds.MAX); JPanel nonTimeMinPaddingPanel = new JPanel(); nonTimeMinPaddingPanel.add(nonTimeMinPadding); nonTimeMinPaddingPanel.add(new JLabel(BUNDLE.getString("Percent.label"))); JPanel nonTimeMaxPaddingPanel = new JPanel(); nonTimeMaxPaddingPanel.add(nonTimeMaxPadding); nonTimeMaxPaddingPanel.add(new JLabel(BUNDLE.getString("Percent.label"))); JPanel nonTimeMins = new JPanel(); nonTimeMins.setLayout(new GridBagLayout()); GridBagConstraints gbc0 = new GridBagConstraints(); gbc0.gridy = 0; gbc0.anchor = GridBagConstraints.WEST; nonTimeMins.add(nonTimeMinAutoAdjustModePanel, gbc0); gbc0.gridy = 1; nonTimeMins.add(nonTimeMinFixedModePanel, gbc0); gbc0.gridy = 2; gbc0.insets = new Insets(0, INDENTATION_SEMI_FIXED_CHECKBOX, 0, 0); nonTimeMins.add(nonTimeMinSemiFixedModePanel, gbc0); JPanel nonTimeMaxs = new JPanel(); nonTimeMaxs.setLayout(new GridBagLayout()); GridBagConstraints gbc1 = new GridBagConstraints(); gbc1.gridy = 0; gbc1.anchor = GridBagConstraints.WEST; nonTimeMaxs.add(nonTimeMaxAutoAdjustModePanel, gbc1); gbc1.gridy = 1; nonTimeMaxs.add(nonTimeMaxFixedModePanel, gbc1); gbc1.gridy = 2; gbc1.insets = new Insets(0, INDENTATION_SEMI_FIXED_CHECKBOX, 0, 0); nonTimeMaxs.add(nonTimeMaxSemiFixedModePanel, gbc1); GridLinedPanel griddedPanel = new GridLinedPanel(); GridBagConstraints gbc = new GridBagConstraints(); gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 1; gbc.weighty = 1; gbc.ipadx = BEHAVIOR_CELLS_X_PADDING; griddedPanel.setGBC(gbc); // Title row A int row = 0; gbc.gridwidth = 1; gbc.gridheight = 2; // First 2 titles are 2 rows high griddedPanel.addCell(titleMin, 1, row); griddedPanel.addCell(titleMax, 2, row); gbc.gridwidth = 2; // "Padding" spans 2 columns, 1 row high gbc.gridheight = 1; griddedPanel.addCell(titlePadding, 3, row); gbc.gridwidth = 1; // Title row B - only 2 cells occupied row++; griddedPanel.addCell(titleMinPadding, 3, row); griddedPanel.addCell(titleMaxPadding, 4, row); // Row 1 row++; griddedPanel.addCell(nonTimeMins, 1, row, GridBagConstraints.WEST); griddedPanel.addCell(nonTimeMaxs, 2, row, GridBagConstraints.WEST); griddedPanel.addCell(nonTimeMinPaddingPanel, 3, row); griddedPanel.addCell(nonTimeMaxPaddingPanel, 4, row); // Instrument nonTimeMins.setName("nonTimeMins"); nonTimeMaxs.setName("nonTimeMaxs"); return griddedPanel; } @SuppressWarnings("serial") private JTextField createPaddingTextField(AxisType axisType, AxisBounds bound) { final JFormattedTextField tField = new JFormattedTextField(new InternationalFormatter( NumberFormat.getIntegerInstance()) { protected DocumentFilter getDocumentFilter() { return filter; } private DocumentFilter filter = new PaddingFilter(); }); tField.setColumns(PADDING_COLUMNS); tField.setHorizontalAlignment(JTextField.RIGHT); if (bound.equals(AxisBounds.MIN)) { tField.setText(axisType.getMinimumDefaultPaddingAsText()); } else { tField.setText(axisType.getMaximumDefaultPaddingAsText()); } tField.addAncestorListener(new AncestorListener() { @Override public void ancestorAdded(AncestorEvent event) { tField.selectAll(); tField.removeAncestorListener(this); } @Override public void ancestorMoved(AncestorEvent event) { } @Override public void ancestorRemoved(AncestorEvent event) { } }); return tField; } private void setFontToBold(JLabel item) { item.setFont(item.getFont().deriveFont(Font.BOLD)); } class FocusBasedSelector implements FocusListener { private JRadioButton button; private FocusBasedSelector(JRadioButton button) { this.button = button; } @Override public void focusGained(FocusEvent arg0) { button.doClick(); } @Override public void focusLost(FocusEvent arg0) { } } private final FocusListener focusActivator = new FocusListener() { @Override public void focusGained(FocusEvent arg0) { } @Override public void focusLost(FocusEvent arg0) { Object o = arg0.getSource(); if (o instanceof JTextField) { actionPerformed(null); } } }; private final DocumentListener documentListener = new DocumentListener() { @Override public void changedUpdate(DocumentEvent arg0) { fireCallbacks(); } @Override public void insertUpdate(DocumentEvent arg0) { fireCallbacks(); } @Override public void removeUpdate(DocumentEvent arg0) { if (arg0.getDocument().getLength() > 0) fireCallbacks(); } }; /* * This filter blocks non-numeric characters from being entered in the padding fields */ class PaddingFilter extends DocumentFilter { private StringBuilder insertBuilder; private StringBuilder replaceBuilder; @Override public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { insertBuilder = new StringBuilder(string); for (int k = insertBuilder.length() - 1; k >= 0; k--) { int cp = insertBuilder.codePointAt(k); if (! Character.isDigit(cp)) { insertBuilder.deleteCharAt(k); if (Character.isSupplementaryCodePoint(cp)) { k--; insertBuilder.deleteCharAt(k); } } } if (insertBuilder.length() + fb.getDocument().getLength() < 3 && insertBuilder.length() + fb.getDocument().getLength() > 0) { super.insertString(fb, offset, insertBuilder.toString(), attr); } } @Override public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException { replaceBuilder = new StringBuilder(string); for (int k = replaceBuilder.length() - 1; k >= 0; k--) { int cp = replaceBuilder.codePointAt(k); if (! Character.isDigit(cp)) { replaceBuilder.deleteCharAt(k); if (Character.isSupplementaryCodePoint(cp)) { k--; replaceBuilder.deleteCharAt(k); } } } if ((replaceBuilder.length() - length + fb.getDocument().getLength()) < 3) { if ((replaceBuilder.length() - length + fb.getDocument().getLength()) == 0) { super.replace(fb, offset, length, "0", attr); } else { super.replace(fb, offset, length, replaceBuilder.toString(), attr); } } } @Override public void remove(FilterBypass fb, int offset, int length) throws BadLocationException { if (fb.getDocument().getLength() - length >= 1) { super.remove(fb, offset, length); } else { super.replace(fb, 0, fb.getDocument().getLength(), "0", null); } } StringBuilder getInsertBuilder() { return insertBuilder; } StringBuilder getReplaceBuilder() { return replaceBuilder; } } private static class GridLinedPanel extends JPanel { private static final long serialVersionUID = -1227455333903006294L; private GridBagConstraints wrapGbc; public GridLinedPanel() { setLayout(new GridBagLayout()); setBorder(BorderFactory.createLineBorder(Color.gray)); } void setGBC(GridBagConstraints inputGbc) { wrapGbc = inputGbc; } // Wrap each added ui control in a JPanel with a border void addCell(JLabel uiControl, int xPosition, int yPosition) { uiControl.setHorizontalAlignment(JLabel.CENTER); wrapControlInPanel(uiControl, xPosition, yPosition); } // Wrap each added ui control in a JPanel with a border void addCell(JPanel uiControl, int xPosition, int yPosition) { wrapControlInPanel(uiControl, xPosition, yPosition); } private void wrapControlInPanel(JComponent uiControl, int xPosition, int yPosition) { JPanel wrapperPanel = new JPanel(); wrapperPanel.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); wrapperPanel.add(uiControl, gbc); wrapGbc.gridx = xPosition; wrapGbc.gridy = yPosition; wrapperPanel.setBorder(new LineBorder(Color.lightGray)); add(wrapperPanel, wrapGbc); } private void addCell(JComponent uiControl, int xPosition, int yPosition, int alignment) { JPanel wrapperPanel = new JPanel(new GridBagLayout()); wrapperPanel.setBorder(new LineBorder(Color.lightGray)); GridBagConstraints gbc = new GridBagConstraints(); if (alignment == GridBagConstraints.WEST) { gbc.weightx = 1; gbc.anchor = GridBagConstraints.WEST; } wrapperPanel.add(uiControl, gbc); wrapGbc.gridx = xPosition; wrapGbc.gridy = yPosition; add(wrapperPanel, wrapGbc); } } @Override public boolean isValidated() { return Double.parseDouble(nonTimeMinPadding.getText()) + Double.parseDouble(nonTimeMaxPadding.getText()) < 100.0 && super.isValidated(); } }