Ignore:
Timestamp:
2011-06-27T19:48:13+02:00 (13 years ago)
Author:
benshu
Message:
  • moved various things around to centrally handle exceptions (#josm6513)
  • primitives which were removed from the dataset are dropped when rebuilding the model a change (#josm6512)
  • the turnlanes plugin should now lie dormant (i.e. do nothing) unless its dialog is visible (#josm6512)
Location:
applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/GuiContainer.java

    r26154 r26192  
    2727    static final Color GREEN = new Color(66, 234, 108);
    2828   
     29    private static final GuiContainer EMPTY = new GuiContainer(ModelContainer.empty());
     30   
     31    public static GuiContainer empty() {
     32        return EMPTY;
     33    }
     34   
    2935    private final ModelContainer mc;
    3036   
     
    4652       
    4753        final LatLon originCoor = Main.getProjection().eastNorth2latlon(new EastNorth(origin.getX(), origin.getY()));
    48         final LatLon relCoor = Main.getProjection().eastNorth2latlon(new EastNorth(origin.getX() + 1, origin.getY() + 1));
     54        final LatLon relCoor = Main.getProjection().eastNorth2latlon(
     55                new EastNorth(origin.getX() + 1, origin.getY() + 1));
    4956       
    5057        // meters per source unit
     
    6572   
    6673    private static Point2D avgOrigin(List<Point2D> locs) {
     74        if (locs.isEmpty()) {
     75            return new Point2D.Double(0, 0);
     76        }
     77       
    6778        double x = 0;
    6879        double y = 0;
     
    143154   
    144155    public Rectangle2D getBounds() {
     156        if (isEmpty()) {
     157            return new Rectangle2D.Double(-1, -1, 2, 2);
     158        }
     159       
    145160        final List<Junction> primaries = new ArrayList<Junction>(mc.getPrimaryJunctions());
    146161        final List<Double> top = new ArrayList<Double>();
     
    178193        return junctions.values();
    179194    }
     195   
     196    public boolean isEmpty() {
     197        return mc.isEmpty();
     198    }
    180199}
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/JunctionPane.java

    r26182 r26192  
    55import java.awt.Graphics;
    66import java.awt.Graphics2D;
     7import java.awt.GridBagConstraints;
     8import java.awt.GridBagLayout;
     9import java.awt.Insets;
    710import java.awt.RenderingHints;
    811import java.awt.event.ActionEvent;
     
    2427import javax.swing.AbstractAction;
    2528import javax.swing.JComponent;
     29import javax.swing.JLabel;
    2630import javax.swing.KeyStroke;
     31
     32import org.openstreetmap.josm.plugins.turnlanes.model.UnexpectedDataException;
    2733
    2834class JunctionPane extends JComponent {
     
    142148    private GuiContainer container;
    143149   
     150    private final JLabel error = new JLabel("");
     151   
    144152    private int width = 0;
    145153    private int height = 0;
     
    159167        setJunction(container);
    160168       
     169        setLayout(new GridBagLayout());
     170        error.setOpaque(false);
     171        add(error, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
     172                new Insets(8, 8, 8, 8), 0, 0));
     173       
    161174        setFocusable(true);
    162175       
     
    250263        removeMouseMotionListener(mip);
    251264        removeMouseWheelListener(mip);
    252         interactives.clear();
    253         dragging = null;
     265        this.interactives.clear();
     266        this.dragging = null;
     267       
    254268        this.container = container;
    255        
    256         if (container == null) {
    257             this.state = null;
    258         } else {
    259             setState(new State.Dirty(new State.Default()));
    260            
    261             center();
    262            
    263             addMouseListener(mip);
    264             addMouseMotionListener(mip);
    265             addMouseWheelListener(mip);
    266         }
     269        center();
     270        setState(new State.Invalid(new State.Default()));
     271       
     272        addMouseListener(mip);
     273        addMouseMotionListener(mip);
     274        addMouseWheelListener(mip);
    267275    }
    268276   
     
    289297   
    290298    private void setState(State state) {
     299        error.setText("");
    291300       
    292301        if (state instanceof State.AllTurns) {
     
    294303            this.state = state;
    295304        } else if (state instanceof State.Invalid) {
    296             container = container.recalculate();
    297305            dirty = true;
    298306            setState(((State.Invalid) state).unwrap());
     307           
     308            try {
     309                final GuiContainer old = container;
     310               
     311                container = container.recalculate();
     312               
     313                if (old.isEmpty() != container.isEmpty()) {
     314                    center();
     315                }
     316            } catch (UnexpectedDataException e) {
     317                displayError(e);
     318            } catch (RuntimeException e) {
     319                displayError(e);
     320            }
    299321        } else if (state instanceof State.Dirty) {
    300322            dirty = true;
     
    305327       
    306328        repaint();
     329    }
     330   
     331    private void displayError(UnexpectedDataException e) {
     332        if (e.getKind() == UnexpectedDataException.Kind.MISSING_TAG
     333                && UnexpectedDataException.Kind.MISSING_TAG.format("lanes").equals(e.getMessage())) {
     334           
     335            error.setText("<html>The number of lanes is not specified for one or more roads;"
     336                    + " please add missing lanes tags.</html>");
     337        } else {
     338            displayError((RuntimeException) e);
     339        }
     340    }
     341   
     342    private void displayError(RuntimeException e) {
     343        error.setText("<html>An error occured while constructing the model."
     344                + " Please run the validator to make sure the data is consistent.<br><br>Error: " + e.getMessage()
     345                + "</html>");
    307346    }
    308347   
     
    344383        }
    345384       
    346         if (container == null) {
    347             super.paintComponent(g);
    348             return;
    349         }
    350        
    351385        if (dirty) {
    352386            paintPassive((Graphics2D) passive.getGraphics());
     
    359393        g2d.drawImage(passive, 0, 0, getWidth(), getHeight(), null);
    360394        g2d.drawImage(interactive, 0, 0, getWidth(), getHeight(), null);
     395       
     396        paintChildren(g);
    361397    }
    362398   
     
    447483   
    448484    void refresh() {
    449         if (state != null) {
    450             setState(new State.Invalid(state));
    451         }
     485        setState(new State.Invalid(state));
    452486    }
    453487}
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/gui/TurnLanesDialog.java

    r26182 r26192  
    1515import javax.swing.Action;
    1616import javax.swing.ButtonGroup;
    17 import javax.swing.JLabel;
    1817import javax.swing.JPanel;
    1918import javax.swing.JToggleButton;
     
    4039import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    4140import org.openstreetmap.josm.plugins.turnlanes.model.ModelContainer;
    42 import org.openstreetmap.josm.plugins.turnlanes.model.UnexpectedDataException;
    4341
    4442public class TurnLanesDialog extends ToggleDialog {
     
    5957            editing = true;
    6058            editButton.setSelected(true);
     59            refresh();
    6160        }
    6261    }
     
    137136    private static final String CARD_EDIT = "EDIT";
    138137    private static final String CARD_VALIDATE = "VALIDATE";
    139     private static final String CARD_ERROR = "ERROR";
    140138   
    141139    private final JPanel body = new JPanel();
    142     private final JunctionPane junctionPane = new JunctionPane(null);
    143     private final JLabel error = new JLabel();
     140    private final JunctionPane junctionPane = new JunctionPane(GuiContainer.empty());
    144141   
    145142    private final JToggleButton editButton = new JToggleButton(editAction);
     
    149146   
    150147    private boolean editing = true;
     148    private boolean wasShowing = false;
    151149   
    152150    public TurnLanesDialog() {
     
    175173                selected.addAll(newSelection);
    176174               
    177                 final Collection<OsmPrimitive> s = Collections.unmodifiableCollection(newSelection);
    178                 final List<Node> nodes = OsmPrimitive.getFilteredList(s, Node.class);
    179                 final List<Way> ways = OsmPrimitive.getFilteredList(s, Way.class);
    180                
    181                 if (nodes.isEmpty()) {
    182                     setJunction(null);
    183                     return;
    184                 }
    185                
    186                 try {
    187                     setJunction(ModelContainer.create(nodes, ways));
    188                 } catch (UnexpectedDataException e) {
    189                     displayError(e);
    190                     return;
    191                 } catch (RuntimeException e) {
    192                     displayError(e);
    193                     return;
    194                 }
     175                refresh();
    195176            }
    196177        });
     
    210191        body.add(junctionPane, CARD_EDIT);
    211192        body.add(new ValidationPanel(), CARD_VALIDATE);
    212         body.add(error, CARD_ERROR);
    213193       
    214194        editButton.doClick();
    215195    }
    216196   
    217     void displayError(UnexpectedDataException e) {
    218         if (editing) {
    219             if (e.getKind() == UnexpectedDataException.Kind.MISSING_TAG
    220                     && UnexpectedDataException.Kind.MISSING_TAG.format("lanes").equals(e.getMessage())) {
    221                
    222                 error.setText("<html>The number of lanes is not specified for one or more roads;"
    223                         + " please add missing lanes tags.</html>");
    224             } else {
    225                 displayError((RuntimeException) e);
    226             }
     197    @Override
     198    protected void stateChanged() {
     199        if (isShowing && !wasShowing) {
     200            refresh();
     201        }
     202        wasShowing = isShowing;
     203    }
     204   
     205    void refresh() {
     206        if (isShowing && editing) {
     207            final Collection<OsmPrimitive> s = Collections.unmodifiableCollection(selected);
     208            final List<Node> nodes = OsmPrimitive.getFilteredList(s, Node.class);
     209            final List<Way> ways = OsmPrimitive.getFilteredList(s, Way.class);
    227210           
    228             final CardLayout cl = (CardLayout) body.getLayout();
    229             cl.show(body, CARD_ERROR);
    230         }
    231     }
    232    
    233     void displayError(RuntimeException e) {
    234         if (editing) {
    235             e.printStackTrace();
     211            final ModelContainer mc = nodes.isEmpty() ? ModelContainer.empty() : ModelContainer
     212                    .createEmpty(nodes, ways);
    236213           
    237             error.setText("<html>An error occured while constructing the model."
    238                     + " Please run the validator to make sure the data is consistent.<br><br>Error: " + e.getMessage()
    239                     + "</html>");
    240            
    241             final CardLayout cl = (CardLayout) body.getLayout();
    242             cl.show(body, CARD_ERROR);
    243         }
    244     }
    245    
    246     void setJunction(ModelContainer mc) {
    247         if (mc != null && editing) {
    248214            junctionPane.setJunction(new GuiContainer(mc));
    249             final CardLayout cl = (CardLayout) body.getLayout();
    250             cl.show(body, CARD_EDIT);
    251215        }
    252216    }
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Junction.java

    r26154 r26192  
    1818        this.container = container;
    1919        this.node = n;
    20        
    21         container.register(this);
    22        
    23         if (isPrimary()) {
    24             // if turn data is invalid, this will force an exception now, not later during painting
    25             // getTurns(); TODO force this again
    26         }
    2720    }
    2821   
     
    8073       
    8174        throw new IllegalArgumentException("While there exists a road for the given way, the way neither "
    82             + "starts nor ends at the junction node.");
     75                + "starts nor ends at the junction node.");
    8376    }
    8477   
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Lane.java

    r26182 r26192  
    104104    private final Kind kind;
    105105   
     106    private Set<Turn> turns;
    106107    private double length = -1;
    107108   
     
    222223   
    223224    public Set<Turn> getTurns() {
     225        return turns;
     226    }
     227   
     228    public void remove() {
     229        if (!isExtra()) {
     230            throw new UnsupportedOperationException();
     231        }
     232       
     233        final GenericCommand cmd = new GenericCommand(getOutgoingJunction().getNode().getDataSet(), tr("Delete lane."));
     234       
     235        for (Turn t : getTurns()) {
     236            t.remove(cmd);
     237        }
     238       
     239        getOutgoingRoadEnd().removeLane(cmd, this);
     240       
     241        Main.main.undoRedo.add(cmd);
     242    }
     243   
     244    void initialize() {
    224245        final Set<Turn> turns = Turn.load(getContainer(), Constants.TURN_ROLE_FROM, getOutgoingRoadEnd().getWay());
    225246       
     
    233254        }
    234255       
    235         return turns;
    236     }
    237    
    238     public void remove() {
    239         if (!isExtra()) {
    240             throw new UnsupportedOperationException();
    241         }
    242        
    243         final GenericCommand cmd = new GenericCommand(getOutgoingJunction().getNode().getDataSet(), tr("Delete lane."));
    244        
    245         for (Turn t : getTurns()) {
    246             t.remove(cmd);
    247         }
    248        
    249         getOutgoingRoadEnd().removeLane(cmd, this);
    250        
    251         Main.main.undoRedo.add(cmd);
     256        this.turns = Collections.unmodifiableSet(turns);
    252257    }
    253258}
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/ModelContainer.java

    r26182 r26192  
    22
    33import java.util.ArrayList;
     4import java.util.Collection;
    45import java.util.Collections;
    56import java.util.HashMap;
    67import java.util.HashSet;
     8import java.util.Iterator;
    79import java.util.List;
    810import java.util.Map;
     
    1820
    1921public class ModelContainer {
     22    private static final ModelContainer EMPTY = new ModelContainer(Collections.<Node> emptySet(), Collections
     23            .<Way> emptySet(), false);
     24   
    2025    public static ModelContainer create(Iterable<Node> primaryNodes, Iterable<Way> primaryWays) {
    21         final Set<Node> closedNodes = new HashSet<Node>(CollectionUtils.toList(primaryNodes));
    22         final Set<Way> closedWays = new HashSet<Way>(CollectionUtils.toList(primaryWays));
    23        
    24         close(closedNodes, closedWays);
    25        
    26         return new ModelContainer(closedNodes, closedWays);
     26        return new ModelContainer(new HashSet<Node>(CollectionUtils.toList(primaryNodes)), new HashSet<Way>(
     27                CollectionUtils.toList(primaryWays)), false);
     28    }
     29   
     30    public static ModelContainer createEmpty(Iterable<Node> primaryNodes, Iterable<Way> primaryWays) {
     31        return new ModelContainer(new HashSet<Node>(CollectionUtils.toList(primaryNodes)), new HashSet<Way>(
     32                CollectionUtils.toList(primaryWays)), true);
     33    }
     34   
     35    public static ModelContainer empty() {
     36        return EMPTY;
    2737    }
    2838   
     
    4151                }
    4252               
    43                 for (Way w : new ArrayList<Way>(closedWays) ) {
     53                for (Way w : new ArrayList<Way>(closedWays)) {
    4454                    closed &= close(closedNodes, closedWays, w, Constants.TURN_ROLE_VIA);
    4555                }
     
    90100    }
    91101   
     102    private static <E extends OsmPrimitive, C extends Collection<E>> C filterUsables(C collection) {
     103        final Iterator<E> it = collection.iterator();
     104       
     105        while (it.hasNext()) {
     106            final E e = it.next();
     107           
     108            if (e.getDataSet() == null || !e.isUsable()) {
     109                it.remove();
     110            }
     111        }
     112       
     113        return collection;
     114    }
     115   
    92116    private final Map<Node, Junction> junctions = new HashMap<Node, Junction>();
    93117    private final Map<Way, Road> roads = new HashMap<Way, Road>();
     
    96120    private final Set<Way> primaryWays;
    97121   
    98     private ModelContainer(Set<Node> primaryNodes, Set<Way> primaryWays) {
    99         this.primaryNodes = Collections.unmodifiableSet(new HashSet<Node>(primaryNodes));
    100         this.primaryWays = Collections.unmodifiableSet(new HashSet<Way>(primaryWays));
    101        
    102         final Set<Pair<Way, Junction>> ws = new HashSet<Pair<Way, Junction>>();
     122    private final boolean empty;
     123   
     124    private ModelContainer(Set<Node> primaryNodes, Set<Way> primaryWays, boolean empty) {
     125        if (empty) {
     126            this.primaryNodes = Collections.unmodifiableSet(new HashSet<Node>(primaryNodes));
     127            this.primaryWays = Collections.unmodifiableSet(new HashSet<Way>(primaryWays));
     128            this.empty = true;
     129        } else {
     130            final Set<Node> closedNodes = filterUsables(new HashSet<Node>(primaryNodes));
     131            final Set<Way> closedWays = filterUsables(new HashSet<Way>(primaryWays));
     132           
     133            close(closedNodes, closedWays);
     134           
     135            this.primaryNodes = Collections.unmodifiableSet(closedNodes);
     136            this.primaryWays = Collections.unmodifiableSet(closedWays);
     137           
     138            for (Pair<Way, Junction> w : createPrimaryJunctions()) {
     139                if (!this.primaryWays.contains(w.a)) {
     140                    addRoad(new Road(this, w.a, w.b));
     141                }
     142            }
     143           
     144            for (Route r : Utils.orderWays(this.primaryWays, this.primaryNodes)) {
     145                addRoad(new Road(this, r));
     146            }
     147           
     148            for (Road r : roads.values()) {
     149                r.initialize();
     150            }
     151           
     152            this.empty = junctions.isEmpty();
     153        }
     154    }
     155   
     156    private Set<Pair<Way, Junction>> createPrimaryJunctions() {
     157        final Set<Pair<Way, Junction>> roads = new HashSet<Pair<Way, Junction>>();
     158       
    103159        for (Node n : primaryNodes) {
    104             final Junction j = getOrCreateJunction(n);
    105            
     160            final List<Way> ws = new ArrayList<Way>();
    106161            for (Way w : Utils.filterRoads(n.getReferrers())) {
    107162                if (w.isFirstLastNode(n)) {
    108                     ws.add(new Pair<Way, Junction>(w, j));
    109                 }
    110             }
    111         }
    112        
    113         final List<Route> rs = Utils.orderWays(primaryWays, primaryNodes);
    114         for (Route r : rs) {
    115             addRoad(new Road(this, r));
    116         }
    117        
    118         for (Pair<Way, Junction> w : ws) {
    119             if (!primaryWays.contains(w.a)) {
    120                 addRoad(new Road(this, w.a, w.b));
    121             }
    122         }
     163                    ws.add(w);
     164                }
     165            }
     166           
     167            if (ws.size() > 1) {
     168                final Junction j = register(new Junction(this, n));
     169                for (Way w : ws) {
     170                    roads.add(new Pair<Way, Junction>(w, j));
     171                }
     172            }
     173        }
     174       
     175        return roads;
    123176    }
    124177   
     
    130183        }
    131184       
    132         return new Junction(this, n);
     185        return register(new Junction(this, n));
    133186    }
    134187   
     
    161214            if (oldRoad != null) {
    162215                if (mergedA == null) {
    163                     final Road mergedRoad = mergeRoads(oldRoad, newRoad);
    164                     addRoad(mergedRoad, oldRoad, newRoad);
     216                    addRoad(mergeRoads(oldRoad, newRoad), oldRoad, newRoad);
    165217                } else if (!oldRoad.equals(mergedA) && !oldRoad.equals(mergedB)) {
    166218                    throw new RuntimeException("A road can't be connected to more than two junctions.");
     
    198250    }
    199251   
    200     void register(Junction j) {
     252    private Junction register(Junction j) {
    201253        if (junctions.put(j.getNode(), j) != null) {
    202254            throw new IllegalStateException();
    203255        }
     256       
     257        return j;
    204258    }
    205259   
    206260    public Set<Junction> getPrimaryJunctions() {
     261        if (empty) {
     262            return Collections.emptySet();
     263        }
     264       
    207265        final Set<Junction> pjs = new HashSet<Junction>();
    208        
    209266        for (Node n : primaryNodes) {
    210             pjs.add(getOrCreateJunction(n));
    211         }
    212        
     267            pjs.add(getJunction(n));
     268        }
    213269        return pjs;
    214270    }
    215271   
    216272    public Set<Road> getPrimaryRoads() {
     273        if (empty) {
     274            return Collections.emptySet();
     275        }
     276       
    217277        final Set<Road> prs = new HashSet<Road>();
    218        
    219278        for (Way w : primaryWays) {
    220279            prs.add(roads.get(w));
    221280        }
    222        
    223281        return prs;
    224282    }
    225283   
    226284    public ModelContainer recalculate() {
    227         return new ModelContainer(primaryNodes, primaryWays);
     285        return new ModelContainer(primaryNodes, primaryWays, false);
    228286    }
    229287   
     
    235293        return primaryWays.contains(r.getRoute().getFirstSegment().getWay());
    236294    }
     295   
     296    public boolean isEmpty() {
     297        return empty;
     298    }
    237299}
  • applications/editors/josm/plugins/turnlanes/src/org/openstreetmap/josm/plugins/turnlanes/model/Road.java

    r26182 r26192  
    66import java.util.ArrayList;
    77import java.util.Arrays;
     8import java.util.Collections;
    89import java.util.List;
    910import java.util.Set;
     
    3334       
    3435        private final List<Lane> lanes;
     36        private Set<Turn> turns;
    3537       
    3638        private End(boolean from, Junction junction, Relation lengthsLeft, Relation lengthsRight) {
     
    8688         */
    8789        public Set<Turn> getTurns() {
    88             return Turn.load(getContainer(), Constants.TURN_ROLE_TO, getWay());
     90            return turns;
    8991        }
    9092       
     
    260262                    && bRel.get(Constants.LENGTHS_KEY_LENGTHS_RIGHT) == null) {
    261263                bRel.setDeleted(true);
     264            }
     265        }
     266       
     267        void initialize() {
     268            this.turns = Collections.unmodifiableSet(Turn.load(getContainer(), Constants.TURN_ROLE_TO, getWay()));
     269           
     270            for (Lane l : lanes) {
     271                l.initialize();
    262272            }
    263273        }
     
    394404        return getContainer().isPrimary(this);
    395405    }
     406   
     407    void initialize() {
     408        fromEnd.initialize();
     409        toEnd.initialize();
     410    }
    396411}
Note: See TracChangeset for help on using the changeset viewer.