/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* 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 3 of the License, or (at your option)
* 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, see http://www.gnu.org/licenses/
*/
package org.esa.snap.ui.crs;
import com.bc.ceres.swing.TableLayout;
import com.bc.ceres.swing.TableLayout.Anchor;
import com.bc.ceres.swing.TableLayout.Fill;
import com.jidesoft.swing.LabeledTextField;
import org.esa.snap.ui.util.FilteredListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.awt.Container;
import java.awt.Dimension;
import java.util.logging.Logger;
class PredefinedCrsPanel extends JPanel {
public static final Logger LOG = Logger.getLogger(PredefinedCrsPanel.class.getName());
private final CrsInfoListModel crsListModel;
private JTextArea infoArea;
private JList<CrsInfo> crsList;
private LabeledTextField filterField;
private CrsInfo selectedCrsInfo;
private FilteredListModel<CrsInfo> filteredListModel;
// for testing the UI
public static void main(String[] args) {
final JFrame frame = new JFrame("CRS Selection Panel");
Container contentPane = frame.getContentPane();
final CrsInfoListModel listModel = new CrsInfoListModel(CrsInfo.generateCRSList());
PredefinedCrsPanel predefinedCrsForm = new PredefinedCrsPanel(listModel);
contentPane.add(predefinedCrsForm);
frame.setSize(600, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
SwingUtilities.invokeLater(() -> frame.setVisible(true));
}
PredefinedCrsPanel(CrsInfoListModel model) {
crsListModel = model;
createUI();
}
private void createUI() {
filterField = new LabeledTextField();
filterField.setHintText("Type here to filter CRS");
filterField.getTextField().getDocument().addDocumentListener(new FilterDocumentListener());
filteredListModel = new FilteredListModel<>(crsListModel);
crsList = new JList<>(filteredListModel);
crsList.setVisibleRowCount(15);
crsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
final JLabel filterLabel = new JLabel("Filter:");
final JLabel infoLabel = new JLabel("Well-Known Text (WKT):");
final JScrollPane crsListScrollPane = new JScrollPane(crsList);
crsListScrollPane.setPreferredSize(new Dimension(200, 150));
infoArea = new JTextArea(15, 30);
infoArea.setEditable(false);
crsList.addListSelectionListener(new CrsListSelectionListener());
crsList.setSelectedIndex(0);
final JScrollPane infoAreaScrollPane = new JScrollPane(infoArea);
TableLayout tableLayout = new TableLayout(3);
setLayout(tableLayout);
tableLayout.setTableFill(Fill.BOTH);
tableLayout.setTableAnchor(Anchor.NORTHWEST);
tableLayout.setTableWeightX(1.0);
tableLayout.setTablePadding(4, 4);
tableLayout.setRowWeightY(0, 0.0); // no weight Y for first row
tableLayout.setCellWeightX(0, 0, 0.0); // filter label; no grow in X
tableLayout.setRowWeightY(1, 1.0); // second row grow in Y
tableLayout.setCellColspan(1, 0, 2); // CRS list; spans 2 cols
tableLayout.setCellRowspan(1, 2, 2); // info area; spans 2 rows
tableLayout.setCellColspan(2, 0, 2); // defineCrsBtn button; spans to cols
add(filterLabel);
add(filterField);
add(infoLabel);
add(crsListScrollPane);
add(infoAreaScrollPane);
addPropertyChangeListener("enabled", evt -> {
filterLabel.setEnabled((Boolean) evt.getNewValue());
filterField.setEnabled((Boolean) evt.getNewValue());
infoLabel.setEnabled((Boolean) evt.getNewValue());
crsList.setEnabled((Boolean) evt.getNewValue());
crsListScrollPane.setEnabled((Boolean) evt.getNewValue());
infoArea.setEnabled((Boolean) evt.getNewValue());
infoAreaScrollPane.setEnabled((Boolean) evt.getNewValue());
});
crsList.getSelectionModel().setSelectionInterval(0, 0);
}
private class FilterDocumentListener implements DocumentListener {
@Override
public void insertUpdate(DocumentEvent e) {
updateFilter(getFilterText(e));
clearListSelection();
}
@Override
public void removeUpdate(DocumentEvent e) {
updateFilter(getFilterText(e));
clearListSelection();
}
private void clearListSelection() {
crsList.clearSelection();
setInfoText("");
}
@Override
public void changedUpdate(DocumentEvent e) {
}
private void updateFilter(String text) {
filteredListModel.setFilter(crsInfo -> {
String description = crsInfo.toString().toLowerCase();
return description.contains(text.trim().toLowerCase());
});
}
private String getFilterText(DocumentEvent e) {
Document document = e.getDocument();
String text = null;
try {
text = document.getText(0, document.getLength());
} catch (BadLocationException e1) {
LOG.severe(e1.getMessage());
}
return text;
}
}
private class CrsListSelectionListener implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent e) {
final JList list = (JList) e.getSource();
selectedCrsInfo = (CrsInfo) list.getSelectedValue();
if (selectedCrsInfo != null) {
try {
setInfoText(selectedCrsInfo.getDescription());
} catch (Exception e1) {
String message = e1.getMessage();
if (message != null) {
setInfoText("Error while creating CRS:\n\n" + message);
}
}
}
}
}
CrsInfo getSelectedCrsInfo() {
return selectedCrsInfo;
}
private void setInfoText(String infoText) {
infoArea.setText(infoText);
infoArea.setCaretPosition(0);
}
}