/******************************************************************************* * Copyright (c) MOBAC developers * * This program 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 2 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 mobac.gui.panels; import java.awt.GridBagLayout; import java.util.ArrayList; import java.util.List; import javax.swing.JButton; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import mobac.data.gpx.gpx11.RteType; import mobac.data.gpx.gpx11.TrkType; import mobac.data.gpx.gpx11.TrksegType; import mobac.data.gpx.gpx11.WptType; import mobac.gui.actions.GpxAddPoint; import mobac.gui.actions.GpxClear; import mobac.gui.actions.GpxLoad; import mobac.gui.actions.GpxNew; import mobac.gui.actions.GpxSave; import mobac.gui.components.JCollapsiblePanel; import mobac.gui.gpxtree.GpxEntry; import mobac.gui.gpxtree.GpxRootEntry; import mobac.gui.gpxtree.GpxTreeListener; import mobac.gui.gpxtree.RteEntry; import mobac.gui.gpxtree.TrkEntry; import mobac.gui.gpxtree.TrksegEntry; import mobac.gui.gpxtree.WptEntry; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.layer.GpxLayer; import mobac.utilities.GBC; import mobac.utilities.I18nUtils; /** * Allows to load, display, edit and save gpx files using a tree view. TODO warn unsaved changes on exit * */ public class JGpxPanel extends JCollapsiblePanel { private static final long serialVersionUID = 1L; private JTree tree; private DefaultMutableTreeNode rootNode; private DefaultTreeModel model; private ArrayList<String> openedFiles; private PreviewMap previewMap; public JGpxPanel(PreviewMap previewMap) { super("Gpx", new GridBagLayout()); this.previewMap = previewMap; JButton newGpx = new JButton(I18nUtils.localizedStringForKey("rp_gpx_new_gpx")); newGpx.addActionListener(new GpxNew(this)); JButton loadGpx = new JButton(I18nUtils.localizedStringForKey("rp_gpx_load_gpx")); loadGpx.addActionListener(new GpxLoad(this)); JButton saveGpx = new JButton(I18nUtils.localizedStringForKey("rp_gpx_save_gpx")); saveGpx.addActionListener(new GpxSave(this)); JButton clearGpx = new JButton(I18nUtils.localizedStringForKey("rp_gpx_clear_gpx")); clearGpx.addActionListener(new GpxClear(this)); JButton addPointGpx = new JButton(I18nUtils.localizedStringForKey("rp_gpx_add_wpt")); addPointGpx.addActionListener(new GpxAddPoint(this)); rootNode = new DefaultMutableTreeNode(I18nUtils.localizedStringForKey("rp_gpx_default_node_name")); tree = new JTree(rootNode); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); tree.setRootVisible(false); tree.setShowsRootHandles(true); JScrollPane treeView = new JScrollPane(tree); // treeView.setPreferredSize(new Dimension(100, 300)); model = (DefaultTreeModel) tree.getModel(); tree.addMouseListener(new GpxTreeListener()); openedFiles = new ArrayList<String>(); GBC eol = GBC.eol().fill(GBC.HORIZONTAL); GBC std = GBC.std().fill(GBC.HORIZONTAL); addContent(treeView, GBC.eol().fill()); addContent(clearGpx, std); addContent(addPointGpx, eol); addContent(newGpx, std); addContent(loadGpx, std); addContent(saveGpx, eol); } /** * adds a layer for a new gpx file on the map and adds its structure to the treeview * */ public GpxRootEntry addGpxLayer(GpxLayer layer) { layer.setPanel(this); GpxRootEntry gpxEntry = new GpxRootEntry(layer); DefaultMutableTreeNode gpxNode = new DefaultMutableTreeNode(gpxEntry); model.insertNodeInto(gpxNode, rootNode, rootNode.getChildCount()); TreePath path = new TreePath(gpxNode.getPath()); tree.scrollPathToVisible(new TreePath(path)); tree.setSelectionPath(path); addRtes(layer, gpxNode); addTrks(layer, gpxNode); addWpts(layer, gpxNode); if (layer.getFile() != null) openedFiles.add(layer.getFile().getAbsolutePath()); previewMap.mapLayers.add(layer); return gpxEntry; } /** * @param layer * @param gpxNode * @param model */ private void addWpts(GpxLayer layer, DefaultMutableTreeNode gpxNode) { List<WptType> wpts = layer.getGpx().getWpt(); for (WptType wpt : wpts) { WptEntry wptEntry = new WptEntry(wpt, layer); DefaultMutableTreeNode wptNode = new DefaultMutableTreeNode(wptEntry); model.insertNodeInto(wptNode, gpxNode, gpxNode.getChildCount()); } } /** * @param layer * @param gpxNode * @param model */ private void addTrks(GpxLayer layer, DefaultMutableTreeNode gpxNode) { // tracks List<TrkType> trks = layer.getGpx().getTrk(); for (TrkType trk : trks) { TrkEntry trkEntry = new TrkEntry(trk, layer); DefaultMutableTreeNode trkNode = new DefaultMutableTreeNode(trkEntry); model.insertNodeInto(trkNode, gpxNode, gpxNode.getChildCount()); // trkseg List<TrksegType> trksegs = trk.getTrkseg(); int counter = 1; for (TrksegType trkseg : trksegs) { TrksegEntry trksegEntry = new TrksegEntry(trkseg, counter, layer); DefaultMutableTreeNode trksegNode = new DefaultMutableTreeNode(trksegEntry); model.insertNodeInto(trksegNode, trkNode, trkNode.getChildCount()); counter++; // add trkpts List<WptType> trkpts = trkseg.getTrkpt(); for (WptType trkpt : trkpts) { WptEntry trkptEntry = new WptEntry(trkpt, layer); DefaultMutableTreeNode trkptNode = new DefaultMutableTreeNode(trkptEntry); model.insertNodeInto(trkptNode, trksegNode, trksegNode.getChildCount()); } } } } /** * adds routes and route points to the tree view * * @param layer * @param gpxNode */ private void addRtes(GpxLayer layer, DefaultMutableTreeNode gpxNode) { List<RteType> rtes = layer.getGpx().getRte(); for (RteType rte : rtes) { RteEntry rteEntry = new RteEntry(rte, layer); DefaultMutableTreeNode rteNode = new DefaultMutableTreeNode(rteEntry); model.insertNodeInto(rteNode, gpxNode, gpxNode.getChildCount()); // add rtepts List<WptType> rtepts = rte.getRtept(); for (WptType rtept : rtepts) { WptEntry rteptEntry = new WptEntry(rtept, layer); DefaultMutableTreeNode rteptNode = new DefaultMutableTreeNode(rteptEntry); model.insertNodeInto(rteptNode, rteNode, rteNode.getChildCount()); } } } /** * Updates the tree view to show the newly added waypoint. * * @param wpt * - new waypoint * @param gpxEntry * - parent entry in the tree */ public void addWpt(WptType wpt, GpxEntry gpxEntry) { WptEntry wptEntry = new WptEntry(wpt, gpxEntry.getLayer()); DefaultMutableTreeNode wptNode = new DefaultMutableTreeNode(wptEntry); model.insertNodeInto(wptNode, gpxEntry.getNode(), gpxEntry.getNode().getChildCount()); } /** * Updates the tree view after removing a waypoint. * * @param wpt * - deleted waypoint * @param gpxEntry * - parent entry of the deleted element in the tree */ public void removeWpt(WptEntry wptEntry) { DefaultMutableTreeNode wptNode = wptEntry.getNode(); model.removeNodeFromParent(wptNode); // update layer (is changing the gpx enough? prolly not // did remove it already...check wheter its enough } public GpxEntry getSelectedEntry() { TreePath selection = tree.getSelectionPath(); if (selection == null) { return null; } DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) selection.getLastPathComponent(); GpxEntry gpxEntry = null; try { gpxEntry = (GpxEntry) selectedNode.getUserObject(); gpxEntry.setNode(selectedNode); } catch (ClassCastException e) { } return gpxEntry; } public boolean isFileOpen(String path) { return openedFiles.contains(path); } /** * Resets the tree view. Used by GpxClear. * */ public void resetModel() { rootNode = new DefaultMutableTreeNode(I18nUtils.localizedStringForKey("rp_gpx_default_node_name")); model.setRoot(rootNode); openedFiles = new ArrayList<String>(); } public DefaultTreeModel getTreeModel() { return model; } }