/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2008-2011, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.swing.process;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.geotools.process.ProcessFactory;
import org.geotools.process.Processors;
import org.geotools.swing.wizard.JPage;
import org.opengis.feature.type.Name;
import org.opengis.util.InternationalString;
/**
* This page is responsible for making a process selection widget that moves onto to the selected
* process page.
*
* @author gdavis (Refractions)
* @since 8.0
*
* @source $URL$
* @version $Id$
*/
public class ProcessSelectionPage extends JPage {
/**
* This is an initial set of input parameters; which can be used to help find an initial
* "matching" process.
*/
Map<String, Object> input;
/** List of available processes */
JTree processList;
/**
* This set of process factories avaialble (mostly an internal detail).
*/
Set<ProcessFactory> processFactories;
/** Description of the current process */
JTextField descLabel;
/** The currently selected factory responsible for describing a process */
ProcessFactory selectedFactory;
private Name selectedName;
final static String defaultDesc = "Select a process to see its description";
public ProcessSelectionPage() {
this(null);
}
public ProcessSelectionPage(Map<String, Object> input) {
super("process selection");
this.input = input;
processFactories = Processors.getProcessFactories();
selectedFactory = null;
}
public String getBackPageIdentifier() {
return null;
}
public String getNextPageIdentifier() {
if (selectedFactory == null) {
return null;
}
ProcessParameterPage inputPage = new ProcessParameterPage(selectedFactory);
this.getJWizard().registerWizardPanel(inputPage);
return inputPage.getPageIdentifier();
}
public void aboutToDisplayPanel() {
JPanel page = getPanel();
page.removeAll();
GridBagLayout gridBag = new GridBagLayout();
page.setLayout(gridBag);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.ipadx = 5;
c.ipady = 5;
JLabel title = new JLabel("Process Selection");
title.setFont(new Font("Arial", Font.BOLD, 14));
c.gridx = 0;
c.gridy = 0;
gridBag.setConstraints(title, c);
page.add(title);
JLabel description = new JLabel("Select a Process and click 'Next'");
description.setFont(new Font("Arial", Font.PLAIN, 11));
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 2;
c.ipady = 20;
gridBag.setConstraints(description, c);
page.add(description);
JLabel label1 = new JLabel("Process:");
label1.setFont(new Font("Arial", Font.BOLD, 12));
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 1;
c.ipady = 5;
gridBag.setConstraints(label1, c);
page.add(label1);
JLabel label2 = new JLabel("Process Description:");
label2.setFont(new Font("Arial", Font.BOLD, 12));
c.gridx = 1;
c.gridy = 2;
gridBag.setConstraints(label2, c);
page.add(label2);
TreeModel data = createFactoryTitleArray(processFactories);
processList = new JTree(data);
processList.setFont(new Font("Arial", Font.PLAIN, 12));
processList.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
processList.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
TreePath path = e.getNewLeadSelectionPath();
if (path.getLastPathComponent() instanceof Name) {
Name name = (Name) path.getLastPathComponent();
ProcessFactory factory = (ProcessFactory) path.getParentPath()
.getLastPathComponent();
updateProcessDesc(factory, name);
}
}
});
c.gridx = 0;
c.gridy = 3;
gridBag.setConstraints(processList, c);
page.add(processList);
descLabel = new JTextField(defaultDesc, 35);
descLabel.setEditable(false);
Border border = new LineBorder(this.getPanel().getBackground(), 0);
descLabel.setBorder(border);
descLabel.setFont(new Font("Arial", Font.PLAIN, 11));
c.gridx = 1;
c.gridy = 3;
gridBag.setConstraints(descLabel, c);
page.add(descLabel);
/*
* ParamWidget widget; widget = new JField( parameter ); JComponent field =
* widget.doLayout(); page.add(processList); fields.put( parameter.key, widget );
*/
}
/**
* Populates an array of strings with the process factory titles based on the factory set
*
* @param processFactories2 the string array to populate
* @return
*/
private TreeModel createFactoryTitleArray(Set<ProcessFactory> factories) {
final List<ProcessFactory> root = new ArrayList<ProcessFactory>();
final Map<ProcessFactory, List<Name>> branch = new HashMap<ProcessFactory, List<Name>>();
root.addAll(factories);
Collections.sort(root, new Comparator<ProcessFactory>() {
@Override
public int compare(ProcessFactory o1, ProcessFactory o2) {
String s1 = o1.getTitle().toString();
String s2 = o2.getTitle().toString();
return s1.compareTo(s2);
}
});
return new TreeModel() {
@Override
public Object getRoot() {
return root;
}
List<Name> getChildren(ProcessFactory factory) {
synchronized (factory) {
List<Name> list = branch.get(factory);
if (list == null) {
list = new ArrayList<Name>();
list.addAll(factory.getNames());
Collections.sort(list, new Comparator<Name>() {
@Override
public int compare(Name o1, Name o2) {
String s1 = o1.toString();
String s2 = o2.toString();
return s1.compareTo(s2);
}
});
branch.put(factory, list);
}
return list;
}
}
@Override
public Object getChild(Object parent, int index) {
if (parent == root) {
return root.get(index);
} else if (parent instanceof ProcessFactory) {
ProcessFactory factory = (ProcessFactory) parent;
return getChildren(factory).get(index);
}
return null;
}
@Override
public int getChildCount(Object parent) {
if (parent == root) {
return root.size();
} else if (parent instanceof ProcessFactory) {
ProcessFactory factory = (ProcessFactory) parent;
return getChildren(factory).size();
}
return 0;
}
@Override
public boolean isLeaf(Object node) {
if (node == root) {
return false;
} else if (node instanceof ProcessFactory) {
return false;
} else if (node instanceof Name) {
return true;
}
return true;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
// our tree is not editable
}
@Override
public int getIndexOfChild(Object parent, Object child) {
if (parent == root) {
return root.indexOf(child);
} else if (parent instanceof ProcessFactory) {
ProcessFactory factory = (ProcessFactory) parent;
return getChildren(factory).indexOf(child);
}
return 0;
}
@Override
public void addTreeModelListener(TreeModelListener l) {
// our tree is not editable
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
// our tree is not editable
}
};
}
/**
* Returns the first instance of a ProcssFactory in the factories set that has a title matching
* the given title.
*
* @param title
* @return ProcessFactory instance
*/
private ProcessFactory findProcessFactoryByTitle(String title) {
Iterator<ProcessFactory> iterator = processFactories.iterator();
while (iterator.hasNext()) {
ProcessFactory fac = iterator.next();
if (fac.getTitle().toString().equalsIgnoreCase(title)) {
return fac;
}
}
return null;
}
/**
* Update the process description based on the selected process
*
* @param selection title of selected process
* @param name
*/
private void updateProcessDesc(ProcessFactory factory, Name name) {
if (name == null || factory == null) {
return;
}
InternationalString title = factory.getTitle(name);
InternationalString description = factory.getDescription(name);
descLabel.setText(defaultDesc);
selectedFactory = factory;
selectedName = name;
updateNavButtons();
descLabel.setText("<html><b>"+title+"</b>"+description);
updateNavButtons();
}
/**
* Update the wizard nav buttons based on what process factory is selected and if the form is
* validated to move to the next page or not
*/
private void updateNavButtons() {
this.getJWizard().getController().syncButtonsToPage();
}
}