/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2007 - 2008, Open Source Geospatial Foundation (OSGeo) * (C) 2008 - 2011, Johann Sorel * * 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.geotoolkit.gui.swing.crschooser; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.Polygon; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.logging.Level; import javax.measure.Unit; import javax.swing.*; import javax.swing.GroupLayout.Alignment; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.geotoolkit.data.FeatureStoreUtilities; import org.geotoolkit.data.FeatureCollection; import org.geotoolkit.display2d.GO2Hints; import org.geotoolkit.display2d.canvas.painter.BackgroundPainter; import org.geotoolkit.display2d.canvas.painter.BackgroundPainterGroup; import org.geotoolkit.display2d.canvas.painter.SolidColorPainter; import org.geotoolkit.display2d.ext.grid.DefaultGridTemplate; import org.geotoolkit.display2d.ext.grid.GridPainter; import org.geotoolkit.display2d.ext.grid.GridTemplate; import org.geotoolkit.factory.FactoryFinder; import org.geotoolkit.factory.Hints; import org.geotoolkit.gui.swing.render2d.JMap2D; import org.geotoolkit.gui.swing.render2d.control.JNavigationBar; import org.geotoolkit.gui.swing.render2d.control.navigation.PanHandler; import org.geotoolkit.gui.swing.resource.MessageBundle; import org.geotoolkit.io.X364; import org.apache.sis.measure.Units; import org.apache.sis.io.wkt.Colors; import org.geotoolkit.io.wkt.WKTFormat; import org.geotoolkit.map.MapBuilder; import org.geotoolkit.map.MapContext; import org.geotoolkit.map.MapLayer; import org.geotoolkit.referencing.CRS; import org.geotoolkit.referencing.ReferencingUtilities; import org.apache.sis.referencing.CommonCRS; import org.apache.sis.util.Classes; import org.geotoolkit.resources.Vocabulary; import org.geotoolkit.style.MutableStyle; import org.geotoolkit.style.MutableStyleFactory; import org.geotoolkit.style.StyleConstants; import org.opengis.filter.FilterFactory; import org.opengis.filter.expression.Expression; import org.opengis.geometry.Envelope; import org.opengis.util.FactoryException; import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.style.Description; import org.opengis.style.LineSymbolizer; import org.apache.sis.io.wkt.Warnings; import org.apache.sis.util.logging.Logging; import org.opengis.feature.Feature; import org.opengis.feature.FeatureType; /** * CRSChooser component * * @author Johann Sorel * @module */ public class JCRSChooser extends javax.swing.JDialog { public static enum ACTION { APPROVE, CANCEL, CLOSE } private JCRSList liste; private ACTION exitmode = ACTION.CLOSE; private CoordinateReferenceSystem crs = null; public static JCRSChooser create(final Window parent, final boolean modal) { if(parent instanceof JFrame){ return new JCRSChooser((JFrame)parent, modal); }else if(parent instanceof JDialog){ return new JCRSChooser((JDialog)parent, modal); }else{ return new JCRSChooser(modal); } } /** Creates new form JCRSChooser * @param parent * @param modal */ public JCRSChooser(final JDialog parent, final boolean modal) { super(parent, modal); init(); } /** Creates new form JCRSChooser * @param parent * @param modal */ public JCRSChooser(final JFrame parent, final boolean modal) { super(parent, modal); init(); } /** Creates new form JCRSChooser * @param parent * @param modal */ public JCRSChooser(final Frame parent, final boolean modal) { super(parent, modal); init(); } /** Creates new form JCRSChooser * @param parent * @param modal */ public JCRSChooser(final boolean modal) { super(); setModal(modal); init(); } private void init(){ initComponents(); final JLabel lbl = new JLabel(MessageBundle.format("loading")); lbl.setHorizontalAlignment(SwingConstants.CENTER); lbl.setVerticalAlignment(SwingConstants.CENTER); lbl.setHorizontalTextPosition(SwingConstants.CENTER); pan_list.add(BorderLayout.CENTER,lbl); new Thread(){ @Override public void run() { liste = new JCRSList(); liste.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { IdentifiedObject item; try { item = liste.getSelectedItem(); } catch (FactoryException ex) { String message = ex.getLocalizedMessage(); if (message == null) { message = Classes.getShortClassName(ex); } setErrorMessage(message); return; } setIdentifiedObject(item); } }); pan_list.removeAll(); pan_list.add(BorderLayout.CENTER, liste); pan_list.revalidate(); pan_list.repaint(); if(crs != null){ liste.setCRS(crs); } } }.start(); wktArea.setEditable(false); wktArea.setContentType("text/html"); guiMap.getCanvas().setRenderingHint(GO2Hints.KEY_GENERALIZE, false); guiMap.getCanvas().setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); guiMap.getContainer().setContext(MapBuilder.createContext()); guiNav.setMap(guiMap); guiMap.setHandler(new PanHandler(guiMap,false)); GridTemplate gridTemplate = new DefaultGridTemplate( CommonCRS.WGS84.normalizedGeographic(), new BasicStroke(1.2f), new Color(120,120,120,200), new BasicStroke(1,BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 3, new float[]{5,5}, 0), new Color(120,120,120,60), new Font("serial", Font.BOLD, 10),Color.GRAY,0,Color.WHITE, new Font("serial", Font.ITALIC, 8),Color.GRAY,0,Color.WHITE); BackgroundPainter bgWhite = new SolidColorPainter(Color.WHITE); guiMap.getCanvas().setBackgroundPainter(BackgroundPainterGroup.wrap(bgWhite ,new GridPainter(gridTemplate))); guiForceLongitudeFirst.setSelected(true); } public void setCRS(final CoordinateReferenceSystem crs) { this.crs = crs; if (crs != null) { String epsg = crs.getName().toString(); gui_jtf_crs.setText(epsg); setIdentifiedObject(crs); } } public CoordinateReferenceSystem getCRS() { if(liste != null){ CoordinateReferenceSystem crs = liste.getCRS(); if(guiForceLongitudeFirst.isSelected()){ try { crs = ReferencingUtilities.setLongitudeFirst(crs); } catch (FactoryException ex) { Logging.getLogger("org.geotoolkit.gui.swing.crschooser").log(Level.SEVERE, null, ex); } } return crs; }else{ return crs; } } private void setIdentifiedObject(final IdentifiedObject item) { final WKTFormat formatter = new WKTFormat(); formatter.setColors(Colors.DEFAULT); final StringBuilder buffer = new StringBuilder(); /* * Set the Well Known Text (WKT) panel using the following steps: * * 1) Write the warning if there is one. * 2) Replace the X3.64 escape sequences by HTML colors. * 3) Turn quoted WKT names ("foo") in italic characters. */ buffer.setLength(0); buffer.append("<html>"); String text, warning; try { text = formatter.format(item); Warnings w = formatter.getWarnings(); warning = (w != null) ? w.toString() : null; } catch (RuntimeException e) { text = String.valueOf((item!=null)?item.getName():""); warning = e.getLocalizedMessage(); } if (warning != null) { buffer.append("<p><b>").append(Vocabulary.format(Vocabulary.Keys.Warning)) .append(":</b> ").append(warning).append("</p><hr>\n"); } buffer.append("<pre>"); // '\u001A' is the SUBSTITUTE character. We use it as a temporary replacement for avoiding // confusion between WKT quotes and HTML quotes while we search for text to make italic. makeItalic(X364.toHTML(text.replace('"', '\u001A')), buffer, '\u001A'); wktArea.setText(buffer.append("</pre></html>").toString()); //update map area final MapContext ctx = guiMap.getContainer().getContext(); ctx.layers().clear(); if(item instanceof CoordinateReferenceSystem){ final Envelope env = CRS.getEnvelope((CoordinateReferenceSystem)item); if(env != null){ final FeatureTypeBuilder ftb = new FeatureTypeBuilder(); ftb.setName("validity"); ftb.addAttribute(Polygon.class).setName("geom").setCRS(env.getCoordinateReferenceSystem()); final FeatureType type = ftb.build(); final GeometryFactory GF = new GeometryFactory(); final FilterFactory FF = FactoryFinder.getFilterFactory(null); final MutableStyleFactory SF = (MutableStyleFactory) FactoryFinder.getStyleFactory( new Hints(Hints.STYLE_FACTORY, MutableStyleFactory.class)); final LinearRing ring = GF.createLinearRing(new Coordinate[]{ new Coordinate(env.getMinimum(0), env.getMinimum(1)), new Coordinate(env.getMinimum(0), env.getMaximum(1)), new Coordinate(env.getMaximum(0), env.getMaximum(1)), new Coordinate(env.getMaximum(0), env.getMinimum(1)), new Coordinate(env.getMinimum(0), env.getMinimum(1))}); final Polygon polygon = GF.createPolygon(ring, new LinearRing[0]); final Feature feature = type.newInstance(); feature.setPropertyValue("geom",polygon); final FeatureCollection col = FeatureStoreUtilities.collection(feature); //general informations final String name = "mySymbol"; final Description desc = StyleConstants.DEFAULT_DESCRIPTION; final String geometry = null; //use the default geometry of the feature final Unit unit = Units.POINT; final Expression offset = StyleConstants.LITERAL_ZERO_FLOAT; //the visual element final Expression color = SF.literal(Color.BLUE); final Expression width = FF.literal(2); final Expression opacity = StyleConstants.LITERAL_ONE_FLOAT; final org.opengis.style.Stroke stroke = SF.stroke(color,width,opacity); final LineSymbolizer symbolizer = SF.lineSymbolizer(name,geometry,desc,unit,stroke,offset); final MutableStyle style = SF.style(symbolizer); final MapLayer layer = MapBuilder.createFeatureLayer(col, style); ctx.layers().add(layer); try { guiMap.getCanvas().setVisibleArea(env); } catch (Exception ex) { ex.printStackTrace(); } } } } /** * Copies the given text in the given buffer, while putting the quoted text in italic. * The quote character is given by the {@code quote} argument and will be replaced by * the usual {@code "} character. */ private static void makeItalic(final String text, final StringBuilder buffer, final char quote) { boolean isQuoting = false; int last = 0; for (int i=text.indexOf(quote); i>=0; i=text.indexOf(quote, last)) { buffer.append(text.substring(last, i)).append(isQuoting ? "</cite>\"" : "\"<cite>"); isQuoting = !isQuoting; last = i+1; } buffer.append(text.substring(last)); } /** * Sets an error message to display instead of the current identified object. * * @param message The error message. */ private void setErrorMessage(final String message) { wktArea.setText("<html>"+Vocabulary.format(Vocabulary.Keys.Error_1, message)+"</html>"); } public ACTION showDialog() { exitmode = ACTION.CLOSE; pack(); setLocationRelativeTo(null); setVisible(true); return exitmode; } /** 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. */ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jTabbedPane1 = new JTabbedPane(); jPanel1 = new JPanel(); jLabel1 = new JLabel(); gui_jtf_crs = new JTextField(); pan_list = new JPanel(); guiForceLongitudeFirst = new JCheckBox(); jPanel2 = new JPanel(); jScrollPane2 = new JScrollPane(); wktArea = new JEditorPane(); jPanel3 = new JPanel(); guiMap = new JMap2D(); guiNav = new JNavigationBar(); but_valider = new JButton(); but_fermer = new JButton(); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setTitle(MessageBundle.format("crschooser_title")); jLabel1.setText(MessageBundle.format("crschooser_crs")); gui_jtf_crs.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { gui_jtf_crsActionPerformed(evt); } }); gui_jtf_crs.addKeyListener(new KeyAdapter() { public void keyTyped(KeyEvent evt) { gui_jtf_crsKeyTyped(evt); } }); pan_list.setLayout(new BorderLayout()); guiForceLongitudeFirst.setText(MessageBundle.format("force_longitude_first")); GroupLayout jPanel1Layout = new GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(Alignment.LEADING) .addGroup(Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(Alignment.TRAILING) .addComponent(pan_list, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 429, Short.MAX_VALUE) .addComponent(gui_jtf_crs, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 436, Short.MAX_VALUE) .addComponent(jLabel1, Alignment.LEADING) .addComponent(guiForceLongitudeFirst, Alignment.LEADING)) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() .addComponent(jLabel1) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(gui_jtf_crs, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(guiForceLongitudeFirst) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(pan_list, GroupLayout.DEFAULT_SIZE, 176, Short.MAX_VALUE) .addContainerGap()) ); jTabbedPane1.addTab(MessageBundle.format("crschooser_list"), jPanel1); jScrollPane2.setViewportView(wktArea); GroupLayout jPanel2Layout = new GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( jPanel2Layout.createParallelGroup(Alignment.LEADING) .addComponent(jScrollPane2) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(Alignment.LEADING) .addComponent(jScrollPane2, GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE) ); jTabbedPane1.addTab(MessageBundle.format("crschooser_wkt"), jPanel2); jPanel3.setLayout(new BorderLayout()); jPanel3.add(guiMap, BorderLayout.CENTER); guiNav.setFloatable(false); guiNav.setOrientation(1); guiNav.setRollover(true); jPanel3.add(guiNav, BorderLayout.EAST); jTabbedPane1.addTab(MessageBundle.format("area_validity"), jPanel3); but_valider.setText(MessageBundle.format("crschooser_apply")); but_valider.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { but_valideractionAjouter(evt); } }); but_fermer.setText(MessageBundle.format("crschooser_cancel")); but_fermer.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { but_fermeractionFermer(evt); } }); GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(Alignment.LEADING) .addGroup(Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(but_valider) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(but_fermer) .addContainerGap()) .addComponent(jTabbedPane1) ); layout.setVerticalGroup( layout.createParallelGroup(Alignment.LEADING) .addGroup(Alignment.TRAILING, layout.createSequentialGroup() .addComponent(jTabbedPane1) .addPreferredGap(ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(Alignment.BASELINE) .addComponent(but_fermer) .addComponent(but_valider)) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents private void gui_jtf_crsActionPerformed(final ActionEvent evt) {//GEN-FIRST:event_gui_jtf_crsActionPerformed liste.searchCRS(gui_jtf_crs.getText()); }//GEN-LAST:event_gui_jtf_crsActionPerformed private void gui_jtf_crsKeyTyped(final KeyEvent evt) {//GEN-FIRST:event_gui_jtf_crsKeyTyped liste.searchCRS(gui_jtf_crs.getText()); }//GEN-LAST:event_gui_jtf_crsKeyTyped private void but_valideractionAjouter(final ActionEvent evt) {//GEN-FIRST:event_but_valideractionAjouter exitmode = ACTION.APPROVE; dispose(); }//GEN-LAST:event_but_valideractionAjouter private void but_fermeractionFermer(final ActionEvent evt) {//GEN-FIRST:event_but_fermeractionFermer exitmode = ACTION.CANCEL; dispose(); }//GEN-LAST:event_but_fermeractionFermer // Variables declaration - do not modify//GEN-BEGIN:variables private JButton but_fermer; private JButton but_valider; private JCheckBox guiForceLongitudeFirst; private JMap2D guiMap; private JNavigationBar guiNav; private JTextField gui_jtf_crs; private JLabel jLabel1; private JPanel jPanel1; private JPanel jPanel2; private JPanel jPanel3; private JScrollPane jScrollPane2; private JTabbedPane jTabbedPane1; private JPanel pan_list; private JEditorPane wktArea; // End of variables declaration//GEN-END:variables }