Changeset 21094 in osm for applications/editors/josm
- Timestamp:
- 2010-05-02T22:39:56+02:00 (15 years ago)
- Location:
- applications/editors/josm/plugins/terracer/src/terracer
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputDialog.java
r21022 r21094 18 18 import java.awt.GridBagLayout; 19 19 import java.awt.GridLayout; 20 import java.awt.event.ActionEvent; 21 20 22 import java.util.TreeSet; 21 23 … … 23 25 import javax.swing.JButton; 24 26 import javax.swing.JCheckBox; 25 import javax.swing.JDialog;26 27 import javax.swing.JLabel; 27 28 import javax.swing.JOptionPane; … … 34 35 import org.openstreetmap.josm.data.osm.OsmPrimitive; 35 36 import org.openstreetmap.josm.data.osm.Way; 36 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox; 37 import org.openstreetmap.josm.gui.ExtendedDialog; 38 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox; 37 39 import org.openstreetmap.josm.tools.GBC; 38 40 … … 48 50 * 49 51 */ 50 public class HouseNumberInputDialog extends JDialog {52 public class HouseNumberInputDialog extends ExtendedDialog { 51 53 /* 52 54 final static String MIN_NUMBER = "plugin.terracer.lowest_number"; … … 64 66 private Container jContentPane; 65 67 private JPanel inputPanel; 66 private JPanel buttonPanel;67 68 private JLabel loLabel; 68 69 JTextField lo; … … 74 75 JTextField segments; 75 76 JTextArea messageLabel; 76 JButton okButton;77 JButton cancelButton;78 77 private JLabel interpolationLabel; 79 78 Choice interpolation; … … 81 80 JCheckBox deleteOutlineCheckBox; 82 81 82 HouseNumberInputHandler inputHandler; 83 83 84 /** 84 85 * @param street If street is not null, we assume, the name of the street to be fixed … … 86 87 * @param relationExists If the buildings can be added to an existing relation or not. 87 88 */ 88 public HouseNumberInputDialog(Way street, boolean relationExists) { 89 super(JOptionPane.getFrameForComponent(Main.parent)); 89 public HouseNumberInputDialog(HouseNumberInputHandler handler, Way street, boolean relationExists) { 90 super(Main.parent, 91 tr("Terrace a house"), 92 new String[] { tr("OK"), tr("Cancel")}, 93 true 94 ); 95 this.inputHandler = handler; 90 96 this.street = street; 91 97 this.relationExists = relationExists; 98 handler.dialog = this; 99 JPanel content = getInputPanel(); 100 setContent(content); 101 setButtonIcons(new String[] {"ok.png", "cancel.png" }); 102 getJContentPane(); 92 103 initialize(); 93 } 94 95 /** 104 setupDialog(); 105 setVisible(true); 106 } 107 108 /** 96 109 * This method initializes this 97 110 * … … 99 112 */ 100 113 private void initialize() { 101 this.setTitle(tr("Terrace a house")); 102 getJContentPane(); 103 SwingUtilities.invokeLater(new Runnable() { public void run() { lo.requestFocus(); } } ); 104 this.pack(); 105 this.setLocationRelativeTo(Main.parent); 106 } 107 114 this.lo.addFocusListener(this.inputHandler); 115 this.hi.addFocusListener(this.inputHandler); 116 this.segments.addFocusListener(this.inputHandler); 117 this.interpolation.addItemListener(this.inputHandler); 118 } 119 108 120 /** 109 121 * This method initializes jContentPane … … 113 125 private Container getJContentPane() { 114 126 if (jContentPane == null) { 127 115 128 messageLabel = new JTextArea(); 116 129 messageLabel.setText(DEFAULT_MESSAGE); … … 121 134 messageLabel.setBackground(new Color(238, 238, 238)); 122 135 messageLabel.setEditable(false); 136 123 137 jContentPane = this.getContentPane(); 124 jContentPane.setLayout(new BoxLayout(jContentPane, 125 BoxLayout.Y_AXIS)); 138 jContentPane.setLayout(new BoxLayout(jContentPane, BoxLayout.Y_AXIS)); 126 139 jContentPane.add(messageLabel, jContentPane); 127 140 jContentPane.add(getInputPanel(), jContentPane); 128 jContentPane.add(getButtonPanel(), jContentPane);129 141 } 130 142 return jContentPane; … … 176 188 } 177 189 178 /** 179 * This method initializes buttonPanel 180 * 181 * @return javax.swing.JPanel 182 */ 183 private JPanel getButtonPanel() { 184 if (buttonPanel == null) { 185 buttonPanel = new JPanel(); 186 buttonPanel.setLayout(new FlowLayout()); 187 buttonPanel.add(getOkButton(), null); 188 buttonPanel.add(getCancelButton(), null); 189 } 190 return buttonPanel; 190 /** 191 * Overrides the default actions. Will not close the window when upload trace is clicked 192 */ 193 @Override protected void buttonAction(final ActionEvent evt) { 194 String a = evt.getActionCommand(); 195 this.inputHandler.actionPerformed(evt); 191 196 } 192 197 … … 251 256 252 257 /** 253 * This method initializes okButton254 *255 * @return javax.swing.JButton256 */257 private JButton getOkButton() {258 if (okButton == null) {259 okButton = new JButton();260 okButton.setText(tr("OK"));261 okButton.setName("OK");262 }263 return okButton;264 }265 266 /**267 * This method initializes cancelButton268 *269 * @return javax.swing.JButton270 */271 private JButton getCancelButton() {272 if (cancelButton == null) {273 cancelButton = new JButton();274 cancelButton.setText(tr("Cancel"));275 cancelButton.setName("CANCEL");276 }277 return cancelButton;278 }279 280 /**281 258 * This method initializes interpolation 282 259 * … … 290 267 } 291 268 return interpolation; 292 }293 294 /**295 * Registers the handler as a listener to all relevant events.296 *297 * @param handler the handler298 */299 public void addHandler(HouseNumberInputHandler handler) {300 this.hi.addActionListener(handler);301 this.hi.addFocusListener(handler);302 303 this.lo.addActionListener(handler);304 this.lo.addFocusListener(handler);305 306 this.segments.addActionListener(handler);307 this.segments.addFocusListener(handler);308 309 this.okButton.addActionListener(handler);310 this.cancelButton.addActionListener(handler);311 312 this.interpolation.addItemListener(handler);313 314 269 } 315 270 -
applications/editors/josm/plugins/terracer/src/terracer/HouseNumberInputHandler.java
r19658 r21094 11 11 12 12 import java.awt.Color; 13 import java.awt.Component; 14 import java.awt.Container; 13 15 import java.awt.event.ActionEvent; 14 16 import java.awt.event.ActionListener; … … 20 22 import javax.swing.JButton; 21 23 import javax.swing.JTextField; 22 import javax.swing.event.ChangeEvent; 23 import javax.swing.event.ChangeListener; 24 import javax.swing.JOptionPane; 24 25 25 26 import org.openstreetmap.josm.Main; 26 27 import org.openstreetmap.josm.data.osm.Way; 27 28 import org.openstreetmap.josm.data.osm.Relation; 29 import org.openstreetmap.josm.actions.JosmAction; 28 30 29 31 /** … … 37 39 * @author casualwalker 38 40 */ 39 public class HouseNumberInputHandler implements ChangeListener, ItemListener, 40 ActionListener, FocusListener { 41 41 public class HouseNumberInputHandler extends JosmAction implements ActionListener, FocusListener, ItemListener { 42 42 private TerracerAction terracerAction; 43 43 private Way outline, street; 44 44 private Relation associatedStreet; 45 p rivateHouseNumberInputDialog dialog;45 public HouseNumberInputDialog dialog; 46 46 47 47 /** … … 61 61 this.street = street; 62 62 this.associatedStreet = associatedStreet; 63 dialog = new HouseNumberInputDialog(street, associatedStreet != null); 64 dialog.addHandler(this); 65 66 dialog.setVisible(true); 67 dialog.setTitle(title); 68 69 } 70 63 64 // This dialog is started modal 65 this.dialog = new HouseNumberInputDialog(this, street, associatedStreet != null); 66 67 // We're done 68 } 69 70 /** 71 * Find a button with a certain caption. 72 * Loops recursively through all objects to find all buttons. 73 * Function returns on the first match. 74 * 75 * @param root A container object that is recursively searched for other containers or buttons 76 * @param caption The caption of the button that is being searched 77 * 78 * @return The first button that matches the caption or null if not found 79 */ 80 private static JButton getButton(Container root, String caption) { 81 Component children[] = root.getComponents(); 82 for (Component child : children) { 83 JButton b; 84 if (child instanceof JButton) { 85 b = (JButton) child; 86 if (caption.equals(b.getText())) return b; 87 } else if (child instanceof Container) { 88 b = getButton((Container)child, caption); 89 if (b != null) return b; 90 } 91 } 92 return null; 93 } 94 71 95 /** 72 96 * Validate the current input fields. … … 76 100 * Should be triggered each time the input changes. 77 101 */ 78 private voidvalidateInput() {102 private boolean validateInput() { 79 103 boolean isOk = true; 80 104 StringBuffer message = new StringBuffer(); … … 83 107 isOk = isOk && checkSegmentsFromHousenumber(message); 84 108 isOk = isOk && checkSegments(message); 85 isOk = isOk 86 && checkNumberStringField(dialog.lo, tr("Lowest number"), 87 message); 109 110 // Allow non numeric characters for the low number as long as there is no high number of the segmentcount is 1 111 if (dialog.hi.getText().length() > 0 | segments() > 1) { 112 isOk = isOk 113 && checkNumberStringField(dialog.lo, tr("Lowest number"), 114 message); 115 } 88 116 isOk = isOk 89 117 && checkNumberStringField(dialog.hi, tr("Highest number"), … … 94 122 95 123 if (isOk) { 96 dialog.okButton.setEnabled(true); 124 JButton okButton = getButton(dialog, "OK"); 125 if (okButton != null) 126 okButton.setEnabled(true); 127 128 // For some reason the messageLabel doesn't want to show up 97 129 dialog.messageLabel.setForeground(Color.black); 98 dialog.messageLabel 99 .setText(tr(HouseNumberInputDialog.DEFAULT_MESSAGE)); 100 130 dialog.messageLabel.setText(tr(HouseNumberInputDialog.DEFAULT_MESSAGE)); 131 return true; 101 132 } else { 102 dialog.okButton.setEnabled(false); 103 dialog.messageLabel.setForeground(Color.red); 104 dialog.messageLabel.setText(message.toString()); 133 JButton okButton = getButton(dialog, "OK"); 134 if (okButton != null) 135 okButton.setEnabled(false); 136 137 // For some reason the messageLabel doesn't want to show up, so a MessageDialog is shown instead. Someone more knowledgeable might fix this. 138 dialog.messageLabel.setForeground(Color.red); 139 dialog.messageLabel.setText(message.toString()); 140 JOptionPane.showMessageDialog(null, message.toString(), tr("Error"), JOptionPane.ERROR_MESSAGE); 141 142 return false; 105 143 } 106 144 } … … 119 157 if (numberFrom().intValue() > numberTo().intValue()) { 120 158 appendMessageNewLine(message); 121 message 122 .append(tr("Lowest housenumber cannot be higher than highest housenumber")); 159 message.append(tr("Lowest housenumber cannot be higher than highest housenumber")); 123 160 return false; 124 161 } … … 147 184 if (segments % stepSize() != 0) { 148 185 appendMessageNewLine(message); 149 message 150 .append(tr("Housenumbers do not match odd/even setting")); 186 message.append(tr("Housenumbers do not match odd/even setting")); 151 187 return false; 152 188 } … … 222 258 223 259 /* (non-Javadoc) 224 * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)225 */226 public void stateChanged(ChangeEvent e) {227 validateInput();228 229 }230 231 /* (non-Javadoc)232 260 * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent) 261 * Called when the user selects from a pulldown selection 233 262 */ 234 263 public void itemStateChanged(ItemEvent e) { … … 240 269 */ 241 270 public void actionPerformed(final ActionEvent e) { 242 243 271 // OK or Cancel button-actions 244 272 if (e.getSource() instanceof JButton) { 245 273 JButton button = (JButton) e.getSource(); 246 if ("OK".equals(button.getName())) { 247 saveValues(); 248 terracerAction.terraceBuilding( 249 outline, 250 street, 251 associatedStreet, 252 segments(), 253 numberFrom(), 254 numberTo(), 255 stepSize(), 256 streetName(), 257 doHandleRelation(), 258 doDeleteOutline()); 259 260 this.dialog.dispose(); 261 } else if ("CANCEL".equals(button.getName())) { 274 if ("OK".equals(button.getActionCommand()) & button.isEnabled()) { 275 if (validateInput()) { 276 saveValues(); 277 278 terracerAction.terraceBuilding( 279 outline, 280 street, 281 associatedStreet, 282 segments(), 283 dialog.lo.getText(), 284 dialog.hi.getText(), 285 stepSize(), 286 streetName(), 287 doHandleRelation(), 288 doDeleteOutline()); 289 290 this.dialog.dispose(); 291 } 292 } else if ("Cancel".equals(button.getActionCommand())) { 262 293 this.dialog.dispose(); 263 294 } 264 295 } else { 265 // anything else is a change in the input296 // Anything else is a change in the input (we don't get here though) 266 297 validateInput(); 267 298 } 268 269 299 } 270 300 … … 327 357 if (street != null) 328 358 return null; 359 329 360 Object selected = dialog.streetComboBox.getSelectedItem(); 330 361 if (selected == null) { … … 345 376 */ 346 377 public boolean doHandleRelation() { 347 return dialog.handleRelationCheckBox.isSelected(); 378 if (this.dialog == null) { 379 JOptionPane.showMessageDialog(null, "dialog", "alert", JOptionPane.ERROR_MESSAGE); 380 } 381 if (this.dialog.handleRelationCheckBox == null) { 382 JOptionPane.showMessageDialog(null, "checkbox", "alert", JOptionPane.ERROR_MESSAGE); 383 return true; 384 } else { 385 return this.dialog.handleRelationCheckBox.isSelected(); 386 } 348 387 } 349 388 … … 359 398 */ 360 399 public void focusGained(FocusEvent e) { 361 validateInput(); 400 // Empty, but placeholder is required 362 401 } 363 402 … … 366 405 */ 367 406 public void focusLost(FocusEvent e) { 407 if (e.getOppositeComponent() == null) 408 return; 409 368 410 validateInput(); 369 411 } -
applications/editors/josm/plugins/terracer/src/terracer/TerracerAction.java
r20084 r21094 25 25 import org.openstreetmap.josm.actions.JosmAction; 26 26 import org.openstreetmap.josm.command.AddCommand; 27 import org.openstreetmap.josm.command.ChangePropertyCommand; 27 28 import org.openstreetmap.josm.command.ChangeCommand; 28 29 import org.openstreetmap.josm.command.Command; … … 57 58 // repeated terraces. this is the easiest, but not necessarily nicest, way. 58 59 // private static String lastSelectedValue = ""; 59 60 61 Collection<Command> commands; 62 60 63 public TerracerAction() { 61 64 super(tr("Terrace a building"), "terrace", … … 149 152 } 150 153 154 public Integer getNumber(String number) { 155 try { 156 return Integer.parseInt(number); 157 } catch (NumberFormatException ex) { 158 return null; 159 } 160 } 161 151 162 /** 152 163 * Terraces a single, closed, quadrilateral way. … … 159 170 * @param outline The closed, quadrilateral way to terrace. 160 171 * @param street The street, the buildings belong to (may be null) 172 * @param associatedStreet 173 * @param From 174 * @param To 175 * @param streetName the name of a street (may be null). Used if not null and street is null. 161 176 * @param handleRelations If the user likes to add a relation or extend an existing relation 162 177 * @param deleteOutline If the outline way should be deleted, when done 163 178 */ 164 public void terraceBuilding(Way outline, Way street, Relation associatedStreet, Integer segments, Integer from, 165 Integer to, int step, String streetName, boolean handleRelations, boolean deleteOutline) { 179 public void terraceBuilding(Way outline, 180 Way street, 181 Relation associatedStreet, 182 Integer segments, 183 String From, 184 String To, 185 int step, 186 String streetName, 187 boolean handleRelations, 188 boolean deleteOutline) { 166 189 final int nb; 190 191 Integer to, from; 192 to = getNumber(To); 193 from = getNumber(From); 167 194 if (to != null && from != null) { 168 195 nb = 1 + (to.intValue() - from.intValue()) / step; … … 176 203 + " from " + from + " to " + to + " step " + step); 177 204 } 178 205 179 206 // now find which is the longest side connecting the first node 180 207 Pair<Way, Way> interp = findFrontAndBack(outline); … … 186 213 Node[][] new_nodes = new Node[2][nb + 1]; 187 214 188 Collection<Command>commands = new LinkedList<Command>();215 this.commands = new LinkedList<Command>(); 189 216 Collection<Way> ways = new LinkedList<Way>(); 190 217 191 // create intermediate nodes by interpolating. 192 for (int i = 0; i <= nb; ++i) { 193 new_nodes[0][i] = interpolateAlong(interp.a, frontLength * i / nb); 194 new_nodes[1][i] = interpolateAlong(interp.b, backLength * i / nb); 195 commands.add(new AddCommand(new_nodes[0][i])); 196 commands.add(new AddCommand(new_nodes[1][i])); 197 } 198 199 // assemble new quadrilateral, closed ways 200 for (int i = 0; i < nb; ++i) { 201 Way terr = new Way(); 202 // Using Way.nodes.add rather than Way.addNode because the latter 203 // doesn't 204 // exist in older versions of JOSM. 205 terr.addNode(new_nodes[0][i]); 206 terr.addNode(new_nodes[0][i + 1]); 207 terr.addNode(new_nodes[1][i + 1]); 208 terr.addNode(new_nodes[1][i]); 209 terr.addNode(new_nodes[0][i]); 210 211 // add the tags of the outline to each building (e.g. source=*) 212 TagCollection.from(outline).applyTo(terr); 213 214 if (from != null) { 215 // only, if the user has specified house numbers 216 terr.put("addr:housenumber", "" + (from + i * step)); 217 } 218 terr.put("building", "yes"); 219 if (street != null) { 220 terr.put("addr:street", street.get("name")); 221 } else if (streetName != null) { 222 terr.put("addr:street", streetName); 223 } 224 ways.add(terr); 225 commands.add(new AddCommand(terr)); 226 } 227 228 if (handleRelations) { // create a new relation or merge with existing 229 if (associatedStreet == null) { // create a new relation 230 associatedStreet = new Relation(); 231 associatedStreet.put("type", "associatedStreet"); 232 if (street != null) { // a street was part of the selection 233 associatedStreet.put("name", street.get("name")); 234 associatedStreet.addMember(new RelationMember("street", street)); 235 } else { 236 associatedStreet.put("name", streetName); 237 } 238 for (Way w : ways) { 239 associatedStreet.addMember(new RelationMember("house", w)); 240 } 241 commands.add(new AddCommand(associatedStreet)); 242 } 243 else { // relation exists already - add new members 244 Relation newAssociatedStreet = new Relation(associatedStreet); 245 for (Way w : ways) { 246 newAssociatedStreet.addMember(new RelationMember("house", w)); 247 } 248 commands.add(new ChangeCommand(associatedStreet, newAssociatedStreet)); 249 } 250 } 251 252 if (deleteOutline) { 253 commands.add(DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(outline), true, true)); 254 } 255 256 Main.main.undoRedo.add(new SequenceCommand(tr("Terrace"), commands)); 257 Main.main.getCurrentDataSet().setSelected(ways); 218 if (nb > 1) { 219 // create intermediate nodes by interpolating. 220 for (int i = 0; i <= nb; ++i) { 221 new_nodes[0][i] = interpolateAlong(interp.a, frontLength * i / nb); 222 new_nodes[1][i] = interpolateAlong(interp.b, backLength * i / nb); 223 this.commands.add(new AddCommand(new_nodes[0][i])); 224 this.commands.add(new AddCommand(new_nodes[1][i])); 225 } 226 227 // assemble new quadrilateral, closed ways 228 for (int i = 0; i < nb; ++i) { 229 Way terr = new Way(); 230 // Using Way.nodes.add rather than Way.addNode because the latter 231 // doesn't 232 // exist in older versions of JOSM. 233 terr.addNode(new_nodes[0][i]); 234 terr.addNode(new_nodes[0][i + 1]); 235 terr.addNode(new_nodes[1][i + 1]); 236 terr.addNode(new_nodes[1][i]); 237 terr.addNode(new_nodes[0][i]); 238 239 // add the tags of the outline to each building (e.g. source=*) 240 TagCollection.from(outline).applyTo(terr); 241 242 String number = Integer.toString(from + i * step); 243 244 terr = addressBuilding(terr, street, streetName, number); 245 246 ways.add(terr); 247 this.commands.add(new AddCommand(terr)); 248 } 249 250 if (deleteOutline) { 251 this.commands.add(DeleteCommand.delete(Main.main.getEditLayer(), Collections.singleton(outline), true, true)); 252 } 253 } else { 254 // Single building, just add the address details 255 Way newOutline; 256 newOutline = addressBuilding(outline, street, streetName, From); 257 ways.add(newOutline); 258 this.commands.add(new ChangeCommand(outline, newOutline)); 259 } 260 261 if (handleRelations) { // create a new relation or merge with existing 262 if (associatedStreet == null) { // create a new relation 263 associatedStreet = new Relation(); 264 associatedStreet.put("type", "associatedStreet"); 265 if (street != null) { // a street was part of the selection 266 associatedStreet.put("name", street.get("name")); 267 associatedStreet.addMember(new RelationMember("street", street)); 268 } else { 269 associatedStreet.put("name", streetName); 270 } 271 for (Way w : ways) { 272 associatedStreet.addMember(new RelationMember("house", w)); 273 } 274 this.commands.add(new AddCommand(associatedStreet)); 275 } 276 else { // relation exists already - add new members 277 Relation newAssociatedStreet = new Relation(associatedStreet); 278 for (Way w : ways) { 279 newAssociatedStreet.addMember(new RelationMember("house", w)); 280 } 281 this.commands.add(new ChangeCommand(associatedStreet, newAssociatedStreet)); 282 } 283 } 284 Main.main.undoRedo.add(new SequenceCommand(tr("Terrace"), commands)); 285 if (nb > 1) { 286 // Select the new building outlines (for quick reversing) 287 Main.main.getCurrentDataSet().setSelected(ways); 288 } else if (street != null) { 289 // Select the way (for quick selection of a new house (with the same way)) 290 Main.main.getCurrentDataSet().setSelected(street); 291 } 292 } 293 294 /** 295 * Adds address details to a single building 296 * 297 * @param outline The closed, quadrilateral way to add the address to. 298 * @param street The street, the buildings belong to (may be null) 299 * @param streetName the name of a street (may be null). Used if not null and street is null. 300 * @param number The house number 301 * @return the way with added address details 302 */ 303 private Way addressBuilding(Way outline, Way street, String streetName, String number) { 304 Way changedOutline = outline; 305 if (number != null) { 306 // only, if the user has specified house numbers 307 this.commands.add(new ChangePropertyCommand(changedOutline, "addr:housenumber", number)); 308 } 309 changedOutline.put("building", "yes"); 310 if (street != null) { 311 this.commands.add(new ChangePropertyCommand(changedOutline, "addr:street", street.get("name"))); 312 } else if (streetName != null) { 313 this.commands.add(new ChangePropertyCommand(changedOutline, "addr:street", streetName)); 314 } 315 return changedOutline; 258 316 } 259 317
Note:
See TracChangeset
for help on using the changeset viewer.