package org.openstreetmap.josm.plugins.rasterfilters.model;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.BufferedImage;
import java.rmi.server.UID;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JSlider;
import com.bric.swing.ColorPicker;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.gui.layer.ImageProcessor;
import org.openstreetmap.josm.plugins.rasterfilters.filters.Filter;
import org.openstreetmap.josm.plugins.rasterfilters.gui.FilterGuiListener;
import org.openstreetmap.josm.plugins.rasterfilters.gui.FilterPanel;
import org.openstreetmap.josm.plugins.rasterfilters.gui.FiltersDialog;
import org.openstreetmap.josm.plugins.rasterfilters.preferences.FiltersDownloader;
/**
* This class adds filter to the dialog and can also remove
* or disable it from the filters chain.
*
* @author Nipel-Crumple
*/
public class FiltersManager implements StateChangeListener, ImageProcessor, ActionListener, ItemListener {
public Map<UID, Filter> filtersMap = new LinkedHashMap<>();
public Set<Filter> disabledFilters = new HashSet<>();
public FiltersDialog dialog;
public FiltersManager(FiltersDialog dialog) {
this.dialog = dialog;
}
@SuppressWarnings("unchecked")
private JPanel createFilterWithPanel(JsonObject meta) {
FilterPanel fp = new FilterPanel();
// listener to track sliders and checkbox of creating filter
FilterGuiListener filterListener = new FilterGuiListener(this);
String filterClassName = meta.getString("classname");
String filterTitle = meta.getString("title");
fp.setName(filterTitle);
// creating model of the filter
FilterStateModel filterState = new FilterStateModel();
filterState.setFilterClassName(filterClassName);
// loading jar with filter at runtime
Class<?> clazz;
// filter for adding to map states
Filter filter = null;
try {
Main.debug("ClassName for loading " + filterState.getFilterClassName());
clazz = FiltersDownloader.loader.loadClass(filterState
.getFilterClassName());
filter = (Filter) clazz.getConstructor().newInstance();
} catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
e.printStackTrace();
}
if (filter != null) {
UID filterId = new UID();
fp.setFilterId(filterId);
filterListener.setFilterId(filterId);
filter.setId(filterId);
filtersMap.put(filterId, filter);
// all filters enabled in the beggining by default
}
fp.setBorder(BorderFactory.createTitledBorder(meta.getString("title")));
JsonArray controls = meta.getJsonArray("controls");
for (int i = 0; i < controls.size(); i++) {
JsonObject temp = controls.getJsonObject(i);
// Main.debug(temp.toString());
JComponent component = fp.addGuiElement(temp);
if (component != null) {
if (component instanceof JSlider) {
((JSlider) component).addChangeListener(filterListener);
} else if (component instanceof JCheckBox) {
((JCheckBox) component).addItemListener(filterListener);
} else if (component instanceof JComboBox) {
((JComboBox<String>) component).addActionListener(filterListener);
} else if (component instanceof ColorPicker) {
((ColorPicker) component).addPropertyChangeListener(filterListener);
}
// adding parameters to the filter instance
filterState.addParams(temp);
}
}
fp.setNeededHeight(fp.getNeededHeight() + 60);
fp.setMaximumSize(new Dimension(300, fp.getNeededHeight()));
fp.setPreferredSize(new Dimension(300, fp.getNeededHeight()));
if (filter != null) {
filter.changeFilterState(filterState.encodeJson());
}
Main.getLayerManager().getActiveLayer().setFilterStateChanged();
fp.createBottomPanel(this);
filterListener.setFilterState(filterState);
Main.debug("The number of elems in the Filters map is equal \n"
+ filtersMap.size());
return fp;
}
/**
* The method notifies about changes in the filter's status.
*
* @param filterState - model that contains info about filter which was changed
*/
@Override
public void filterStateChanged(UID filterId, FilterStateModel filterState) {
if (filtersMap.get(filterId) != null) {
filtersMap.get(filterId).changeFilterState(filterState.encodeJson());
}
if (Main.getLayerManager().getActiveLayer() != null) {
Main.getLayerManager().getActiveLayer().setFilterStateChanged();
}
}
public JPanel createPanelByTitle(String title) {
for (JsonObject json : FiltersDownloader.filtersMeta) {
if (json.getString("title").equals(title)) {
return createFilterWithPanel(json);
}
}
return null;
}
@Override
public BufferedImage process(BufferedImage image) {
Iterator<Filter> it = filtersMap.values().iterator();
// iterating through map of filters according to the order
while (it.hasNext()) {
Filter curFilter = it.next();
if (!disabledFilters.contains(curFilter)) {
// if next filter will return null
// we should take an old example of the image
BufferedImage oldImg = image;
// applying filter to the current image
image = curFilter.applyFilter(image);
if (image == null) {
image = oldImg;
}
}
}
return image;
}
@Override
public void actionPerformed(ActionEvent e) {
FilterPanel filterPanel = (FilterPanel) ((JButton) e.getSource())
.getParent().getParent();
UID filterId = filterPanel.getFilterId();
// removing filter from the filters chain
filtersMap.remove(filterId);
dialog.getShowedFiltersTitles().remove(filterPanel.getName());
// add filterTitle to the 'choose list' on the top
dialog.getListModel().addElement(filterPanel.getName());
// removing panel from filterContainer
filterPanel.removeAll();
dialog.getFilterContainer().remove(filterPanel);
if (dialog.getFilterContainer().getComponentCount() == 0) {
dialog.deleteFilterContainer();
} else {
dialog.getFilterContainer().revalidate();
dialog.getFilterContainer().repaint();
}
// if there were no elements in the list
// but then it appeared
// button should be enabled
if (!dialog.getAddButton().isEnabled()) {
dialog.getFilterChooser().setEnabled(true);
dialog.getAddButton().setEnabled(true);
}
Main.getLayerManager().getActiveLayer().setFilterStateChanged();
}
@Override
public void itemStateChanged(ItemEvent e) {
JCheckBox enableFilter = (JCheckBox) e.getSource();
FilterPanel filterPanel = (FilterPanel) enableFilter.getParent()
.getParent();
if (enableFilter.isSelected()) {
UID filterId = filterPanel.getFilterId();
disabledFilters.add(filtersMap.get(filterId));
Main.getLayerManager().getActiveLayer().setFilterStateChanged();
} else {
UID filterId = filterPanel.getFilterId();
disabledFilters.remove(filtersMap.get(filterId));
Main.getLayerManager().getActiveLayer().setFilterStateChanged();
}
}
}