package com.revolsys.swing.map.form;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.swing.DefaultRowSorter;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListModel;
import javax.swing.RowFilter;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.jdesktop.swingx.HorizontalLayout;
import org.jdesktop.swingx.JXList;
import org.jdesktop.swingx.VerticalLayout;
import com.revolsys.swing.Borders;
import com.revolsys.swing.SwingUtil;
import com.revolsys.swing.component.ValueField;
import com.revolsys.swing.field.CheckBox;
import com.revolsys.swing.field.SearchField;
import com.revolsys.swing.layout.GroupLayouts;
import com.revolsys.swing.list.ArrayListModel;
import com.revolsys.swing.list.filter.StringContainsRowFilter;
import com.revolsys.swing.map.layer.AbstractLayer;
import com.revolsys.swing.map.layer.record.AbstractRecordLayer;
import com.revolsys.swing.toolbar.ToolBar;
public class SnapLayersPanel extends ValueField implements ActionListener, ListSelectionListener {
private static final long serialVersionUID = 1L;
private final JButton addButton;
private final JPanel fieldsPanel;
private final JPanel filterPanel;
private final AbstractRecordLayer layer;
private final JXList layerPathsField;
private final ArrayListModel<String> layerPathsModel;
private final StringContainsRowFilter layerPathsTextFilter;
private final JButton removeButton;
private final JXList snapLayerPathsField;
private final ArrayListModel<String> snapLayerPathsModel;
private final StringContainsRowFilter snapLayerPathsTextFilter;
private final CheckBox snapToAllLayers;
public SnapLayersPanel(final AbstractRecordLayer layer) {
super(new VerticalLayout(5));
this.layer = layer;
Borders.titled(this, "Snapping");
final JPanel snapAllPanel = new JPanel();
snapAllPanel.setOpaque(false);
add(snapAllPanel);
SwingUtil.addLabel(snapAllPanel, "Snap To All Visible Layers");
this.snapToAllLayers = new CheckBox("snapToAllLayers", layer.isSnapToAllLayers());
this.snapToAllLayers.addActionListener(this);
snapAllPanel.add(this.snapToAllLayers);
GroupLayouts.makeColumns(snapAllPanel, 2, false);
this.filterPanel = new JPanel(new HorizontalLayout(46));
this.filterPanel.setOpaque(false);
add(this.filterPanel);
final SearchField layerPathsFilterField = new SearchField("layerPathsFilter");
layerPathsFilterField.setPreferredSize(new Dimension(350, 25));
layerPathsFilterField.addActionListener(this);
this.filterPanel.add(layerPathsFilterField);
final SearchField snapLayerPathsFilterField = new SearchField("snapLayerPathsFilter");
snapLayerPathsFilterField.setPreferredSize(new Dimension(350, 25));
snapLayerPathsFilterField.addActionListener(this);
this.filterPanel.add(snapLayerPathsFilterField);
this.fieldsPanel = new JPanel(new HorizontalLayout(5));
this.fieldsPanel.setOpaque(false);
final List<AbstractRecordLayer> recordLayers = layer.getProject()
.getDescenants(AbstractRecordLayer.class);
this.layerPathsModel = new ArrayListModel<>();
for (final AbstractLayer recordLayer : recordLayers) {
if (recordLayer.isHasGeometry()) {
final String layerPath = recordLayer.getPath();
this.layerPathsModel.add(layerPath);
}
}
this.layerPathsField = new JXList(this.layerPathsModel);
this.layerPathsField.setAutoCreateRowSorter(true);
this.layerPathsField.setSortable(true);
this.layerPathsField.setSortOrder(SortOrder.ASCENDING);
this.layerPathsField.addListSelectionListener(this);
final JScrollPane layerPathsScrollPane = new JScrollPane(this.layerPathsField);
layerPathsScrollPane.setPreferredSize(new Dimension(350, 400));
this.fieldsPanel.add(layerPathsScrollPane);
final ToolBar toolBar = new ToolBar(SwingConstants.VERTICAL);
toolBar.setOpaque(false);
toolBar.setMinimumSize(new Dimension(25, 25));
this.fieldsPanel.add(toolBar);
this.addButton = toolBar.addButtonTitleIcon("default", "Add", "add", this::addSelected);
this.removeButton = toolBar.addButtonTitleIcon("default", "Remove", "delete",
this::removeSelected);
final Collection<String> snapLayerPaths = layer.getSnapLayerPaths();
this.snapLayerPathsModel = new ArrayListModel<>(snapLayerPaths);
this.snapLayerPathsField = new JXList(this.snapLayerPathsModel);
this.snapLayerPathsField.setAutoCreateRowSorter(true);
this.snapLayerPathsField.setSortable(true);
this.snapLayerPathsField.setSortOrder(SortOrder.ASCENDING);
this.snapLayerPathsField.addListSelectionListener(this);
this.snapLayerPathsTextFilter = new StringContainsRowFilter();
this.snapLayerPathsField.setRowFilter(this.snapLayerPathsTextFilter);
final JScrollPane snapScrollPane = new JScrollPane(this.snapLayerPathsField);
snapScrollPane.setPreferredSize(new Dimension(350, 400));
this.fieldsPanel.add(snapScrollPane);
add(this.fieldsPanel);
this.layerPathsTextFilter = new StringContainsRowFilter();
final RowFilter<ListModel, Integer> layerPathsFilter = RowFilter.andFilter(Arrays
.asList(new CollectionRowFilter(this.snapLayerPathsModel, false), this.layerPathsTextFilter));
this.layerPathsField.setRowFilter(layerPathsFilter);
updateEnabledState();
}
@Override
public void actionPerformed(final ActionEvent event) {
final Object source = event.getSource();
if (source instanceof SearchField) {
final SearchField field = (SearchField)source;
final String fieldName = field.getFieldName();
final String text = field.getText();
if (fieldName.equals("layerPathsFilter")) {
this.layerPathsTextFilter.setFilterText(text);
sort(this.layerPathsField);
} else if (fieldName.equals("snapLayerPathsFilter")) {
this.snapLayerPathsTextFilter.setFilterText(text);
sort(this.snapLayerPathsField);
}
} else if (source == this.snapToAllLayers) {
updateEnabledState();
}
}
public void addSelected() {
this.snapLayerPathsField.clearSelection();
for (final Object selectedValue : this.layerPathsField.getSelectedValues()) {
final String layerPath = (String)selectedValue;
if (!this.snapLayerPathsModel.contains(layerPath)) {
this.snapLayerPathsModel.add(layerPath);
final RowSorter<? extends ListModel> rowSorter = this.layerPathsField.getRowSorter();
if (rowSorter instanceof DefaultRowSorter) {
final DefaultRowSorter<?, ?> sorter = (DefaultRowSorter<?, ?>)rowSorter;
sorter.sort();
}
final int index = this.snapLayerPathsField
.convertIndexToView(this.snapLayerPathsModel.indexOf(layerPath));
this.snapLayerPathsField.addSelectionInterval(index, index);
}
}
}
public void removeSelected() {
final Object[] selectedValues = this.snapLayerPathsField.getSelectedValues();
this.snapLayerPathsModel.removeAll(selectedValues);
sort(this.layerPathsField);
}
@Override
public void save() {
super.save();
this.layer.setSnapToAllLayers(this.snapToAllLayers.isSelected());
final Set<String> layerPaths = new TreeSet<>();
for (int i = 0; i < this.snapLayerPathsModel.size(); i++) {
final String layerPath = this.snapLayerPathsModel.get(i);
layerPaths.add(layerPath);
}
this.layer.setSnapLayerPaths(layerPaths);
}
public void sort(final JXList list) {
final RowSorter<? extends ListModel> rowSorter = list.getRowSorter();
if (rowSorter instanceof DefaultRowSorter) {
final DefaultRowSorter<?, ?> sorter = (DefaultRowSorter<?, ?>)rowSorter;
sorter.sort();
}
}
public void updateEnabledState() {
final boolean enabled = !this.snapToAllLayers.isSelected();
SwingUtil.setDescendantsEnabled(this.filterPanel, enabled);
SwingUtil.setDescendantsEnabled(this.fieldsPanel, enabled);
if (enabled) {
this.addButton.setEnabled(this.layerPathsField.getSelectedIndex() > -1);
this.removeButton.setEnabled(this.snapLayerPathsField.getSelectedIndex() > -1);
}
}
@Override
public void valueChanged(final ListSelectionEvent event) {
updateEnabledState();
}
}