Ignore:
Timestamp:
2009-12-13T22:47:51+01:00 (15 years ago)
Author:
casualwalker
Message:

Re-Design of JOSM terracer input dialog.
This implements the tickets #2989 #3343.
Code-cleanup (comments and all those nice things) to follow.

Location:
applications/editors/josm/plugins/terracer/src/terracer
Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/terracer/src/terracer/TerracerAction.java

    r17874 r19084  
    1111import static org.openstreetmap.josm.tools.I18n.trn;
    1212
    13 import java.awt.Choice;
    14 import java.awt.Component;
    15 import java.awt.GridBagLayout;
    1613import java.awt.event.ActionEvent;
    17 import java.awt.event.ItemEvent;
    18 import java.awt.event.ItemListener;
    1914import java.awt.event.KeyEvent;
    2015import java.util.ArrayList;
     
    2419import java.util.TreeSet;
    2520
    26 import javax.swing.JFormattedTextField;
    27 import javax.swing.JLabel;
    2821import javax.swing.JOptionPane;
    29 import javax.swing.JPanel;
    30 import javax.swing.JSpinner;
    31 import javax.swing.SpinnerNumberModel;
    32 import javax.swing.event.ChangeEvent;
    33 import javax.swing.event.ChangeListener;
    3422
    3523import org.openstreetmap.josm.Main;
     
    4432import org.openstreetmap.josm.data.osm.RelationMember;
    4533import org.openstreetmap.josm.data.osm.Way;
    46 import org.openstreetmap.josm.gui.widgets.AutoCompleteComboBox;
    47 import org.openstreetmap.josm.tools.GBC;
    4834import org.openstreetmap.josm.tools.Pair;
    4935import org.openstreetmap.josm.tools.Shortcut;
     
    6349        // smsms1 asked for the last value to be remembered to make it easier to do
    6450        // repeated terraces. this is the easiest, but not necessarily nicest, way.
    65         //private static String lastSelectedValue = "";
     51        // private static String lastSelectedValue = "";
    6652
    6753        public TerracerAction() {
    68                 super(tr("Terrace a building"),
    69                                 "terrace",
     54                super(tr("Terrace a building"), "terrace",
    7055                                tr("Creates individual buildings from a long building."),
    71                                 Shortcut.registerShortcut("tools:Terracer",
    72                                                 tr("Tool: {0}", tr("Terrace a building")),
    73                                                 KeyEvent.VK_T, Shortcut.GROUP_EDIT,
    74                                                 Shortcut.SHIFT_DEFAULT),
    75                                                 true);
     56                                Shortcut.registerShortcut("tools:Terracer", tr("Tool: {0}",
     57                                                tr("Terrace a building")), KeyEvent.VK_T,
     58                                                Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
    7659        }
    7760
     
    8164         */
    8265        public void actionPerformed(ActionEvent e) {
    83                 Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet().getSelected();
     66                Collection<OsmPrimitive> sel = Main.main.getCurrentDataSet()
     67                                .getSelected();
    8468                boolean badSelect = false;
    8569
     
    8872
    8973                        if (prim instanceof Way) {
    90                                 Way way = (Way)prim;
    91 
    92                                 if ((way.getNodesCount() >= 5) &&
    93                                                 way.isClosed()) {
     74                                Way way = (Way) prim;
     75
     76                                if ((way.getNodesCount() >= 5) && way.isClosed()) {
     77                                        String title = trn("Change {0} object",
     78                                                        "Change {0} objects", sel.size(), sel.size());
     79                                        if (sel.size() == 0)
     80                                                title = tr("Nothing selected!");
     81
    9482                                        // first ask the user how many buildings to terrace into
    95                                         HouseNumberDialog dialog = new HouseNumberDialog();
    96                                         final JOptionPane optionPane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
    97 
    98                                         String title = trn("Change {0} object", "Change {0} objects", sel.size(), sel.size());
    99                                         if(sel.size() == 0)
    100                                                 title = tr("Nothing selected!");
    101 
    102                                         optionPane.createDialog(Main.parent, title).setVisible(true);
    103                                         Object answerObj = optionPane.getValue();
    104                                         if (answerObj != null &&
    105                                                         answerObj != JOptionPane.UNINITIALIZED_VALUE &&
    106                                                         (answerObj instanceof Integer &&
    107                                                                         (Integer)answerObj == JOptionPane.OK_OPTION)) {
    108 
    109                                                 // call out to the method which does the actual
    110                                                 // terracing.
    111                                                 terraceBuilding(way,
    112                                                                 dialog.numberFrom(),
    113                                                                 dialog.numberTo(),
    114                                                                 dialog.stepSize(),
    115                                                                 dialog.streetName());
    116 
    117                                         }
     83                                        HouseNumberInputHandler handler = new HouseNumberInputHandler(
     84                                                        this, way, title);
     85
     86                                        // IntermediateInputDialog inputDialog = new
     87                                        // IntermediateInputDialog(
     88                                        // this, way);
     89                                        // inputDialog.pack();
     90                                        // inputDialog.setVisible(true);
     91
     92                                        // HouseNumberDialog dialog = new HouseNumberDialog(this);
     93                                        // final JOptionPane optionPane = new JOptionPane(dialog,
     94                                        // JOptionPane.PLAIN_MESSAGE,
     95                                        // JOptionPane.OK_CANCEL_OPTION);
     96                                        //
     97                                        // String title = trn("Change {0} object",
     98                                        // "Change {0} objects", sel.size(), sel.size());
     99                                        // if (sel.size() == 0)
     100                                        // title = tr("Nothing selected!");
     101                                        //
     102                                        // optionPane.createDialog(Main.parent, title)
     103                                        // .setVisible(true);
     104                                        // Object answerObj = optionPane.getValue();
     105                                        // if (answerObj != null
     106                                        // && answerObj != JOptionPane.UNINITIALIZED_VALUE
     107                                        // && (answerObj instanceof Integer && (Integer) answerObj
     108                                        // == JOptionPane.OK_OPTION)) {
     109                                        //
     110                                        // // call out to the method which does the actual
     111                                        // // terracing.
     112                                        // terraceBuilding(way, dialog.numberFrom(), dialog
     113                                        // .numberTo(), dialog.stepSize(), dialog
     114                                        // .streetName());
     115                                        //
     116                                        // }
    118117                                } else {
    119118                                        badSelect = true;
     
    142141         * @param w The closed, quadrilateral way to terrace.
    143142         */
    144         private void terraceBuilding(Way w, int from, int to, int step, String streetName) {
    145                 final int nb = 1 + (to - from) / step;
     143        public void terraceBuilding(Way w, Integer segments, Integer from,
     144                        Integer to, int step, String streetName) {
     145                final int nb;
     146                if (to != null && from != null) {
     147                        nb = 1 + (to.intValue() - from.intValue()) / step;
     148                } else if (segments != null) {
     149                        nb = segments.intValue();
     150                } else {
     151                        // TODO: we're in trouble.
     152                        // do exception handling.
     153                        nb = 0;
     154                }
    146155
    147156                // now find which is the longest side connecting the first node
    148                 Pair<Way,Way> interp = findFrontAndBack(w);
     157                Pair<Way, Way> interp = findFrontAndBack(w);
    149158
    150159                final double frontLength = wayLength(interp.a);
     
    159168                // create intermediate nodes by interpolating.
    160169                for (int i = 0; i <= nb; ++i) {
    161                         new_nodes[0][i] = interpolateAlong(interp.a, frontLength * (i) / (nb));
    162                         new_nodes[1][i] = interpolateAlong(interp.b, backLength * (i) / (nb));
     170                        new_nodes[0][i] = interpolateAlong(interp.a, frontLength * (i)
     171                                        / (nb));
     172                        new_nodes[1][i] = interpolateAlong(interp.b, backLength * (i)
     173                                        / (nb));
    163174                        commands.add(new AddCommand(new_nodes[0][i]));
    164175                        commands.add(new AddCommand(new_nodes[1][i]));
     
    172183                }
    173184                // note that we don't actually add the street member to the relation, as
    174                 // the name isn't unambiguous and it could cause confusion if the editor were
     185                // the name isn't unambiguous and it could cause confusion if the editor
     186                // were
    175187                // to automatically select one which wasn't the one the user intended.
    176188
     
    178190                for (int i = 0; i < nb; ++i) {
    179191                        Way terr = new Way();
    180                         // Using Way.nodes.add rather than Way.addNode because the latter doesn't
     192                        // Using Way.nodes.add rather than Way.addNode because the latter
     193                        // doesn't
    181194                        // exist in older versions of JOSM.
    182195                        terr.addNode(new_nodes[0][i]);
    183                         terr.addNode(new_nodes[0][i+1]);
    184                         terr.addNode(new_nodes[1][i+1]);
     196                        terr.addNode(new_nodes[0][i + 1]);
     197                        terr.addNode(new_nodes[1][i + 1]);
    185198                        terr.addNode(new_nodes[1][i]);
    186199                        terr.addNode(new_nodes[0][i]);
    187                         terr.put("addr:housenumber", "" + (from + i * step));
     200
     201                        if (from != null) {
     202                                // only, if the user has specified house numbers
     203                                terr.put("addr:housenumber", "" + (from + i * step));
     204                        }
    188205                        terr.put("building", "yes");
    189206                        if (streetName != null) {
     
    215232        private Node interpolateAlong(Way w, double l) {
    216233                Node n = null;
    217                 for (Pair<Node,Node> p : w.getNodePairs(false)) {
    218                         final double seg_length = p.a.getCoor().greatCircleDistance(p.b.getCoor());
     234                for (Pair<Node, Node> p : w.getNodePairs(false)) {
     235                        final double seg_length = p.a.getCoor().greatCircleDistance(
     236                                        p.b.getCoor());
    219237                        if (l <= seg_length) {
    220238                                n = interpolateNode(p.a, p.b, l / seg_length);
     
    225243                }
    226244                if (n == null) {
    227                         // sometimes there is a small overshoot due to numerical roundoff, so we just
    228                         // set these cases to be equal to the last node. its not pretty, but it works ;-)
     245                        // sometimes there is a small overshoot due to numerical roundoff,
     246                        // so we just
     247                        // set these cases to be equal to the last node. its not pretty, but
     248                        // it works ;-)
    229249                        n = w.getNode(w.getNodesCount() - 1);
    230250                }
     
    241261        private double wayLength(Way w) {
    242262                double length = 0.0;
    243                 for (Pair<Node,Node> p : w.getNodePairs(false)) {
     263                for (Pair<Node, Node> p : w.getNodePairs(false)) {
    244264                        length += p.a.getCoor().greatCircleDistance(p.b.getCoor());
    245265                }
     
    275295
    276296                // if the second side has a shorter length and an approximately equal
    277                 // sideness then its better to choose the shorter, as with quadrilaterals
     297                // sideness then its better to choose the shorter, as with
     298                // quadrilaterals
    278299                // created using the orthogonalise tool the sideness will be about the
    279300                // same for all sides.
    280                 if (sideLength(w, side1) > sideLength(w, side1 + 1) &&
    281                         Math.abs(sideness[side1] - sideness[side1 + 1]) < 0.001) {
     301                if (sideLength(w, side1) > sideLength(w, side1 + 1)
     302                                && Math.abs(sideness[side1] - sideness[side1 + 1]) < 0.001) {
    282303                        side1 = side1 + 1;
    283304                        side2 = (side2 + 1) % (w.getNodesCount() - 1);
     
    286307                // swap side1 and side2 into sorted order.
    287308                if (side1 > side2) {
    288                         // i can't believe i have to write swap() myself - surely java standard
     309                        // i can't believe i have to write swap() myself - surely java
     310                        // standard
    289311                        // library has this somewhere??!!?ONE!
    290312                        int tmp = side2;
     
    316338        private double sideLength(Way w, int i) {
    317339                Node a = w.getNode(i);
    318                 Node b = w.getNode((i+1) % (w.getNodesCount() - 1));
     340                Node b = w.getNode((i + 1) % (w.getNodesCount() - 1));
    319341                return a.getCoor().greatCircleDistance(b.getCoor());
    320342        }
     
    336358                        public double x;
    337359                        public int i;
     360
    338361                        public SortWithIndex(double a, int b) {
    339                                 x = a; i = b;
    340                         }
     362                                x = a;
     363                                i = b;
     364                        }
     365
    341366                        public int compareTo(SortWithIndex o) {
    342367                                return Double.compare(x, o.x);
     
    366391                double[] sideness = new double[length];
    367392
    368                 sideness[0] = calculateSideness(
    369                                 w.getNode(length - 1), w.getNode(0),
    370                                 w.getNode(1), w.getNode(2));
     393                sideness[0] = calculateSideness(w.getNode(length - 1), w.getNode(0), w
     394                                .getNode(1), w.getNode(2));
    371395                for (int i = 1; i < length - 1; ++i) {
    372                         sideness[i] = calculateSideness(
    373                                         w.getNode(i-1), w.getNode(i),
    374                                         w.getNode(i+1), w.getNode(i+2));
    375                 }
    376                 sideness[length-1] = calculateSideness(
    377                                 w.getNode(length - 2), w.getNode(length - 1),
    378                                 w.getNode(length), w.getNode(1));
     396                        sideness[i] = calculateSideness(w.getNode(i - 1), w.getNode(i), w
     397                                        .getNode(i + 1), w.getNode(i + 2));
     398                }
     399                sideness[length - 1] = calculateSideness(w.getNode(length - 2), w
     400                                .getNode(length - 1), w.getNode(length), w.getNode(1));
    379401
    380402                return sideness;
     
    392414                final double pdy = d.getCoor().getY() - c.getCoor().getY();
    393415
    394                 return (ndx * pdx + ndy * pdy) /
    395                 Math.sqrt((ndx * ndx + ndy * ndy) * (pdx * pdx + pdy * pdy));
    396         }
    397 
    398         /**
    399          * Dialog box to allow users to input housenumbers in a nice way.
    400          */
    401         class HouseNumberDialog extends JPanel {
    402                 private SpinnerNumberModel lo, hi;
    403                 private JSpinner clo, chi;
    404                 private Choice step;
    405                 private AutoCompleteComboBox street;
    406 
    407                 public HouseNumberDialog() {
    408                         super(new GridBagLayout());
    409                         lo = new SpinnerNumberModel(1, 1, 1, 1);
    410                         hi = new SpinnerNumberModel(1, 1, null, 1);
    411                         step = new Choice();
    412                         step.add(tr("All"));
    413                         step.add(tr("Even"));
    414                         step.add(tr("Odd"));
    415                         clo = new JSpinner(lo);
    416                         chi = new JSpinner(hi);
    417 
    418                         lo.addChangeListener(new ChangeListener() {
    419                                 public void stateChanged(ChangeEvent e) {
    420                                         hi.setMinimum((Integer)lo.getNumber());
    421                                 }
    422                         });
    423                         hi.addChangeListener(new ChangeListener() {
    424                                 public void stateChanged(ChangeEvent e) {
    425                                         lo.setMaximum((Integer)hi.getNumber());
    426                                 }
    427                         });
    428                         step.addItemListener(new ItemListener() {
    429                                 public void itemStateChanged(ItemEvent e) {
    430                                         if (step.getSelectedItem() == tr("All")) {
    431                                                 hi.setStepSize(1);
    432                                                 lo.setStepSize(1);
    433                                         } else {
    434                                                 int odd_or_even = 0;
    435                                                 int min = 0;
    436 
    437                                                 if (step.getSelectedItem() == tr("Even")) {
    438                                                         odd_or_even = 0;
    439                                                         min = 2;
    440                                                 } else {
    441                                                         odd_or_even = 1;
    442                                                         min = 1;
    443                                                 }
    444 
    445                                                 if ((lo.getNumber().intValue() & 1) != odd_or_even) {
    446                                                         int nextval = lo.getNumber().intValue() - 1;
    447                                                         lo.setValue((nextval > min) ? nextval : min);
    448                                                 }
    449                                                 if ((hi.getNumber().intValue() & 1) != odd_or_even) {
    450                                                         int nextval = hi.getNumber().intValue() - 1;
    451                                                         hi.setValue((nextval > min) ? nextval : min);
    452                                                 }
    453                                                 lo.setMinimum(min);
    454                                                 hi.setStepSize(2);
    455                                                 lo.setStepSize(2);
    456                                         }
    457                                 }
    458                         });
    459 
    460                         final TreeSet<String> names = createAutoCompletionInfo();
    461 
    462                         street = new AutoCompleteComboBox();
    463                         street.setPossibleItems(names);
    464                         street.setEditable(true);
    465                         street.setSelectedItem(null);
    466 
    467                         JFormattedTextField x;
    468                         x = ((JSpinner.DefaultEditor)clo.getEditor()).getTextField();
    469                         x.setColumns(5);
    470                         x = ((JSpinner.DefaultEditor)chi.getEditor()).getTextField();
    471                         x.setColumns(5);
    472                         addLabelled(tr("Highest number") + ": ",   chi);
    473                         addLabelled(tr("Lowest number") + ": ", clo);
    474                         addLabelled(tr("Interpolation") + ": ", step);
    475                         addLabelled(tr("Street name") + " (" + tr("Optional") + "): ", street);
    476                 }
    477 
    478                 private void addLabelled(String str, Component c) {
    479                         JLabel label = new JLabel(str);
    480                         add(label, GBC.std());
    481                         label.setLabelFor(c);
    482                         add(c, GBC.eol());
    483                 }
    484 
    485                 public int numberFrom() {
    486                         return lo.getNumber().intValue();
    487                 }
    488 
    489                 public int numberTo() {
    490                         return hi.getNumber().intValue();
    491                 }
    492 
    493                 public int stepSize() {
    494                         return (step.getSelectedItem() == tr("All")) ? 1 : 2;
    495                 }
    496 
    497                 public String streetName() {
    498                         Object selected = street.getSelectedItem();
    499                         if (selected == null) {
    500                                 return null;
    501                         } else {
    502                                 String name = selected.toString();
    503                                 if (name.length() == 0) {
    504                                         return null;
    505                                 } else {
    506                                         return name;
    507                                 }
    508                         }
    509                 }
     416                return (ndx * pdx + ndy * pdy)
     417                                / Math.sqrt((ndx * ndx + ndy * ndy) * (pdx * pdx + pdy * pdy));
    510418        }
    511419
     
    513421         * Generates a list of all visible names of highways in order to do
    514422         * autocompletion on the road name.
    515          */
    516         private TreeSet<String> createAutoCompletionInfo() {
     423         *
     424         * TODO: REMOVE this method here!
     425         */
     426        TreeSet<String> createAutoCompletionInfo() {
    517427                final TreeSet<String> names = new TreeSet<String>();
    518                 for (OsmPrimitive osm : Main.main.getCurrentDataSet().allNonDeletedPrimitives()) {
    519                         if (osm.getKeys() != null &&
    520                                         osm.keySet().contains("highway") &&
    521                                         osm.keySet().contains("name")) {
     428                for (OsmPrimitive osm : Main.main.getCurrentDataSet()
     429                                .allNonDeletedPrimitives()) {
     430                        if (osm.getKeys() != null && osm.keySet().contains("highway")
     431                                        && osm.keySet().contains("name")) {
    522432                                names.add(osm.get("name"));
    523433                        }
     
    553463                // screen coordinates rather than lat/lon, but it doesn't seem to
    554464                // make a great deal of difference at the scale of most terraces.
    555                 return new LatLon(a.getCoor().lat() * (1.0 - f) + b.getCoor().lat() * f,
    556                                 a.getCoor().lon() * (1.0 - f) + b.getCoor().lon() * f);
     465                return new LatLon(
     466                                a.getCoor().lat() * (1.0 - f) + b.getCoor().lat() * f, a
     467                                                .getCoor().lon()
     468                                                * (1.0 - f) + b.getCoor().lon() * f);
    557469        }
    558470}
Note: See TracChangeset for help on using the changeset viewer.