/* * SettingsPanel.java * * Copyright (C) 2003 Robert McKinnon * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package net.sf.delineate.gui; import net.sf.delineate.command.Command; import net.sf.delineate.command.Parameter; import net.sf.delineate.utility.FileUtilities; import net.sf.delineate.utility.GuiUtilities; import net.sf.delineate.utility.XPathTool; import net.sf.delineate.utility.SettingUtilities; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.SpinnerNumberModel; import javax.swing.SpringLayout; import javax.swing.SpringUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.xml.xpath.XPathExpressionException; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * Controls user defined settings. * @author robmckinnon@users.sourceforge.net */ public class SettingsPanel implements RenderingListener { private static final String INPUT_FILE_ACTION = "InputFileAction"; private static final String OUTPUT_FILE_ACTION = "OutputFileAction"; private static final String BACKGROUND_COLOR_ACTION = "BackgroundColorAction"; private final Map textFieldMap = new HashMap(5); private final Map fileSizeLabelMap = new HashMap(5); private final Map checkBoxMap = new HashMap(23); private final Map spinnerSliderMap = new HashMap(23); private final JPanel panel; private Command command; private JFileChooser tracingAppFileChooser; private ColorEditor colorEditor; private final ChangeListener changeListener = new ChangeListener() { public void stateChanged(ChangeEvent e) { Object source = e.getSource(); if(source instanceof SpinnerSlider) { SpinnerSlider spinnerSlider = (SpinnerSlider)source; command.setParameterValue(spinnerSlider.getName(), spinnerSlider.getValueAsString(), false); } else { JCheckBox checkBox = (JCheckBox)e.getSource(); command.setParameterEnabled(checkBox.getName(), checkBox.isSelected(), false); } } }; private final KeyAdapter textFieldKeyListener = new KeyAdapter() { public void keyReleased(KeyEvent e) { JTextField textField = ((JTextField)e.getSource()); command.setParameterValue(textField.getName(), textField.getText(), false); setFileSizeText(textField.getName(), textField.getText()); } }; private static final String SETTINGS_FILE_NAME = "settings.prop"; public SettingsPanel(XPathTool xpathTool) throws Exception { panel = new JPanel(new BorderLayout()); panel.setBorder(BorderFactory.createTitledBorder("Conversion settings")); panel.add(initContentPane(xpathTool), BorderLayout.NORTH); SaveSettingsPanel saveSettingsPanel = new SaveSettingsPanel(command); panel.add(saveSettingsPanel.getPanel(), BorderLayout.SOUTH); } public void renderingCompleted() { updateFileSize(); } public JPanel getPanel() { return panel; } public String getCommand() { return command.getCommand(); } public void setHeight(double height) { command.setParameterValue("height", Double.toString(height), false); } public void setWidth(double width) { command.setParameterValue("width", Double.toString(width), false); } public String getBackgroundColor() { if(command.getParameterEnabled(Command.BACKGROUND_COLOR_PARAMETER)) { return command.getParameterValue(Command.BACKGROUND_COLOR_PARAMETER); } else { return null; } } public File getInputFile() { String inputFile = command.getParameterValue(Command.INPUT_FILE_PARAMETER); return new File(inputFile); } public void setInputFile(File file) { command.setParameterValue(Command.INPUT_FILE_PARAMETER, file.getPath(), true); } public String getOutputFile() { return command.getParameterValue(Command.OUTPUT_FILE_PARAMETER); } public void selectInputTextField() { JTextField textField = getTextField(Command.INPUT_FILE_PARAMETER); textField.selectAll(); textField.requestFocus(); } public void updateFileSize() { String file = command.getParameterValue(Command.OUTPUT_FILE_PARAMETER); setFileSizeText(Command.OUTPUT_FILE_PARAMETER, file); } private JPanel initContentPane(XPathTool xpathTool) throws XPathExpressionException { final JPanel panel = new JPanel(new BorderLayout()); panel.setLayout(new SpringLayout()); String commandName = xpathTool.string("/parameters/command/name"); String optionIndicator = xpathTool.string("/parameters/command/option-indicator"); int descriptionCount = xpathTool.count("/parameters/parameter/description"); int parameterCount = xpathTool.count("/parameters/parameter"); command = new Command(commandName, optionIndicator, parameterCount, new Command.CommandChangeListener() { public void enabledChanged(Parameter parameter) { String name = parameter.getName(); JCheckBox checkBox = (JCheckBox)checkBoxMap.get(name); if(checkBox != null) checkBox.setSelected(parameter.isEnabled()); } public void valueChanged(Parameter parameter) { String name = parameter.getName(); if(name.equals(Command.BACKGROUND_COLOR_PARAMETER)) { colorEditor.setColor(parameter.getValue()); } else { JTextField textField = (JTextField)textFieldMap.get(name); if(textField != null) { String path = parameter.getValue(); textField.setText(path); } SpinnerSlider spinnerSlider = (SpinnerSlider)spinnerSliderMap.get(name); if(spinnerSlider != null) { spinnerSlider.setValue(parameter.getValue()); } } } }); loadTracingApplicationPath(panel); for(int type = 0; type < 3; type++) { for(int i = 0; i < parameterCount; i++) { String xpathPrefix = "/parameters/parameter[" + (i + 1) + "]/"; xpathTool.setXpathPrefix(xpathPrefix); String name = xpathTool.string("name"); boolean isFileParameter = name.endsWith("file"); boolean isNumberParameter = xpathTool.count("range") == 1; switch(type) { case 0: if(isFileParameter) addParameter(panel, xpathTool, xpathPrefix, name); break; case 1: if(!isFileParameter && !isNumberParameter) addParameter(panel, xpathTool, xpathPrefix, name); break; case 2: if(!isFileParameter && isNumberParameter) addParameter(panel, xpathTool, xpathPrefix, name); break; } } } SpringUtilities.makeCompactGrid(panel, descriptionCount, 2, 6, 6, 6, 6); return panel; } private void loadTracingApplicationPath(final JPanel parent) { Properties properties = SettingUtilities.loadProperties(SETTINGS_FILE_NAME, parent); String commandPath = properties.getProperty(command.getCommandName()); if(commandPath != null) { command.setTracingApplication(commandPath); } } public void showTracingApplicationSelectionDialog() { if(tracingAppFileChooser == null) { String dialogTitle = "Select location of " + command.getCommandName(); this.tracingAppFileChooser = initFileChooser(dialogTitle); } int response = tracingAppFileChooser.showOpenDialog(panel); if(response == JFileChooser.APPROVE_OPTION) { File file = tracingAppFileChooser.getSelectedFile(); String commandPath = file.getPath(); command.setTracingApplication(commandPath); Properties properties = SettingUtilities.loadProperties(SETTINGS_FILE_NAME, panel); properties.setProperty(command.getCommandName(), commandPath); SettingUtilities.saveProperties(properties, SETTINGS_FILE_NAME, "Delineate tracing application settings - http//delineate.sourceforge.net"); } } private JFileChooser initFileChooser(String dialogTitle) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setApproveButtonText("Select"); fileChooser.setApproveButtonToolTipText("Select file"); fileChooser.setDialogTitle(dialogTitle); return fileChooser; } private void addParameter(JPanel panel, XPathTool xpath, String xpathPrefix, String name) throws XPathExpressionException { boolean optional = xpath.toBoolean("optional"); boolean enabled = !optional || xpath.toBoolean("enabled"); String value = xpath.string("default"); String desc = xpath.string("description"); String function = xpath.string("function"); command.addParameter(name, enabled, value, function); if(desc.length() == 0) { return; } JComponent labelPanel; JComponent controlComponent; if(xpath.count("range") != 1) { labelPanel = initLabelPanel(optional, enabled, null, desc, name, function); controlComponent = initControlComponent(name, value, enabled, null); } else { xpath.setXpathPrefix(xpathPrefix + "range/"); boolean useWholeNumbers = xpath.toBoolean("use-whole-numbers"); String stepString = xpath.string("step").trim(); SpinnerNumberModel model = initSpinnerModel(useWholeNumbers, xpath, value); SpinnerSlider spinnerSlider = initSpinnerSlider(model, name, enabled, desc, useWholeNumbers, stepString); labelPanel = initLabelPanel(optional, enabled, spinnerSlider, desc, name, function); controlComponent = initControlPanel(spinnerSlider); } panel.add(labelPanel); panel.add(controlComponent); } private JComponent initControlComponent(String name, String value, boolean enabled, String function) { if(value.length() > 0) { if(name.equals(Command.BACKGROUND_COLOR_PARAMETER)) { colorEditor = new ColorEditor(command, value, panel, enabled); return colorEditor.getColorCombo(); } else { setFileSizeText(name, value); JTextField textField = new JTextField(value); textField.setName(name); textField.setColumns(15); textField.addKeyListener(textFieldKeyListener); if(function != null) { textFieldMap.put(function, textField); } textFieldMap.put(name, textField); return textField; } } else { return new JLabel(""); } } private JPanel initControlPanel(SpinnerSlider spinnerSlider) { JPanel controlPanel = new JPanel(new BorderLayout(0,0)); JSpinner spinner = spinnerSlider.getSpinner(); Dimension size = new Dimension(53, (int)spinner.getPreferredSize().getHeight()); spinner.setPreferredSize(size); controlPanel.add(spinner, BorderLayout.WEST); controlPanel.add(spinnerSlider.getSlider(), BorderLayout.EAST); return controlPanel; } private SpinnerSlider initSpinnerSlider(SpinnerNumberModel model, String name, boolean enabled, String desc, boolean useWholeNumbers, String stepString) { SpinnerSlider spinnerSlider = new SpinnerSlider(model); spinnerSlider.setName(name); spinnerSlider.setEnabled(enabled); spinnerSlider.setTooltipText(desc); spinnerSlider.addChangeListener(changeListener); spinnerSliderMap.put(name, spinnerSlider); if(!useWholeNumbers) { int fractionalDigits = stepString.substring(stepString.indexOf('.') + 1).length(); spinnerSlider.setFractionDigitsLength(fractionalDigits); } return spinnerSlider; } private JPanel initLabelPanel(boolean optional, boolean enabled, final SpinnerSlider spinnerSlider, String desc, final String name, String function) { String labelName = name.replace('-', ' '); boolean isFileParameter = function.equals(Command.INPUT_FILE_PARAMETER) || function.equals(Command.OUTPUT_FILE_PARAMETER); boolean isBgColorParameter = name.equals(Command.BACKGROUND_COLOR_PARAMETER); final JPanel panel = new JPanel(new BorderLayout()); Component labelComponent = null; JButton button = null; if(!isFileParameter && !isBgColorParameter) { JLabel label = new JLabel(labelName); label.setToolTipText(desc); labelComponent = label; } else if(isBgColorParameter) { button = initColorChooserButton(labelName, enabled); labelComponent = button; } else if(isFileParameter) { labelComponent = initFileChooserButton(name, labelName, function); } panel.add(labelComponent, BorderLayout.WEST); if(optional) { JCheckBox checkBox = initCheckbox(name, desc, enabled, spinnerSlider, button); panel.add(checkBox, BorderLayout.EAST); } else if(isFileParameter) { JLabel label = new JLabel(); fileSizeLabelMap.put(function, label); panel.add(label, BorderLayout.EAST); } return panel; } private JButton initColorChooserButton(String labelName, boolean enabled) { AbstractAction action = new AbstractAction() { public void actionPerformed(ActionEvent e) { colorEditor.chooseColor(); } }; JButton button = GuiUtilities.initButton(labelName, BACKGROUND_COLOR_ACTION, KeyEvent.VK_B, panel, action); button.setToolTipText("Choose color"); button.setEnabled(enabled); return button; } private JButton initFileChooserButton(final String name, final String labelName, String function) { final String prompt = function.equals(Command.INPUT_FILE_PARAMETER) ? "Select " : "Name "; AbstractAction action = new AbstractAction() { JFileChooser fileChooser = initFileChooser(prompt + labelName); public void actionPerformed(ActionEvent e) { int response = fileChooser.showOpenDialog((JComponent)e.getSource()); if(response == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); JTextField textField = getTextField(name); textField.setText(file.getPath()); setFileSizeText(name, file.getPath()); command.setParameterValue(textField.getName(), textField.getText(), false); } } }; JButton button = null; if(function.equals(Command.INPUT_FILE_PARAMETER)) { button = GuiUtilities.initButton(labelName, INPUT_FILE_ACTION, KeyEvent.VK_I, panel, action); } else if(function.equals(Command.OUTPUT_FILE_PARAMETER)) { button = GuiUtilities.initButton(labelName, OUTPUT_FILE_ACTION, KeyEvent.VK_O, panel, action); } button.setToolTipText("Browse files"); return button; } private void setFileSizeText(final String name, String filePath) { JLabel label = (JLabel)fileSizeLabelMap.get(name); if(label != null) { File file = FileUtilities.getFile(filePath); String fileSize = FileUtilities.getFileSize(file); label.setText(fileSize); } } private JCheckBox initCheckbox(final String name, String desc, boolean enabled, final SpinnerSlider spinnerSlider, final JButton button) { final JCheckBox checkBox = new JCheckBox("", false); checkBoxMap.put(name, checkBox); checkBox.setName(name); checkBox.setToolTipText(desc); checkBox.setSelected(enabled); checkBox.setFocusPainted(true); if(spinnerSlider != null) { checkBox.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { spinnerSlider.setEnabled(checkBox.isSelected()); } }); } else if(name.equals(Command.BACKGROUND_COLOR_PARAMETER)) { checkBox.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JComboBox combo = colorEditor.getColorCombo(); combo.setEnabled(checkBox.isSelected()); button.setEnabled(checkBox.isSelected()); } }); } checkBox.addChangeListener(changeListener); return checkBox; } private JTextField getTextField(String key) { return (JTextField)textFieldMap.get(key); } private SpinnerNumberModel initSpinnerModel(boolean useWholeNumbers, XPathTool xpath, String defaultValue) throws XPathExpressionException { SpinnerNumberModel model; if(useWholeNumbers) { int value = Integer.parseInt(defaultValue); int min = xpath.toInt("min"); int max = xpath.toInt("max"); int step = xpath.toInt("step"); model = new SpinnerNumberModel(value, min, max, step); } else { double value = Double.parseDouble(defaultValue); double min = xpath.toDouble("min"); double max = xpath.toDouble("max"); double step = xpath.toDouble("step"); model = new SpinnerNumberModel(value, min, max, step); } return model; } public void setColors(Color[] colors) { if(colorEditor != null && colors != null) { colorEditor.setColors(colors); } } public boolean getCenterlineEnabled() { return command.getParameterEnabled(Command.CENTERLINE_PARAMETER); } public String[] getCommandAsArray() { return command.getCommandAsArray(); } public String getCommandName() { return command.getCommandName(); } }