package org.openstreetmap.josm.plugins.rasterfilters.gui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.rmi.server.UID;
import java.util.Hashtable;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import com.bric.swing.ColorPicker;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.plugins.rasterfilters.model.FiltersManager;
import static org.openstreetmap.josm.tools.I18n.tr;
/**
* FilterPanel is usual JPanel with its
* own GUI elements which is added according to
* meta-information of filter.
*
* @author Nipel-Crumple
*/
public class FilterPanel extends JPanel {
private static final long serialVersionUID = 1L;
private UID filterId;
private int neededHeight;
public FilterPanel() {
super();
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
setBackground(Color.white);
}
/**
* Methods adds GUI element on filter's panel according to meta-information and
* automatically resizes the given filter's panel.
*
* @param json filter's meta-information
* @return added GUI element
*/
public JComponent addGuiElement(JsonObject json) {
String type = json.getString("type");
if (type.equals("linear_slider")) {
setNeededHeight(getNeededHeight() + 70);
return createSlider(json);
} else if (type.equals("checkbox")) {
setNeededHeight(getNeededHeight() + 30);
JCheckBox checkBox = createCheckBox(json.getString("title"));
checkBox.setSelected(json.getBoolean("default"));
checkBox.setName(json.getString("name"));
return checkBox;
} else if (type.equals("select")) {
setNeededHeight(getNeededHeight() + 50);
return createSelect(json);
} else if (type.equals("colorpicker")) {
setNeededHeight(getNeededHeight() + 220);
return createColorPicker(json);
}
return null;
}
private JComponent createSelect(JsonObject json) {
Font font = new Font("Arial", Font.PLAIN, 14);
JPanel selectPanel = new JPanel();
selectPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
selectPanel.setBackground(Color.white);
selectPanel.setLayout(new BoxLayout(selectPanel, BoxLayout.X_AXIS));
selectPanel.setMaximumSize(new Dimension(300, 40));
JLabel selectTitle = new JLabel(json.getString("title"));
selectTitle.setFont(font);
selectTitle.setBackground(Color.white);
JsonArray valuesArray = json.getJsonArray("values");
DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
model.setSelectedItem(json.getString("default"));
for (int i = 0; i < valuesArray.size(); i++) {
model.addElement(valuesArray.getString(i));
}
JComboBox<String> selectBox = new JComboBox<>(model);
selectBox.setMinimumSize(new Dimension(140, 30));
selectPanel.add(selectTitle);
selectPanel.add(Box.createHorizontalGlue());
selectPanel.add(selectBox);
selectBox.setName(json.getString("name"));
this.add(selectPanel);
return selectBox;
}
public JComponent createColorPicker(JsonObject json) {
ColorPicker picker = new ColorPicker(false, false);
picker.setPreferredSize(new Dimension(200, 180));
picker.setMode(ColorPicker.HUE);
picker.setName(json.getString("name"));
addControlTitle(json.getString("title"));
this.add(picker);
return picker;
}
public JCheckBox createCheckBox(String text) {
JPanel checkBoxPanel = new JPanel();
checkBoxPanel.setMaximumSize(new Dimension(300, 30));
checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.X_AXIS));
checkBoxPanel.setBackground(Color.white);
JCheckBox checkBox = new JCheckBox(text);
Font font = new Font("Arial", Font.PLAIN, 12);
checkBox.setFont(font);
checkBox.setBackground(Color.white);
checkBox.setName(text);
checkBoxPanel.add(checkBox);
this.add(checkBoxPanel);
return checkBox;
}
private JCheckBox createDisableBox(ItemListener listener) {
JCheckBox disable = new JCheckBox("Disable");
Font font = new Font("Arial", Font.PLAIN, 12);
disable.addItemListener(listener);
disable.setFont(font);
return disable;
}
private JButton createRemoveButton(ActionListener listener) {
JButton removeButton = new JButton("Remove");
Font font = new Font("Arial", Font.PLAIN, 12);
removeButton.setFont(font);
removeButton.setName("remove");
removeButton.addActionListener(listener);
return removeButton;
}
public JPanel createBottomPanel(FiltersManager listener) {
this.add(Box.createRigidArea(new Dimension(0, 10)));
JPanel bottom = new JPanel();
bottom.setLayout(new BoxLayout(bottom, BoxLayout.X_AXIS));
bottom.setMaximumSize(new Dimension(300, 40));
bottom.setBorder(BorderFactory
.createMatteBorder(2, 0, 0, 0, Color.gray));
bottom.add(createDisableBox(listener));
bottom.add(Box.createHorizontalGlue());
bottom.add(createRemoveButton(listener));
this.add(bottom);
return bottom;
}
private void addControlTitle(String labelText) {
Font labelFont = new Font("Arial", Font.PLAIN, 14);
JPanel sliderLabelPanel = new JPanel();
sliderLabelPanel.setMaximumSize(new Dimension(400, 30));
sliderLabelPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
sliderLabelPanel.setBackground(Color.white);
JLabel sliderLabel = new JLabel(labelText, JLabel.LEFT);
sliderLabel.setFont(labelFont);
sliderLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
sliderLabel.setVisible(true);
sliderLabelPanel.add(sliderLabel);
this.add(sliderLabelPanel);
}
public JSlider createSlider(JsonObject json) {
Border sliderBorder = new EmptyBorder(5, 5, 5, 5);
addControlTitle(json.getString("title"));
Hashtable<Integer, JLabel> labelTable = new Hashtable<>();
JsonArray array = json.getJsonArray("scale");
String valueType = json.getString("value_type");
JSlider slider = null;
if (valueType.equals("integer")) {
int minValue = array.getInt(0);
int maxValue = array.getInt(1);
int initValue = json.getInt("default");
Main.debug("Slider is integer\n");
Main.debug("minValue: " + String.valueOf(minValue)
+ "maxValue: " + String.valueOf(maxValue));
try {
slider = new JSlider(JSlider.HORIZONTAL, minValue, maxValue,
initValue);
slider.setName(json.getString("name"));
slider.setToolTipText(String.valueOf(slider.getValue()));
slider.setMinorTickSpacing(maxValue / 4);
} catch (IllegalArgumentException e) {
JOptionPane.showMessageDialog(
Main.parent,
tr("JSlider initialization error. Make sure your meta-inf is correct."),
tr("Error"),
JOptionPane.ERROR_MESSAGE);
}
} else if (valueType.equals("float")) {
Main.debug("Slider is float\n");
// every value is supplied by 10 to be integer for slider
double minValueDouble = array.getJsonNumber(0).doubleValue();
double maxValueDouble = array.getJsonNumber(1).doubleValue();
Main.debug("DminValue: " + String.valueOf(minValueDouble)
+ "DmaxValue: " + String.valueOf(maxValueDouble));
int minValue = (int) (minValueDouble * 100);
int maxValue = (int) (maxValueDouble * 100);
double initValue = json.getJsonNumber("default").doubleValue() * 100;
double delta = (maxValue - minValue) / 100;
for (int i = 0; i <= maxValue; i++) {
if ((i % 20) == 0) {
labelTable.put(Integer.valueOf(i),
new JLabel(String.valueOf(i * delta / 100)));
}
}
try {
slider = new JSlider(JSlider.HORIZONTAL, minValue, maxValue, (int) initValue);
slider.setMinorTickSpacing(maxValue / 4);
slider.setName(json.getString("name"));
slider.setToolTipText(String.valueOf((double) slider.getValue() / 100));
} catch (IllegalArgumentException e) {
JOptionPane.showMessageDialog(
Main.parent,
tr("JSlider initialization error. Make sure your meta-inf is correct."),
tr("Error"),
JOptionPane.ERROR_MESSAGE);
}
}
slider.setBackground(this.getBackground());
slider.setBorder(sliderBorder);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
this.add(slider);
return slider;
}
public void setFilterId(UID filterId) {
this.filterId = filterId;
}
public UID getFilterId() {
return filterId;
}
public int getNeededHeight() {
return neededHeight;
}
public void setNeededHeight(int neededHeight) {
this.neededHeight = neededHeight;
}
}