package org.activityinfo.geoadmin; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.util.List; import java.util.Map; import java.util.prefs.Preferences; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.MutableTreeNode; import javax.swing.tree.TreePath; import org.activityinfo.geoadmin.locations.LocationWindow; import org.activityinfo.geoadmin.model.ActivityInfoClient; import org.activityinfo.geoadmin.model.AdminLevel; import org.activityinfo.geoadmin.model.Country; import org.activityinfo.geoadmin.model.LocationType; import org.activityinfo.geoadmin.model.VersionMetadata; import com.google.common.base.Strings; import com.google.common.collect.Maps; /** * Principal tab which lists the countries present in ActivityInfo */ public class CountryTab extends JPanel { private Preferences prefs = Preferences.userNodeForPackage(GeoAdmin.class); private Country country; private ActivityInfoClient client; private JTree tree; public CountryTab(ActivityInfoClient client, Country country) { super(false); // isDoubleBuffered this.client = client; this.country = country; setLayout(new GridLayout(1, 1)); DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(country.getName()); rootNode.add(createAdminNodes()); rootNode.add(createLocationTypeNodes()); tree = new JTree(rootNode); tree.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); if (selPath != null) { if (SwingUtilities.isRightMouseButton(e)) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getLastPathComponent(); if (node.getUserObject() instanceof AdminLevel) { AdminLevel level = (AdminLevel) node.getUserObject(); showAdminLevelContextMenu(e, level); } else { showRootContextMenu(e); } } else if (e.getClickCount() == 2) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getLastPathComponent(); if (node.getUserObject() instanceof AdminLevel) { showAdminLevels(e, (AdminLevel) node.getUserObject()); } else if(node.getUserObject() instanceof LocationType) { showLocationType(e, (LocationType) node.getUserObject()); } } } } }); add(new JScrollPane(tree), BorderLayout.CENTER); } private void showAdminLevels(MouseEvent e, AdminLevel level) { AdminListWindow window = new AdminListWindow(getParentFrame(), client, level); window.setVisible(true); } private void showLocationType(MouseEvent e, LocationType locationType) { LocationWindow window = new LocationWindow(getParentFrame(), country, locationType, client); window.setVisible(true); } private MutableTreeNode createAdminNodes() { DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Admin Levels"); List<AdminLevel> levels = client.getAdminLevels(country); Map<Integer, DefaultMutableTreeNode> nodes = Maps.newHashMap(); // add root nodes for (AdminLevel level : levels) { DefaultMutableTreeNode node = new DefaultMutableTreeNode(level); nodes.put(level.getId(), node); if (level.isRoot()) { rootNode.add(node); } } // add child nodes for (AdminLevel level : levels) { if (!level.isRoot()) { DefaultMutableTreeNode parent = nodes.get(level.getParentId()); DefaultMutableTreeNode node = nodes.get(level.getId()); parent.add(node); } } return rootNode; } private MutableTreeNode createLocationTypeNodes() { DefaultMutableTreeNode typeNodes = new DefaultMutableTreeNode("Location Types"); List<LocationType> types = client.getLocationTypesByCountryCode(country.getCode()); // add child nodes for (LocationType type : types) { typeNodes.add(new DefaultMutableTreeNode(type)); } return typeNodes; } private void showAdminLevelContextMenu(MouseEvent e, final AdminLevel level) { JMenuItem renameItem = new JMenuItem("Rename level"); renameItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { renameLevel(level); } }); JMenuItem importChildItem = new JMenuItem("Import child level"); importChildItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { importChildLevel(level); } }); JMenuItem updateItem = new JMenuItem("Update from file"); updateItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { updateLevel(level); } }); JPopupMenu menu = new JPopupMenu(); menu.add(renameItem); menu.add(importChildItem); menu.add(updateItem); menu.show(e.getComponent(), e.getX(), e.getY()); } private void showRootContextMenu(MouseEvent e) { JMenuItem importChildItem = new JMenuItem("Import new top level"); importChildItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { importChildLevel(null); } }); JPopupMenu menu = new JPopupMenu(); menu.add(importChildItem); menu.show(e.getComponent(), e.getX(), e.getY()); } private void renameLevel(AdminLevel level) { String newName = JOptionPane.showInputDialog(getParentFrame(), "New name"); if (!Strings.isNullOrEmpty(newName)) { AdminLevel update = new AdminLevel(); update.setId(level.getId()); update.setName(newName); update.setParentId(level.getParentId()); VersionMetadata metadata = new VersionMetadata(); metadata.setMessage(String.format("Renamed level from '%s' to '%s'", level.getName(), newName)); update.setVersionMetadata(metadata); client.updateAdminLevel(update); level.setName(newName); } } private void importChildLevel(AdminLevel level) { File file = chooseFile(); if (file != null) { try { ImportWindow window = new ImportWindow(getParentFrame(), client, country, level, file); window.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } } private void updateLevel(AdminLevel level) { ImportSource source = chooseSource(); if (source != null) { try { UpdateWindow window = new UpdateWindow(getParentFrame(), source, level, client); window.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } } private JFrame getParentFrame() { JFrame frame = (JFrame) SwingUtilities.getRoot(this); return frame; } private ImportSource chooseSource() { File file = chooseFile(); if (file == null) { return null; } try { ImportSource source = new ImportSource(file); if (source.getFeatureCount() == 0) { JOptionPane.showMessageDialog(getParentFrame(), "The file is empty.", file.getName(), JOptionPane.ERROR_MESSAGE); return null; } if (!source.validateGeometry(country)) { JOptionPane.showMessageDialog(getParentFrame(), "The geometry does not seem to match this country's geographic bounds, please " + "ensure that the .prj file correctly defines the projection.", file.getName(), JOptionPane.ERROR_MESSAGE); return null; } return source; } catch (Exception e) { JOptionPane.showMessageDialog(getParentFrame(), "There was an exception opening this source: " + e.getMessage(), file.getName(), JOptionPane.ERROR_MESSAGE); e.printStackTrace(); return null; } } private File chooseFile() { File initialDir = new File(prefs.get("import_dir_" + country.getCode(), prefs.get("import_dir", ""))); JFileChooser chooser = new JFileChooser(initialDir); chooser.setFileFilter(new FileNameExtensionFilter("Shapefiles", "shp")); int returnVal = chooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = chooser.getSelectedFile(); prefs.put("import_dir_" + country.getCode(), file.getParent()); prefs.put("import_dir", file.getParent()); return file; } return null; } }