// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.czechaddress.gui; import java.awt.Component; import java.awt.Font; import java.awt.event.ItemListener; import java.util.ArrayList; import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListCellRenderer; import javax.swing.JList; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; import org.openstreetmap.josm.gui.ExtendedDialog; import org.openstreetmap.josm.plugins.czechaddress.addressdatabase.AddressElement; import org.openstreetmap.josm.plugins.czechaddress.addressdatabase.Database; import org.openstreetmap.josm.plugins.czechaddress.addressdatabase.ElementWithStreets; import org.openstreetmap.josm.plugins.czechaddress.addressdatabase.Region; import org.openstreetmap.josm.plugins.czechaddress.addressdatabase.Suburb; import org.openstreetmap.josm.plugins.czechaddress.addressdatabase.ViToCi; /** * Dialog for selecting the current loaction. * * @author Radomír Černoch, radomir.cernoch@gmail.com * @author Libor Pechacek, lpechacek@gmx.com */ public final class LocationSelector extends ExtendedDialog { protected ElementWithStreets selectedElement; protected ArrayList<ItemListener> listeners = new ArrayList<>(); int regionHlIndex, vitociHlIndex, suburbHlIndex; protected ArrayList<AddressElement> hlRegions = new ArrayList<>(); protected ArrayList<AddressElement> hlViToCis = new ArrayList<>(); protected ArrayList<AddressElement> hlSuburbs = new ArrayList<>(); public static ElementWithStreets selectLocation() { LocationSelector ls = (LocationSelector) new LocationSelector().showDialog(); if (ls.getValue() == 1) return ls.selectedElement; else return null; } private LocationSelector() { super(Main.parent, "Výběr umístění", new String[] {"OK", "Zrušit"}, true); initComponents(); setContent(mainPanel); setButtonIcons(new String[] {"ok.png", "cancel.png"}); setDefaultButton(1); setCancelButton(2); setupDialog(); oblastComboBox.setRenderer(new AddressElementRenderer()); vitociComboBox.setRenderer(new AddressElementRenderer()); suburbComboBox.setRenderer(new SuburbRenderer()); initLocationHints(); DefaultComboBoxModel<Region> regions = new DefaultComboBoxModel<>(Database.getInstance().regions.toArray(new Region[0])); regionHlIndex = reshuffleListItems(regions, hlRegions); oblastComboBox.setModel(regions); oblastComboBox.setSelectedItem(regions.getElementAt(0)); oblastComboBoxItemStateChanged(null); } /** * Guess location name from the map and put all matches to the top of the * list. * */ private void initLocationHints() { boolean assertions = false; assert assertions = true; OsmPrimitive bestFit = null; double bestLen = 0; BoundingXYVisitor visitor = new BoundingXYVisitor(); org.openstreetmap.josm.data.osm.DataSet dataSet = Main.getLayerManager().getEditDataSet(); if (dataSet == null) return; for (OsmPrimitive op : dataSet.allPrimitives()) { if (op instanceof Node) { ((Node) op).accept(visitor); } else if (op instanceof Way) { ((Way) op).accept(visitor); } } LatLon center; try { center = Main.getProjection().eastNorth2latlon(Main.map.mapView.getCenter()); } catch (Exception e) { System.err.println("AUTO: No bounds to determine autolocation."); return; } if (assertions) System.out.println("AUTO: Center is " + center); for (OsmPrimitive op : Main.getLayerManager().getEditDataSet().allPrimitives()) { if (!(op instanceof Node)) { continue; } Node node = (Node) op; double multiplicator = 5; if (new String("city").equals(op.get("place"))) { multiplicator = 2.8; } else if (new String("town").equals(op.get("place"))) { multiplicator = 2.3; } else if (new String("village").equals(op.get("place"))) { multiplicator = 2; } else if (new String("suburb").equals(op.get("place"))) { multiplicator = 1; } else { continue; } double currLen = multiplicator * (node.getCoor().distance(center)); if ((bestFit == null) || (currLen < bestLen)) { bestFit = op; bestLen = currLen; } } if (bestFit != null) { if (assertions) System.out.println("AUTO: Best fit " + bestFit.getName() + "\t " + bestFit.get("name")); for (Region oblast : Database.getInstance().regions) { for (ViToCi obec : oblast.getViToCis()) { if (!bestFit.get("place").equals("suburb")) { if (obec.getName().equalsIgnoreCase(bestFit.get("name"))) { hlRegions.add(oblast); hlViToCis.add(obec); for (Suburb castObce : obec.getSuburbs()) { if (castObce.getName().equalsIgnoreCase(bestFit.get("name"))) hlSuburbs.add(castObce); } } } else { for (Suburb castObce : obec.getSuburbs()) { if (castObce.getName().equalsIgnoreCase(bestFit.get("name"))) { hlRegions.add(oblast); hlViToCis.add(obec); hlSuburbs.add(castObce); } } } } } } } /** * Reshuffle items in combo box list, put those in hlList to the * beginning, return number of moved items. */ private <E> int reshuffleListItems(DefaultComboBoxModel<E> list, final ArrayList<AddressElement> hlList) { int curHlIndex = 0; for (int i = 0; i < list.getSize(); i++) { for (int j = 0; j < hlList.size(); j++) { E t = list.getElementAt(i); if (t == hlList.get(j)) { list.removeElementAt(i); list.insertElementAt(t, curHlIndex++); break; } } } return curHlIndex; } /** 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() { mainPanel = new javax.swing.JPanel(); oblastComboBox = new javax.swing.JComboBox<>(); suburbComboBox = new javax.swing.JComboBox<>(); vitociComboBox = new javax.swing.JComboBox<>(); obecLabel = new javax.swing.JLabel(); castObceLabel = new javax.swing.JLabel(); oblastLabel = new javax.swing.JLabel(); setTitle("Výběr umístění"); setModal(true); setName("locationSelector"); // NOI18N getContentPane().setLayout(new java.awt.GridLayout(1, 0)); oblastComboBox.addItemListener(new java.awt.event.ItemListener() { @Override public void itemStateChanged(java.awt.event.ItemEvent evt) { oblastComboBoxItemStateChanged(evt); } }); suburbComboBox.addItemListener(new java.awt.event.ItemListener() { @Override public void itemStateChanged(java.awt.event.ItemEvent evt) { suburbComboBoxItemStateChanged(evt); } }); vitociComboBox.addItemListener(new java.awt.event.ItemListener() { @Override public void itemStateChanged(java.awt.event.ItemEvent evt) { vitociComboBoxItemStateChanged(evt); } }); obecLabel.setText("Obec:"); castObceLabel.setText("Část obce:"); oblastLabel.setText("ORP:"); javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(mainPanelLayout.createSequentialGroup() .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(oblastLabel) .addComponent(obecLabel) .addComponent(castObceLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(suburbComboBox, 0, 341, Short.MAX_VALUE) .addComponent(vitociComboBox, 0, 341, Short.MAX_VALUE) .addComponent(oblastComboBox, 0, 341, Short.MAX_VALUE))) ); mainPanelLayout.setVerticalGroup( mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(mainPanelLayout.createSequentialGroup() .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(oblastLabel) .addComponent(oblastComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(obecLabel) .addComponent(vitociComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(castObceLabel) .addComponent(suburbComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); getContentPane().add(mainPanel); } // </editor-fold>//GEN-END:initComponents /** * Notifies all listeners about * * private void checkSetSelected(ElementWithStreets elem) { if (elem == null) return; ItemEvent event = new ItemEvent(this, ItemEvent.DESELECTED, selectedElement, ItemEvent.DESELECTED); for (ItemListener i : listeners) i.itemStateChanged(event); selectedElement = elem; event = new ItemEvent(this, ItemEvent.SELECTED, selectedElement, ItemEvent.SELECTED); for (ItemListener i : listeners) i.itemStateChanged(event); }*/ private void oblastComboBoxItemStateChanged(java.awt.event.ItemEvent evt) { //GEN-FIRST:event_oblastComboBoxItemStateChanged Region oblast = (Region) oblastComboBox.getSelectedItem(); if (oblast == null) return; DefaultComboBoxModel<ViToCi> vitocis = new DefaultComboBoxModel<>(oblast.getViToCis().toArray(new ViToCi[0])); vitociHlIndex = reshuffleListItems(vitocis, hlViToCis); vitociComboBox.setModel(vitocis); vitociComboBox.setSelectedItem(vitocis.getElementAt(0)); vitociComboBox.setEnabled(vitociComboBox.getModel().getSize() > 1); vitociComboBoxItemStateChanged(null); } //GEN-LAST:event_oblastComboBoxItemStateChanged private void vitociComboBoxItemStateChanged(java.awt.event.ItemEvent evt) { //GEN-FIRST:event_vitociComboBoxItemStateChanged ViToCi obec = (ViToCi) vitociComboBox.getSelectedItem(); if (obec == null) return; if (obec.getSuburbs().size() > 0) { ElementWithStreets[] suburbs = new ElementWithStreets[obec.getSuburbs().size() + 1]; for (int i = 0; i < obec.getSuburbs().size(); i++) { suburbs[i] = obec.getSuburbs().get(i); } suburbs[obec.getSuburbs().size()] = obec; DefaultComboBoxModel<ElementWithStreets> suburbsList = new DefaultComboBoxModel<>(suburbs); suburbHlIndex = reshuffleListItems(suburbsList, hlSuburbs); suburbComboBox.setModel(suburbsList); suburbComboBox.setSelectedItem(suburbsList.getElementAt(0)); } else suburbComboBox.setModel(new DefaultComboBoxModel<ElementWithStreets>()); suburbComboBox.setEnabled(suburbComboBox.getModel().getSize() > 1); suburbComboBoxItemStateChanged(null); } //GEN-LAST:event_vitociComboBoxItemStateChanged private void suburbComboBoxItemStateChanged(java.awt.event.ItemEvent evt) { //GEN-FIRST:event_suburbComboBoxItemStateChanged /*if (castObceComboBox.getSelectedItem() != null) checkSetSelected((ElementWithStreets) castObceComboBox.getSelectedItem()); else if (obecComboBox.getSelectedItem() != null) checkSetSelected((ElementWithStreets) obecComboBox.getSelectedItem()); else if (oblastComboBox.getSelectedItem() != null) checkSetSelected((ElementWithStreets) oblastComboBox.getSelectedItem());*/ if (suburbComboBox.getSelectedItem() != null) selectedElement = ((ElementWithStreets) suburbComboBox.getSelectedItem()); else if (vitociComboBox.getSelectedItem() != null) selectedElement = ((ElementWithStreets) vitociComboBox.getSelectedItem()); else if (oblastComboBox.getSelectedItem() != null) selectedElement = ((ElementWithStreets) oblastComboBox.getSelectedItem()); } //GEN-LAST:event_suburbComboBoxItemStateChanged // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel castObceLabel; private javax.swing.JPanel mainPanel; private javax.swing.JLabel obecLabel; private javax.swing.JComboBox<Region> oblastComboBox; private javax.swing.JLabel oblastLabel; private javax.swing.JComboBox<ElementWithStreets> suburbComboBox; private javax.swing.JComboBox<ViToCi> vitociComboBox; // End of variables declaration//GEN-END:variables private class AddressElementRenderer extends DefaultListCellRenderer { @Override public Component getListCellRendererComponent( JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof AddressElement && !(value instanceof Region)) setText(((AddressElement) value).getName()); if ((value instanceof Region && index < regionHlIndex) || (value instanceof ViToCi && index < vitociHlIndex)) setFont(getFont().deriveFont(Font.BOLD)); else setFont(getFont().deriveFont(Font.PLAIN)); return c; } } private class SuburbRenderer extends AddressElementRenderer { @Override public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof ViToCi) { setFont(getFont().deriveFont(Font.BOLD)); // setText(((ViToCi) value).getName() + ", všechny části [experimentální]"); setText("všechny části obce [experimentální]"); } else if (index < suburbHlIndex) setFont(getFont().deriveFont(Font.BOLD)); else setFont(getFont().deriveFont(Font.PLAIN)); return c; } } }