// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.graphview.plugin.dialogs;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openstreetmap.josm.gui.preferences.DefaultTabPreferenceSetting;
import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
import org.openstreetmap.josm.plugins.graphview.plugin.dialogs.AccessParameterDialog.BookmarkAction;
import org.openstreetmap.josm.plugins.graphview.plugin.layer.GraphViewLayer;
import org.openstreetmap.josm.plugins.graphview.plugin.preferences.GraphViewPreferenceDefaults;
import org.openstreetmap.josm.plugins.graphview.plugin.preferences.GraphViewPreferences;
import org.openstreetmap.josm.plugins.graphview.plugin.preferences.PreferenceAccessParameters;
import org.openstreetmap.josm.tools.GBC;
public class GraphViewPreferenceEditor extends DefaultTabPreferenceSetting {
private File rulesetFolder;
private Map<String, PreferenceAccessParameters> parameterBookmarks;
private JPanel preferencePanel;
private JCheckBox internalRulesetCheckBox;
private JLabel rulesetFolderLabel;
private JTextField rulesetFolderTextField;
private JButton selectRulesetFolderButton;
private JComboBox<String> bookmarkComboBox;
private JButton editBookmarkButton;
private JButton deleteBookmarkButton;
private JCheckBox separateDirectionsCheckBox;
private JButton segmentColorButton;
private JPanel segmentColorField;
private JButton nodeColorButton;
private JPanel nodeColorField;
private JButton arrowheadFillColorButton;
private JPanel arrowheadFillColorField;
private JSlider arrowheadPlacementSlider;
private JPanel arrowPreviewPanel;
public GraphViewPreferenceEditor() {
super("graphview", tr("Graphview"),
tr("Settings for the Graphview plugin that visualizes routing graphs."));
}
@Override
public void addGui(PreferenceTabbedPane gui) {
readPreferences();
preferencePanel = gui.createPreferenceTab(this);
JPanel mainPanel = createMainPanel();
preferencePanel.add(mainPanel, GBC.eol().fill(GBC.BOTH));
updateVehiclePanel(GraphViewPreferences.getInstance().getCurrentParameterBookmarkName());
}
/**
* creates local versions of preference information
* that will only be written to real preferences if the OK button is pressed
*/
private void readPreferences() {
GraphViewPreferences preferences = GraphViewPreferences.getInstance();
rulesetFolder = preferences.getRulesetFolder();
parameterBookmarks =
new HashMap<>(preferences.getParameterBookmarks());
}
private JPanel createMainPanel() {
JPanel mainPanel = new JPanel();
GridBagLayout mainLayout = new GridBagLayout();
mainPanel.setLayout(mainLayout);
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1;
constraints.gridx = 0;
{
JPanel rulesetPanel = createRulesetPanel();
constraints.gridy = 0;
mainLayout.setConstraints(rulesetPanel, constraints);
mainPanel.add(rulesetPanel);
} {
JPanel vehiclePanel = createVehiclePanel();
constraints.gridy = 1;
mainLayout.setConstraints(vehiclePanel, constraints);
mainPanel.add(vehiclePanel);
} {
JPanel visualizationPanel = createVisualizationPanel();
constraints.gridy = 2;
mainLayout.setConstraints(visualizationPanel, constraints);
mainPanel.add(visualizationPanel);
}
mainPanel.add(GBC.glue(0, 0));
return mainPanel;
}
private JPanel createRulesetPanel() {
JPanel rulesetPanel = new JPanel();
rulesetPanel.setBorder(BorderFactory.createTitledBorder(tr("Ruleset")));
rulesetPanel.setLayout(new BoxLayout(rulesetPanel, BoxLayout.Y_AXIS));
internalRulesetCheckBox = new JCheckBox(tr("Use built-in rulesets"));
internalRulesetCheckBox.setSelected(GraphViewPreferences.getInstance().getUseInternalRulesets());
internalRulesetCheckBox.addActionListener(internalRulesetActionListener);
rulesetPanel.add(internalRulesetCheckBox);
rulesetFolderLabel = new JLabel(tr("External ruleset directory:"));
rulesetPanel.add(rulesetFolderLabel);
rulesetFolderTextField = new JTextField();
rulesetFolderTextField.setText(rulesetFolder.getPath());
rulesetFolderTextField.setEditable(false);
rulesetPanel.add(rulesetFolderTextField);
selectRulesetFolderButton = new JButton(tr("Select directory"));
selectRulesetFolderButton.addActionListener(selectRulesetFolderActionListener);
rulesetPanel.add(selectRulesetFolderButton);
updateRulesetPanel();
return rulesetPanel;
}
private JPanel createVehiclePanel() {
JPanel vehiclePanel = new JPanel();
vehiclePanel.setBorder(BorderFactory.createTitledBorder(tr("Vehicle")));
vehiclePanel.setLayout(new BoxLayout(vehiclePanel, BoxLayout.Y_AXIS));
bookmarkComboBox = new JComboBox<>();
vehiclePanel.add(bookmarkComboBox);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
JButton createButton = new JButton(tr("Create"));
createButton.addActionListener(createVehicleActionListener);
buttonPanel.add(createButton);
editBookmarkButton = new JButton(tr("Edit"));
editBookmarkButton.addActionListener(editVehicleActionListener);
buttonPanel.add(editBookmarkButton);
deleteBookmarkButton = new JButton(tr("Delete"));
deleteBookmarkButton.addActionListener(deleteVehicleActionListener);
buttonPanel.add(deleteBookmarkButton);
JButton restoreDefaultsButton = new JButton(tr("Restore defaults"));
restoreDefaultsButton.addActionListener(restoreVehicleDefaultsActionListener);
buttonPanel.add(restoreDefaultsButton);
vehiclePanel.add(buttonPanel);
return vehiclePanel;
}
private JPanel createVisualizationPanel() {
JPanel visualizationPanel = new JPanel();
visualizationPanel.setBorder(BorderFactory.createTitledBorder(tr("Visualization")));
visualizationPanel.setLayout(new BoxLayout(visualizationPanel, BoxLayout.Y_AXIS));
separateDirectionsCheckBox = new JCheckBox(tr("Draw directions separately"));
separateDirectionsCheckBox.setSelected(GraphViewPreferences.getInstance().getSeparateDirections());
visualizationPanel.add(separateDirectionsCheckBox);
{ // create color chooser panel
JPanel colorPanel = new JPanel();
colorPanel.setLayout(new GridLayout(3, 2));
Color nodeColor = GraphViewPreferences.getInstance().getNodeColor();
nodeColorButton = new JButton(tr("Node color"));
nodeColorButton.addActionListener(chooseNodeColorActionListener);
colorPanel.add(nodeColorButton);
nodeColorField = new JPanel();
nodeColorField.setBackground(nodeColor);
colorPanel.add(nodeColorField);
Color segmentColor = GraphViewPreferences.getInstance().getSegmentColor();
segmentColorButton = new JButton(tr("Arrow color"));
segmentColorButton.addActionListener(chooseSegmentColorActionListener);
colorPanel.add(segmentColorButton);
segmentColorField = new JPanel();
segmentColorField.setBackground(segmentColor);
colorPanel.add(segmentColorField);
Color arrowheadFillColor = GraphViewPreferences.getInstance().getArrowheadFillColor();
arrowheadFillColorButton = new JButton(tr("Arrowhead fill color"));
arrowheadFillColorButton.addActionListener(chooseArrowheadFillColorActionListener);
colorPanel.add(arrowheadFillColorButton);
arrowheadFillColorField = new JPanel();
arrowheadFillColorField.setBackground(arrowheadFillColor);
colorPanel.add(arrowheadFillColorField);
visualizationPanel.add(colorPanel);
}
arrowheadPlacementSlider = new JSlider(0, 100);
arrowheadPlacementSlider.setToolTipText(tr("Arrowhead placement"));
arrowheadPlacementSlider.setMajorTickSpacing(10);
arrowheadPlacementSlider.setPaintTicks(true);
arrowheadPlacementSlider.setName("name");
arrowheadPlacementSlider.setLabelTable(null);
arrowheadPlacementSlider.setValue((int) Math.round(
100 * GraphViewPreferences.getInstance().getArrowheadPlacement()));
arrowheadPlacementSlider.addChangeListener(arrowheadPlacementChangeListener);
visualizationPanel.add(arrowheadPlacementSlider);
arrowPreviewPanel = new ArrowPreviewPanel();
visualizationPanel.add(arrowPreviewPanel);
return visualizationPanel;
}
@Override
public boolean ok() {
GraphViewPreferences preferences = GraphViewPreferences.getInstance();
preferences.setUseInternalRulesets(internalRulesetCheckBox.isSelected());
preferences.setRulesetFolder(rulesetFolder);
preferences.setParameterBookmarks(parameterBookmarks);
String selectedBookmarkName = (String) bookmarkComboBox.getSelectedItem();
preferences.setCurrentParameterBookmarkName(selectedBookmarkName);
preferences.setSeparateDirections(separateDirectionsCheckBox.isSelected());
preferences.setNodeColor(nodeColorField.getBackground());
preferences.setSegmentColor(segmentColorField.getBackground());
preferences.setArrowheadFillColor(arrowheadFillColorField.getBackground());
preferences.setArrowheadPlacement(
arrowheadPlacementSlider.getValue() / 100f);
preferences.distributeChanges();
return false;
}
private final ActionListener internalRulesetActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateRulesetPanel();
}
};
private final ActionListener selectRulesetFolderActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
File initialFCDirectory = rulesetFolder;
if (rulesetFolder.getParentFile() != null) {
initialFCDirectory = rulesetFolder.getParentFile();
}
final JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setCurrentDirectory(initialFCDirectory);
int returnVal = fc.showOpenDialog(preferencePanel);
if (returnVal == JFileChooser.APPROVE_OPTION) {
rulesetFolder = fc.getSelectedFile();
rulesetFolderTextField.setText(rulesetFolder.getPath());
}
}
};
private final ActionListener createVehicleActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PreferenceAccessParameters defaultBookmarkParameters =
GraphViewPreferenceDefaults.createDefaultBookmarkAccessParameters();
AccessParameterDialog apd = new AccessParameterDialog(
null,
false,
tr("New bookmark"),
parameterBookmarks.keySet(),
defaultBookmarkParameters,
new BookmarkAction() {
@Override
public void execute(String name, PreferenceAccessParameters parameters) {
parameterBookmarks.put(name, parameters);
updateVehiclePanel(name);
}
});
apd.setVisible(true);
}
};
private final ActionListener editVehicleActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (bookmarkComboBox.getSelectedItem() != null) {
final String selectedBookmarkName = (String) bookmarkComboBox.getSelectedItem();
PreferenceAccessParameters parameters =
parameterBookmarks.get(selectedBookmarkName);
Collection<String> otherBookmarkNames = new LinkedList<>();
for (String bookmarkName : parameterBookmarks.keySet()) {
if (!bookmarkName.equals(selectedBookmarkName)) {
otherBookmarkNames.add(bookmarkName);
}
}
AccessParameterDialog apd = new AccessParameterDialog(
null,
true,
selectedBookmarkName,
otherBookmarkNames,
parameters,
new BookmarkAction() {
@Override
public void execute(String name, PreferenceAccessParameters parameters) {
parameterBookmarks.remove(selectedBookmarkName);
parameterBookmarks.put(name, parameters);
updateVehiclePanel(name);
}
});
apd.setVisible(true);
}
}
};
private final ActionListener deleteVehicleActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (bookmarkComboBox.getSelectedItem() != null) {
String selectedBookmarkName = (String) bookmarkComboBox.getSelectedItem();
int userChoice = JOptionPane.showConfirmDialog(
preferencePanel,
tr("Really delete \"{0}\"?", selectedBookmarkName),
tr("Bookmark deletion"),
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (userChoice == JOptionPane.YES_OPTION) {
parameterBookmarks.remove(selectedBookmarkName);
updateVehiclePanel(null);
}
}
}
};
private final ActionListener restoreVehicleDefaultsActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int userChoice = JOptionPane.showConfirmDialog(
preferencePanel,
tr("Really restore default bookmarks?\n"
+ "All manually added or edited bookmarks will be lost!"),
tr("Bookmark reset"),
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (userChoice == JOptionPane.YES_OPTION) {
parameterBookmarks.clear();
parameterBookmarks.putAll(
GraphViewPreferenceDefaults.createDefaultAccessParameterBookmarks());
updateVehiclePanel(null);
}
}
};
private final ActionListener chooseNodeColorActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Color selectedColor = JColorChooser.showDialog(
preferencePanel, tr("Choose node color"), nodeColorField.getBackground());
if (selectedColor != null) {
nodeColorField.setBackground(selectedColor);
}
arrowPreviewPanel.repaint();
}
};
private final ActionListener chooseSegmentColorActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Color selectedColor = JColorChooser.showDialog(
preferencePanel, tr("Choose arrow color"), segmentColorField.getBackground());
if (selectedColor != null) {
segmentColorField.setBackground(selectedColor);
}
arrowPreviewPanel.repaint();
}
};
private final ActionListener chooseArrowheadFillColorActionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Color selectedColor = JColorChooser.showDialog(
preferencePanel, tr("Choose arrowhead fill color"), segmentColorField.getBackground());
if (selectedColor != null) {
arrowheadFillColorField.setBackground(selectedColor);
}
arrowPreviewPanel.repaint();
}
};
private final ChangeListener arrowheadPlacementChangeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
arrowPreviewPanel.repaint();
}
};
private void updateRulesetPanel() {
rulesetFolderLabel.setEnabled(!internalRulesetCheckBox.isSelected());
rulesetFolderTextField.setEnabled(!internalRulesetCheckBox.isSelected());
selectRulesetFolderButton.setEnabled(!internalRulesetCheckBox.isSelected());
}
private void updateVehiclePanel(String selectedBookmarkName) {
bookmarkComboBox.removeAllItems();
for (String bookmarkName : parameterBookmarks.keySet()) {
bookmarkComboBox.addItem(bookmarkName);
}
if (selectedBookmarkName == null) {
if (bookmarkComboBox.getItemCount() > 0) {
bookmarkComboBox.setSelectedIndex(0);
}
} else {
bookmarkComboBox.setSelectedItem(selectedBookmarkName);
}
editBookmarkButton.setEnabled(parameterBookmarks.size() > 0);
deleteBookmarkButton.setEnabled(parameterBookmarks.size() > 0);
}
private class ArrowPreviewPanel extends JPanel {
ArrowPreviewPanel() {
setPreferredSize(new Dimension(100, 50));
setBackground(Color.DARK_GRAY);
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
Point p1 = new Point(15, this.getHeight() / 2);
Point p2 = new Point(this.getWidth()-15, this.getHeight() / 2);
g2D.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2D.setColor(segmentColorField.getBackground());
g2D.draw(new Line2D.Float(p1.x, p1.y, p2.x, p2.y));
GraphViewLayer.paintNode(g, p1, nodeColorField.getBackground());
GraphViewLayer.paintNode(g, p2, nodeColorField.getBackground());
GraphViewLayer.paintArrowhead(g2D, p1, p2,
arrowheadPlacementSlider.getValue() / 100.0,
segmentColorField.getBackground(),
arrowheadFillColorField.getBackground());
}
}
}