/* * This file is part of JGrasstools (http://www.jgrasstools.org) * (C) HydroloGIS - www.hydrologis.com * * JGrasstools 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.jgrasstools.gui.spatialtoolbox.core; import java.awt.BorderLayout; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.geom.Point2D; import java.io.File; import java.lang.reflect.Field; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import javax.swing.DefaultComboBoxModel; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFormattedTextField; import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.JTextField; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.data.simple.SimpleFeatureCollection; import org.jgrasstools.gears.JGrassGears; import org.jgrasstools.gears.libs.modules.JGTConstants; import org.jgrasstools.gears.utils.files.FileUtilities; import org.jgrasstools.gui.utils.GuiBridgeHandler; import org.jgrasstools.gui.utils.GuiUtilities; import org.jgrasstools.hortonmachine.HortonMachine; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; /** * The parameters panel. * * @author Andrea Antonello (www.hydrologis.com) * */ public class ParametersPanel extends JPanel implements MouseListener { private static final long serialVersionUID = 1L; private static final String PM_VAR_NAME = "pm"; private Class< ? > parentOmsClass; private String[] rasterLayers; private String[] vectorLayers; private List<JTextField> eastingListeningFields = new ArrayList<JTextField>(); private List<JTextField> northingListeningFields = new ArrayList<JTextField>(); private HashMap<String, Object> fieldName2ValueHolderMap = new HashMap<String, Object>(); private List<String> outputFieldNames = new ArrayList<String>(); private List<JComboBox<String>> rasterComboList = new ArrayList<>(); private List<JComboBox<String>> vectorComboList = new ArrayList<>(); private ModuleDescription module; private GuiBridgeHandler guiBridge; public ParametersPanel( GuiBridgeHandler guiBridge ) { this.guiBridge = guiBridge; } public ModuleDescription getModule() { return module; } public HashMap<String, Object> getFieldName2ValueHolderMap() { return fieldName2ValueHolderMap; } public List<String> getOutputFieldNames() { return outputFieldNames; } public void setVectorRasterLayers( String[] vectorLayers, String[] rasterLayers ) { this.vectorLayers = vectorLayers; this.rasterLayers = rasterLayers; for( JComboBox<String> rasterCombo : rasterComboList ) { try { Object selectedRaster = rasterCombo.getSelectedItem(); if (rasterLayers != null) { String[] tmpRasterLayers = new String[rasterLayers.length + 1]; tmpRasterLayers[0] = ""; System.arraycopy(rasterLayers, 0, tmpRasterLayers, 1, rasterLayers.length); rasterCombo.setModel(new DefaultComboBoxModel<String>(tmpRasterLayers)); } if (selectedRaster != null) { rasterCombo.setSelectedItem(selectedRaster); } } catch (Exception e) { e.printStackTrace(); } } for( JComboBox<String> vectorCombo : vectorComboList ) { try { Object selectedVector = vectorCombo.getSelectedItem(); if (vectorLayers != null) { String[] tmpVectorLayers = new String[vectorLayers.length + 1]; tmpVectorLayers[0] = ""; System.arraycopy(vectorLayers, 0, tmpVectorLayers, 1, vectorLayers.length); vectorCombo.setModel(new DefaultComboBoxModel<String>(tmpVectorLayers)); } if (selectedVector != null) { vectorCombo.setSelectedItem(selectedVector); } } catch (Exception e) { e.printStackTrace(); } } } public void setModule( ModuleDescription module ) { this.module = module; clear(); if (module == null) { return; } parentOmsClass = getParentClass(module); final List<FieldData> inputsList = module.getInputsList(); // final List<FieldData> outputsList = module.getOutputsList(); int allRows = inputsList.size();// + outputsList.size(); String rowsEnc = ""; for( int i = 0; i < allRows; i++ ) { if (i == 0) { rowsEnc = "pref"; } else rowsEnc = rowsEnc + ", 3dlu, max(50dlu;pref)"; } // max(75dlu;pref) this.setLayout(new FormLayout("fill:250px:grow(.35), fill:5px, fill:250px:grow(.55)", rowsEnc)); // this.setLayout(new FormLayout("left:pref, 2dlu, pref:grow", rowsEnc)); addInputs(inputsList); // NO OUTPUTS AVAILABLE // for( FieldData outputField : outputsList ) { // String fieldLabel = null; // String fieldDescription = outputField.fieldDescription; // if (fieldDescription.length() > labelTrim) { // fieldLabel = fieldDescription.substring(0, labelTrim) + "..."; // } else { // fieldLabel = fieldDescription; // } // String fieldTooltip = fieldDescription; // JLabel nameLabel = new JLabel(fieldLabel); // nameLabel.setToolTipText(fieldTooltip); // this.add(nameLabel, cc.xy(1, row)); // JTextField f = new JTextField(); // this.add(f, cc.xy(2, row)); // row = row + 2; // } } private Class< ? > getParentClass( ModuleDescription module ) { Class< ? > parentOmsClass = null; try { Class< ? > moduleClass = module.getModuleClass(); String simpleName = "Oms" + moduleClass.getSimpleName(); Class< ? > pClass = HortonMachine.getInstance().moduleName2Class.get(simpleName); if (pClass == null) { pClass = JGrassGears.getInstance().moduleName2Class.get(simpleName); } if (pClass != null) parentOmsClass = pClass; } catch (Exception e) { // ignore and return null return null; } return parentOmsClass; } private void addInputs( final List<FieldData> inputsList ) { rasterComboList = new ArrayList<>(); vectorComboList = new ArrayList<>(); CellConstraints cc = new CellConstraints(); int row = 1; for( FieldData inputField : inputsList ) { if (inputField.fieldName.equals(PM_VAR_NAME)) { continue; } String fieldDescription = inputField.fieldDescription; String fieldLabel = fieldDescription; String fieldTooltip = fieldDescription; JTextArea nameLabel = new JTextArea(); nameLabel.setOpaque(false); nameLabel.setLineWrap(true); nameLabel.setWrapStyleWord(true); nameLabel.setText(fieldLabel); nameLabel.setToolTipText(fieldTooltip); nameLabel.setEditable(false); TypeCheck fileCheck = getFileCheck(inputField); if (fileCheck.isOutput) { Font font = nameLabel.getFont(); Font boldFont = new Font(font.getFontName(), Font.BOLD, font.getSize()); nameLabel.setFont(boldFont); } this.add(nameLabel, cc.xy(1, row)); // the rest of it int col = 3; if (isAtLeastOneAssignable(inputField.fieldType, String.class)) { if (inputField.guiHints != null && inputField.guiHints.startsWith(JGTConstants.MULTILINE_UI_HINT)) { handleTextArea(inputField, row, col, cc); } else if (inputField.guiHints != null && inputField.guiHints.startsWith(JGTConstants.COMBO_UI_HINT)) { handleComboField(inputField, row, col, cc); } else { handleTextField(inputField, row, col, cc, false, fileCheck); } } else if (isAtLeastOneAssignable(inputField.fieldType, Double.class, double.class)) { handleTextField(inputField, row, col, cc, true, fileCheck); } else if (isAtLeastOneAssignable(inputField.fieldType, Float.class, float.class)) { handleTextField(inputField, row, col, cc, true, fileCheck); } else if (isAtLeastOneAssignable(inputField.fieldType, Integer.class, int.class)) { handleTextField(inputField, row, col, cc, true, fileCheck); } else if (isAtLeastOneAssignable(inputField.fieldType, Short.class, short.class)) { handleTextField(inputField, row, col, cc, true, fileCheck); } else if (isAtLeastOneAssignable(inputField.fieldType, Boolean.class, boolean.class)) { handleBooleanField(inputField, row, col, cc); // } else if (isAtLeastOneAssignable(inputField.fieldType, GridCoverage2D.class)) { // handleGridcoverageInputField(inputField, row, col, cc); // } else if (isAtLeastOneAssignable(inputField.fieldType, GridGeometry2D.class)) { // handleGridgeometryInputField(inputField, row, col, cc); // } else if (isAtLeastOneAssignable(inputField.fieldType, // SimpleFeatureCollection.class)) { // handleFeatureInputField(inputField, row, col, cc); // } else if (isAtLeastOneAssignable(inputField.fieldType, HashMap.class)) { // handleHashMapInputField(inputField, row, col, cc); // } else if (isAtLeastOneAssignable(inputField.fieldType, List.class)) { // if (inputField.guiHints != null && // inputField.guiHints.equals(OmsBoxConstants.FILESPATHLIST_UI_HINT)) { // handleFilesPathListInputField(inputField, row, col, cc); // } else { // handleListInputField(inputField, row, col, cc); } row++; this.add(new JSeparator(JSeparator.HORIZONTAL), cc.xy(1, row)); this.add(new JSeparator(JSeparator.HORIZONTAL), cc.xy(2, row)); this.add(new JSeparator(JSeparator.HORIZONTAL), cc.xy(3, row)); row++; // row = row + 3; } } private TypeCheck getFileCheck( FieldData inputField ) { TypeCheck f = new TypeCheck(); String guiHints = inputField.guiHints; if (guiHints != null) { if (guiHints.contains(JGTConstants.FILEIN_UI_HINT)) { f.isFile = true; } else if (guiHints.contains(JGTConstants.FILEOUT_UI_HINT)) { f.isFile = true; f.isOutput = true; } else if (guiHints.contains(JGTConstants.FOLDERIN_UI_HINT)) { f.isFile = true; f.isFolder = true; } else if (guiHints.contains(JGTConstants.FOLDEROUT_UI_HINT)) { f.isFile = true; f.isFolder = true; f.isOutput = true; } else if (guiHints.contains(JGTConstants.CRS_UI_HINT)) { f.isCrs = true; } else if (guiHints.contains(JGTConstants.MAPCALC_UI_HINT)) { f.isMapcalc = true; } else if (guiHints.contains(SpatialToolboxConstants.GRASSFILE_UI_HINT)) { f.isGrassfile = true; } else if (guiHints.contains(JGTConstants.PROCESS_NORTH_UI_HINT)) { f.isProcessingNorth = true; } else if (guiHints.contains(JGTConstants.PROCESS_SOUTH_UI_HINT)) { f.isProcessingSouth = true; } else if (guiHints.contains(JGTConstants.PROCESS_WEST_UI_HINT)) { f.isProcessingWest = true; } else if (guiHints.contains(JGTConstants.PROCESS_EAST_UI_HINT)) { f.isProcessingEast = true; } else if (guiHints.contains(JGTConstants.PROCESS_COLS_UI_HINT)) { f.isProcessingCols = true; } else if (guiHints.contains(JGTConstants.PROCESS_ROWS_UI_HINT)) { f.isProcessingRows = true; } else if (guiHints.contains(JGTConstants.PROCESS_XRES_UI_HINT)) { f.isProcessingXres = true; } else if (guiHints.contains(JGTConstants.PROCESS_YRES_UI_HINT)) { f.isProcessingYres = true; } else if (guiHints.contains(JGTConstants.NORTHING_UI_HINT)) { f.isNorthing = true; } else if (guiHints.contains(JGTConstants.EASTING_UI_HINT)) { f.isEasting = true; } else if (guiHints.contains(JGTConstants.EASTINGNORTHING_UI_HINT)) { f.isEastingNorthing = true; } } return f; } private void handleTextField( FieldData inputField, int row, int col, CellConstraints cc, boolean onlyNumbers, TypeCheck typeCheck ) { String defaultFieldValue = inputField.fieldValue; if (!typeCheck.isFile) { JTextField textField; if (!onlyNumbers) { textField = new JTextField(); } else { NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.getDefault()); DecimalFormat decimalFormat = (DecimalFormat) numberFormat; decimalFormat.setGroupingUsed(false); textField = new JFormattedTextField(decimalFormat); } if (typeCheck.isEasting) { eastingListeningFields.add(textField); this.add(textField, cc.xy(col, row)); fieldName2ValueHolderMap.put(inputField.fieldName, textField); } else if (typeCheck.isNorthing) { northingListeningFields.add(textField); this.add(textField, cc.xy(col, row)); fieldName2ValueHolderMap.put(inputField.fieldName, textField); } else if (typeCheck.isCrs && guiBridge.supportsMapContext()) { JPanel subPanel = new JPanel(); subPanel.setLayout(new BorderLayout()); subPanel.add(textField, BorderLayout.CENTER); fieldName2ValueHolderMap.put(inputField.fieldName, textField); final JTextField fTextField = textField; JButton crsButton = new JButton("..."); subPanel.add(crsButton, BorderLayout.EAST); crsButton.addActionListener(new ActionListener(){ public void actionPerformed( ActionEvent e ) { String epsg = guiBridge.promptForCrs(); if (epsg != null) { fTextField.setText(epsg); } } }); this.add(subPanel, cc.xy(col, row)); } else { this.add(textField, cc.xy(col, row)); fieldName2ValueHolderMap.put(inputField.fieldName, textField); } textField.setText(defaultFieldValue); } else { boolean isVector = false; boolean isRaster = false; if (parentOmsClass != null && !typeCheck.isOutput) { try { Field field = parentOmsClass.getField(inputField.fieldName); if (field != null) { Class< ? > fieldClass = field.getType(); isVector = isAtLeastOneAssignable(fieldClass.getCanonicalName(), SimpleFeatureCollection.class); isRaster = isAtLeastOneAssignable(fieldClass.getCanonicalName(), GridCoverage2D.class); } } catch (Exception e) { e.printStackTrace(); } } if (isVector && (vectorLayers == null || vectorLayers.length == 0)) { isVector = false; } if (isRaster && (rasterLayers == null || rasterLayers.length == 0)) { isRaster = false; } if (isVector) { String[] tmpVectorLayers = new String[vectorLayers.length + 1]; tmpVectorLayers[0] = ""; System.arraycopy(vectorLayers, 0, tmpVectorLayers, 1, vectorLayers.length); JComboBox<String> comboBox = new JComboBox<String>(tmpVectorLayers); this.add(comboBox, cc.xy(col, row)); vectorComboList.add(comboBox); fieldName2ValueHolderMap.put(inputField.fieldName, comboBox); } else if (isRaster) { String[] tmpRasterLayers = new String[rasterLayers.length + 1]; tmpRasterLayers[0] = ""; System.arraycopy(rasterLayers, 0, tmpRasterLayers, 1, rasterLayers.length); JComboBox<String> comboBox = new JComboBox<String>(tmpRasterLayers); this.add(comboBox, cc.xy(col, row)); rasterComboList.add(comboBox); fieldName2ValueHolderMap.put(inputField.fieldName, comboBox); } else { JPanel subPanel = new JPanel(); this.add(subPanel, cc.xy(col, row)); subPanel.setLayout(new BorderLayout()); final JTextField textField = new JTextField(); subPanel.add(textField, BorderLayout.CENTER); fieldName2ValueHolderMap.put(inputField.fieldName, textField); JButton browseButton = new JButton("..."); subPanel.add(browseButton, BorderLayout.EAST); if (!typeCheck.isFolder && !typeCheck.isOutput) { // input file browseButton.addActionListener(new ActionListener(){ public void actionPerformed( ActionEvent e ) { File[] files = guiBridge.showOpenFileDialog("Select input file", GuiUtilities.getLastFile()); setSelectedFile(textField, files); } }); } else if (!typeCheck.isFolder && typeCheck.isOutput) { outputFieldNames.add(inputField.fieldName); // output file browseButton.addActionListener(new ActionListener(){ public void actionPerformed( ActionEvent e ) { File[] files = guiBridge.showSaveFileDialog("Select file to save", GuiUtilities.getLastFile()); setSelectedFile(textField, files); } }); } else if (typeCheck.isFolder && !typeCheck.isOutput) { // input folder browseButton.addActionListener(new ActionListener(){ public void actionPerformed( ActionEvent e ) { File[] files = guiBridge.showOpenDirectoryDialog("Select folder", GuiUtilities.getLastFile()); setSelectedFile(textField, files); } }); } else if (typeCheck.isFolder && typeCheck.isOutput) { outputFieldNames.add(inputField.fieldName); // output folder browseButton.addActionListener(new ActionListener(){ public void actionPerformed( ActionEvent e ) { File[] files = guiBridge.showOpenDirectoryDialog("Select folder", GuiUtilities.getLastFile()); setSelectedFile(textField, files); } }); } textField.setText(defaultFieldValue); } } } private void setSelectedFile( final JTextField textField, File[] files ) { if (files != null && files.length > 0) { final File gpapFile = files[0]; GuiUtilities.setLastPath(gpapFile.getAbsolutePath()); textField.setText(gpapFile.getAbsolutePath()); } } private void handleTextArea( FieldData inputField, int row, int col, CellConstraints cc ) { String hint = extractSingleGuiHint(JGTConstants.MULTILINE_UI_HINT, inputField.guiHints); String rowsStr = hint.replaceFirst(JGTConstants.MULTILINE_UI_HINT, ""); int areaRows = Integer.parseInt(rowsStr); JTextArea textArea = new JTextArea(); textArea.setRows(areaRows); this.add(textArea, cc.xy(col, row)); fieldName2ValueHolderMap.put(inputField.fieldName, textArea); textArea.setText(inputField.fieldValue); } private void handleBooleanField( FieldData inputField, int row, int col, CellConstraints cc ) { JCheckBox checkBox = new JCheckBox(""); this.add(checkBox, cc.xy(col, row)); fieldName2ValueHolderMap.put(inputField.fieldName, checkBox); boolean select = inputField.fieldValue.equalsIgnoreCase("true") ? true : false; checkBox.setSelected(select); } private void handleComboField( FieldData inputField, int row, int col, CellConstraints cc ) { String[] guiHintsSplit = inputField.guiHints.split(";"); String[] imtemsSplit = new String[]{" - "}; for( String guiHint : guiHintsSplit ) { if (guiHint.startsWith(JGTConstants.COMBO_UI_HINT)) { String items = guiHint.replaceFirst(JGTConstants.COMBO_UI_HINT, "").replaceFirst(":", "").trim(); imtemsSplit = items.split(","); break; } } JComboBox<String> comboBox = new JComboBox<String>(imtemsSplit); this.add(comboBox, cc.xy(col, row)); fieldName2ValueHolderMap.put(inputField.fieldName, comboBox); if (inputField.fieldValue.length() > 0) { comboBox.setSelectedItem(inputField.fieldValue); } } /** * Checks if one class is assignable from at least one of the others. * * @param main the canonical name of class to check. * @param classes the other classes. * @return true if at least one of the other classes match. */ private boolean isAtLeastOneAssignable( String main, Class< ? >... classes ) { for( Class< ? > clazz : classes ) { if (clazz.getCanonicalName().equals(main)) { return true; } } return false; } private String extractSingleGuiHint( String pattern, String guiHints ) { String[] split = guiHints.split(","); for( String hint : split ) { hint = hint.trim(); if (hint.contains(pattern)) { return hint; } } return null; } public void clear() { this.removeAll(); eastingListeningFields.clear(); northingListeningFields.clear(); fieldName2ValueHolderMap.clear(); outputFieldNames.clear(); rasterComboList.clear(); vectorComboList.clear(); } public void freeResources() { } public void mouseClicked( MouseEvent e ) { if (!guiBridge.supportsMapContext()) { return; } int x = e.getX(); int y = e.getY(); Point2D mapPoint = guiBridge.getWorldPoint(x, y); if (mapPoint != null) { for( JTextField textField : eastingListeningFields ) { textField.setText("" + mapPoint.getX()); } for( JTextField textField : northingListeningFields ) { textField.setText("" + mapPoint.getY()); } } } public void mousePressed( MouseEvent e ) { } public void mouseReleased( MouseEvent e ) { } public void mouseEntered( MouseEvent e ) { } public void mouseExited( MouseEvent e ) { } }