/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012, Geomatys
*
* 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 3 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.geotoolkit.gui.swing.chooser;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.image.BufferedImage;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.geotoolkit.client.Client;
import org.geotoolkit.client.ClientFactory;
import org.geotoolkit.storage.coverage.CoverageStoreFactory;
import org.geotoolkit.data.FeatureStoreFactory;
import org.geotoolkit.data.FileFeatureStoreFactory;
import org.geotoolkit.data.AbstractFolderFeatureStoreFactory;
import org.geotoolkit.gui.swing.util.JOptionDialog;
import org.geotoolkit.gui.swing.propertyedit.featureeditor.PropertyValueEditor;
import org.geotoolkit.gui.swing.resource.IconBundle;
import org.geotoolkit.gui.swing.resource.MessageBundle;
import org.geotoolkit.map.MapLayer;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.util.logging.Logging;
import org.geotoolkit.gui.swing.parameters.editor.JParameterValuesEditor;
import org.geotoolkit.storage.DataStores;
import org.jdesktop.swingx.combobox.ListComboBoxModel;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import org.opengis.parameter.ParameterValueGroup;
/**
* Panel allowing to choose a server and configure it among the
* declared ServerFactories.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class JServerChooser extends javax.swing.JPanel {
private static final Logger LOGGER = Logging.getLogger("org.geotoolkit.gui.swing.chooser");
private static final Comparator<ClientFactory> SORTER = new Comparator<ClientFactory>() {
@Override
public int compare(ClientFactory o1, ClientFactory o2) {
return o1.getDisplayName().toString().compareTo(o2.getDisplayName().toString());
}
};
private final JParameterValuesEditor guiEditor = new JParameterValuesEditor();
private final JLayerChooser chooser = new JLayerChooser();
public JServerChooser() {
initComponents();
guiEditPane.add(BorderLayout.CENTER,guiEditor);
guiEditor.setHelpVisible(false);
final List<ClientFactory> factories = new ArrayList<>(DataStores.getAvailableFactories(ClientFactory.class));
Collections.sort(factories, SORTER);
guiList.setHighlighters(HighlighterFactory.createAlternateStriping() );
guiList.setModel(new ListComboBoxModel(factories));
guiList.setCellRenderer(new FactoryCellRenderer());
guiList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
final ClientFactory factory = (ClientFactory) guiList.getSelectedValue();
final ParameterValueGroup param = factory.getParametersDescriptor().createValue();
guiEditor.setParameterValue(param);
}
});
setLayerSelectionVisible(false);
}
public void setLayerSelectionVisible(boolean visible){
if(visible){
guiSplit.setRightComponent(guiLayerSplit);
guiLayerSplit.setLeftComponent(guiConfig);
guiLayerSplit.setRightComponent(chooser);
guiLayerSplit.setDividerLocation(260);
}else{
guiSplit.setRightComponent(guiConfig);
}
}
public Client getServer() throws DataStoreException{
final ClientFactory factory = (ClientFactory) guiList.getSelectedValue();
if(factory == null){
return null;
}
final ParameterValueGroup param = (ParameterValueGroup) guiEditor.getParameterValue();
return (Client) factory.open(param);
}
public List<MapLayer> getSelectedLayers() throws DataStoreException{
return chooser.getLayers();
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
guiLayerSplit = new javax.swing.JSplitPane();
guiSplit = new javax.swing.JSplitPane();
guiConfig = new javax.swing.JPanel();
guiEditPane = new javax.swing.JPanel();
guiInfoLabel = new javax.swing.JTextField();
guiConnect = new javax.swing.JButton();
scr = new javax.swing.JScrollPane();
guiList = new org.jdesktop.swingx.JXList();
guiLayerSplit.setDividerSize(5);
guiSplit.setDividerLocation(240);
guiSplit.setDividerSize(5);
guiEditPane.setLayout(new java.awt.BorderLayout());
guiInfoLabel.setEditable(false);
guiConnect.setText(MessageBundle.format("chooserserver_connect")); // NOI18N
guiConnect.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
guiConnectActionPerformed(evt);
}
});
javax.swing.GroupLayout guiConfigLayout = new javax.swing.GroupLayout(guiConfig);
guiConfig.setLayout(guiConfigLayout);
guiConfigLayout.setHorizontalGroup(
guiConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, guiConfigLayout.createSequentialGroup()
.addComponent(guiInfoLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(guiConnect))
.addComponent(guiEditPane, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
);
guiConfigLayout.setVerticalGroup(
guiConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, guiConfigLayout.createSequentialGroup()
.addComponent(guiEditPane, javax.swing.GroupLayout.DEFAULT_SIZE, 370, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(guiConfigLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(guiInfoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(guiConnect)))
);
guiSplit.setRightComponent(guiConfig);
scr.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scr.setViewportView(guiList);
guiSplit.setLeftComponent(scr);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(guiSplit, javax.swing.GroupLayout.DEFAULT_SIZE, 646, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(guiSplit)
);
}// </editor-fold>//GEN-END:initComponents
private void guiConnectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_guiConnectActionPerformed
Client store = null;
try {
chooser.setSource(null);
store = getServer();
chooser.setSource(store);
guiInfoLabel.setForeground(Color.GREEN);
guiInfoLabel.setText(MessageBundle.format("chooserserver_ok"));
} catch (DataStoreException ex) {
guiInfoLabel.setForeground(Color.RED);
guiInfoLabel.setText(""+ex.getMessage());
LOGGER.log(Level.WARNING, ex.getMessage(),ex);
}
}//GEN-LAST:event_guiConnectActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel guiConfig;
private javax.swing.JButton guiConnect;
private javax.swing.JPanel guiEditPane;
private javax.swing.JTextField guiInfoLabel;
private javax.swing.JSplitPane guiLayerSplit;
private org.jdesktop.swingx.JXList guiList;
private javax.swing.JSplitPane guiSplit;
private javax.swing.JScrollPane scr;
// End of variables declaration//GEN-END:variables
/**
* Display a modal dialog.
*
* @return
* @throws DataStoreException
*/
public static List<Client> showDialog(Component parent) throws DataStoreException{
return showDialog(parent,Collections.EMPTY_LIST);
}
/**
* Display a modal dialog choosing layers.
*
* @param editors : additional FeatureOutline editors
* @return
* @throws DataStoreException
*/
public static List<MapLayer> showLayerDialog(Component parent, List<PropertyValueEditor> editors) throws DataStoreException{
return showDialog(parent,editors, true);
}
/**
* Display a modal dialog.
*
* @param editors : additional FeatureOutline editors
* @return
* @throws DataStoreException
*/
public static List<Client> showDialog(Component parent, List<PropertyValueEditor> editors) throws DataStoreException{
return showDialog(parent,editors, false);
}
private static List showDialog(Component parent, List<PropertyValueEditor> editors, boolean layerVisible) throws DataStoreException{
final JServerChooser chooser = new JServerChooser();
if(editors != null){
chooser.guiEditor.setAvailableEditors(editors);
}
chooser.setLayerSelectionVisible(layerVisible);
final int res = JOptionDialog.show(parent, chooser, JOptionPane.OK_OPTION);
if (JOptionPane.OK_OPTION == res) {
if (layerVisible) {
return chooser.getSelectedLayers();
} else {
final Client store = chooser.getServer();
if (store == null) {
return Collections.EMPTY_LIST;
} else {
return Collections.singletonList(store);
}
}
} else {
return Collections.EMPTY_LIST;
}
}
static class FactoryCellRenderer extends DefaultListCellRenderer{
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
final JLabel lbl = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
String name = "";
String desc = "";
if(value instanceof ClientFactory){
final ClientFactory factory = (ClientFactory) value;
name = String.valueOf(factory.getDisplayName());
desc = String.valueOf(factory.getDescription());
}else if(value instanceof FeatureStoreFactory){
final FeatureStoreFactory factory = (FeatureStoreFactory) value;
name = String.valueOf(factory.getDisplayName());
desc = String.valueOf(factory.getDescription());
}else if(value instanceof CoverageStoreFactory){
final CoverageStoreFactory factory = (CoverageStoreFactory) value;
name = String.valueOf(factory.getDisplayName());
desc = String.valueOf(factory.getDescription());
}
final String txt = "<html><b>"+name+"</b><br/>"
+ "<font size=\"0.5em\"><i>    "+desc+"</i></font></html>";
lbl.setText(txt);
lbl.setIcon(findIcon(value));
return lbl;
}
}
private static final ImageIcon EMPTY_24 = new ImageIcon(new BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB));
private static ImageIcon findIcon(Object candidate){
ImageIcon icon = EMPTY_24;
String name = "";
if(candidate instanceof ClientFactory){
name = ((ClientFactory)candidate).getDisplayName().toString().toLowerCase();
icon = IconBundle.getIcon("24_server");
}else if(candidate instanceof CoverageStoreFactory){
name = ((CoverageStoreFactory)candidate).getDisplayName().toString().toLowerCase();
icon = IconBundle.getIcon("24_folder_img");
}else if(candidate instanceof FeatureStoreFactory){
name = ((FeatureStoreFactory)candidate).getDisplayName().toString().toLowerCase();
icon = IconBundle.getIcon("24_store");
}
final String classname = candidate.getClass().getName().toLowerCase();
//knowned cases
if(name.contains("google")){
icon = IconBundle.getIcon("24_google");
}else if(name.contains("osm")){
icon = IconBundle.getIcon("24_osm");
}else if(name.contains("orient")){
icon = IconBundle.getIcon("24_orientdb");
}else if(name.contains("ign")){
icon = IconBundle.getIcon("24_ign");
}else if(name.contains("ogc")){
icon = IconBundle.getIcon("24_ogc");
}else if(classname.contains("coveragesql")){
icon = IconBundle.getIcon("24_database");
}else if(classname.contains("mysql")){
icon = IconBundle.getIcon("24_database");
}else if(classname.contains("post")){
icon = IconBundle.getIcon("24_database");
}else if(candidate instanceof AbstractFolderFeatureStoreFactory){
icon = IconBundle.getIcon("24_folder_doc");
}else if(candidate instanceof FileFeatureStoreFactory){
icon = IconBundle.getIcon("24_doc");
}
return icon;
}
}