001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.io.session;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.awt.CardLayout;
007    import java.awt.Component;
008    import java.awt.Font;
009    import java.awt.GridBagLayout;
010    import java.awt.event.ActionEvent;
011    import java.awt.event.ActionListener;
012    import java.awt.event.ItemEvent;
013    import java.awt.event.ItemListener;
014    import java.io.File;
015    import java.io.IOException;
016    import java.io.OutputStream;
017    import java.io.OutputStreamWriter;
018    import java.io.PrintWriter;
019    import java.io.UnsupportedEncodingException;
020    import java.io.Writer;
021    import java.net.MalformedURLException;
022    import java.net.URI;
023    import java.net.URL;
024    import java.util.Collection;
025    import java.util.Collections;
026    
027    import javax.swing.ButtonGroup;
028    import javax.swing.JCheckBox;
029    import javax.swing.JLabel;
030    import javax.swing.JPanel;
031    import javax.swing.JRadioButton;
032    import javax.swing.JTextField;
033    import javax.swing.SwingConstants;
034    
035    import org.openstreetmap.josm.gui.layer.GpxLayer;
036    import org.openstreetmap.josm.gui.layer.Layer;
037    import org.openstreetmap.josm.gui.util.GuiHelper;
038    import org.openstreetmap.josm.io.GpxWriter;
039    import org.openstreetmap.josm.io.session.SessionWriter.ExportSupport;
040    import org.openstreetmap.josm.tools.GBC;
041    import org.w3c.dom.Element;
042    
043    public class GpxTracksSessionExporter implements SessionLayerExporter {
044    
045        private GpxLayer layer;
046        private JRadioButton link, include;
047        private JCheckBox export;
048    
049        public GpxTracksSessionExporter(GpxLayer layer) {
050            this.layer = layer;
051        }
052    
053        @Override
054        public Collection<Layer> getDependencies() {
055            return Collections.emptySet();
056        }
057    
058        @Override
059        public Component getExportPanel() {
060            final JPanel p = new JPanel(new GridBagLayout());
061            JPanel topRow = new JPanel(new GridBagLayout());
062            export = new JCheckBox();
063            export.setSelected(true);
064            final JLabel lbl = new JLabel(layer.getName(), layer.getIcon(), SwingConstants.LEFT);
065            lbl.setToolTipText(layer.getToolTipText());
066    
067            JLabel lblData = new JLabel(tr("Data:"));
068            /* I18n: Refer to a OSM data file in session file */ link = new JRadioButton(tr("local file"));
069            link.putClientProperty("actionname", "link");
070            link.setToolTipText(tr("Link to a OSM data file on your local disk."));
071            /* I18n: Include OSM data in session file */ include = new JRadioButton(tr("include"));
072            include.setToolTipText(tr("Include OSM data in the .joz session file."));
073            include.putClientProperty("actionname", "include");
074            ButtonGroup group = new ButtonGroup();
075            group.add(link);
076            group.add(include);
077    
078            JPanel cardLink = new JPanel(new GridBagLayout());
079            final File file = layer.getAssociatedFile();
080            if (file != null) {
081                JTextField tf = new JTextField();
082                tf.setText(file.getPath());
083                tf.setEditable(false);
084                cardLink.add(tf, GBC.std());
085            } else {
086                cardLink.add(new JLabel(tr("No file association")), GBC.eol());
087            }
088    
089            JPanel cardInclude = new JPanel(new GridBagLayout());
090            JLabel lblIncl = new JLabel(tr("OSM data will be included in the session file."));
091            lblIncl.setFont(lblIncl.getFont().deriveFont(Font.PLAIN));
092            cardInclude.add(lblIncl, GBC.eol().fill(GBC.HORIZONTAL));
093    
094            final CardLayout cl = new CardLayout();
095            final JPanel cards = new JPanel(cl);
096            cards.add(cardLink, "link");
097            cards.add(cardInclude, "include");
098    
099            if (file != null) {
100                link.setSelected(true);
101            } else {
102                link.setEnabled(false);
103                link.setToolTipText(tr("No file association"));
104                include.setSelected(true);
105                cl.show(cards, "include");
106            }
107    
108            link.addActionListener(new ActionListener() {
109                public void actionPerformed(ActionEvent e) {
110                    cl.show(cards, "link");
111                }
112            });
113            include.addActionListener(new ActionListener() {
114                public void actionPerformed(ActionEvent e) {
115                    cl.show(cards, "include");
116                }
117            });
118    
119            topRow.add(export, GBC.std());
120            topRow.add(lbl, GBC.std());
121            topRow.add(GBC.glue(1,0), GBC.std().fill(GBC.HORIZONTAL));
122            p.add(topRow, GBC.eol().fill(GBC.HORIZONTAL));
123            p.add(lblData, GBC.std().insets(10,0,0,0));
124            p.add(link, GBC.std());
125            p.add(include, GBC.eol());
126            p.add(cards, GBC.eol().insets(15,0,3,3));
127    
128            export.addItemListener(new ItemListener() {
129                public void itemStateChanged(ItemEvent e) {
130                    if (e.getStateChange() == ItemEvent.DESELECTED) {
131                        GuiHelper.setEnabledRec(p, false);
132                        export.setEnabled(true);
133                    } else {
134                        GuiHelper.setEnabledRec(p, true);
135                        link.setEnabled(file != null);
136                    }
137                }
138            });
139            return p;
140        }
141    
142        @Override
143        public boolean shallExport() {
144            return export.isSelected();
145        }
146    
147        @Override
148        public boolean requiresZip() {
149            return include.isSelected();
150        }
151    
152        @Override
153        public Element export(ExportSupport support) throws IOException {
154            Element layerEl = support.createElement("layer");
155            layerEl.setAttribute("type", "tracks");
156            layerEl.setAttribute("version", "0.1");
157    
158            Element file = support.createElement("file");
159            layerEl.appendChild(file);
160    
161            if (requiresZip()) {
162                String zipPath = "layers/" + String.format("%02d", support.getLayerIndex()) + "/data.gpx";
163                file.appendChild(support.createTextNode(zipPath));
164                addDataFile(support.getOutputStreamZip(zipPath));
165            } else {
166                URI uri = layer.getAssociatedFile().toURI();
167                URL url = null;
168                try {
169                    url = uri.toURL();
170                } catch (MalformedURLException e) {
171                    throw new IOException(e);
172                }
173                file.appendChild(support.createTextNode(url.toString()));
174            }
175            return layerEl;
176        }
177    
178        protected void addDataFile(OutputStream out) throws IOException {
179            Writer writer = null;
180            try {
181                writer = new OutputStreamWriter(out, "UTF-8");
182            } catch (UnsupportedEncodingException e) {
183                throw new RuntimeException(e);
184            }
185            GpxWriter w = new GpxWriter(new PrintWriter(writer));
186            w.write(layer.data);
187            w.flush();
188        }
189    
190    }